最近在haps上驗證一個新的芯片,記錄一下memset訪問出錯的問題。
在沒開mmu和cache的情況下,對全局變量指針進行memset清零操作,發現每次都會出現異常。最后發現是沒開mmu導致出現了數據非對齊訪問導致報錯。
排查EC區域發現是0x25,產生了非對齊訪問。
下面是非對齊訪問的排查邏輯:
在ARM Cortex-A35處理器(ARMv8-A架構)上,可以通過檢查以下狀態寄存器來判斷是否發生了非對齊內存訪問異常:
1.?異常狀態寄存器 (ESR_ELx)
這是判斷異常類型的關鍵寄存器:
EC 字段?(Exception Class, 位[31:26]):
數據中止異常:
0b100101
?(0x25)
ISS 字段?(Instruction Specific Syndrome, 位[24:0]):
對齊錯誤:
DFSC=0b100001
?(0x21)
判斷步驟:
# 讀取ESR_EL1(假設異常發生在EL1)
set esr_value [readreg ESR_EL1]# 提取EC字段(高6位)
set ec [expr ($esr_value >> 26) & 0x3F]# 提取DFSC字段(低6位)
set dfsc [expr $esr_value & 0x3F]# 檢查是否是非對齊數據訪問異常
if {$ec == 0x25 && $dfsc == 0x21} {echo "檢測到非對齊內存訪問異常!"
}
2.?故障地址寄存器 (FAR_ELx)
記錄觸發異常的內存地址:
# 讀取觸發異常的地址
set fault_addr [readreg FAR_EL1]
echo "異常訪問地址:0x[format %x $fault_addr]"
完整調試示例腳本
# 連接到目標
connect -p jtag -c cortex-a35# 設置斷點
break vector_data# 運行程序
run# 異常發生后檢查狀態
stop# 讀取關鍵寄存器
set esr [readreg ESR_EL1]
set far [readreg FAR_EL1]
set pc [readreg PC]# 解析ESR
set ec [expr ($esr >> 26) & 0x3F]
set dfsc [expr $esr & 0x3F]# 輸出診斷信息
echo "-------------------------"
echo "異常診斷信息:"
echo "PC = 0x[format %x $pc]"
echo "FAR = 0x[format %x $far]"
echo "ESR_EL1 = 0x[format %x $esr]"
echo "EC = 0x[format %x $ec]"
echo "DFSC = 0x[format %x $dfsc]"# 判斷異常類型
if {$ec == 0x25} {if {$dfsc == 0x21} {echo ">> 非對齊內存訪問異常!"echo ">> 地址 0x[format %x $far] 未按字長對齊"} else {echo ">> 其他類型數據中止 (DFSC=0x[format %x $dfsc])"}
} else {echo ">> 非數據中止異常 (EC=0x[format %x $ec])"
}
關鍵寄存器說明
寄存器 | 位域 | 值 | 含義 |
---|---|---|---|
ESR_ELx | EC[31:26] | 0x25 | 數據中止異常 |
DFSC[5:0] | 0x21 | 對齊錯誤 | |
FAR_ELx | - | 任意地址 | 觸發異常的內存地址 |
PC | - | 當前地址 | 發生異常時的指令地址 |
常見對齊要求
數據類型 | ARM64對齊要求 |
---|---|
Byte | 1字節 |
Halfword | 2字節 |
Word | 4字節 |
Doubleword | 8字節 |
128-bit向量 | 16字節 |
???注意事項:
異常級別需匹配:EL1異常查ESR_EL1,EL2查ESR_EL2
通過
SCTLR_ELx.A
位可配置對齊檢查:
A=1
:強制對齊檢查(默認)
A=0
:允許非對齊訪問(但性能下降)使用
STM/LDM
等多寄存器指令時,地址必須按8字節對齊
可通過以下命令檢查對齊檢查配置:
# 讀取系統控制寄存器
set sctlr [readreg SCTLR_EL1]
set alignment_check [expr ($sctlr >> 1) & 1] # 提取A位if {$alignment_check} {echo "對齊檢查已啟用"
} else {echo "警告:非對齊訪問被允許!"
}