我正在一個arm-linux板上有幾個PCI插槽。PCI枚舉黑客結束數據中止異常
我想檢查UBoot中PCI模塊的供應商ID /設備ID。 因此,我將PCI驅動程序的初始化部分從linux移植到UBoot。
的哈克: 由於我的船上的PCI拓撲結構是固定的,我把硬編碼的巴士號碼(pirmary,二次,下屬)在UBOOT的自由,所以我沒有端口枚舉代碼UBOOT 。爲了獲得總線編號,我編寫了一個小型可加載的內核模塊,一旦內核完成枚舉PCI總線上的設備,我就可以獲得總線編號
設備
。
問題: 現在,如果模塊存在於PCI插槽中,我可以成功讀取它們的ID。 但是,如果一個模塊不存在,並且我嘗試讀取它的ID,那麼我可以通過ARM的數據中止處理程序。
是否解決此數據中止異常,或在嘗試讀取ID之前事先知道插槽是否已填充。
更新1: 我根據auselen的輸入改性UBOOT源如下:
start.S中
//添加下面的宏
.macro irq_restore_user_regs_mod ldmia sp, {r0 - lr}^ @ Calling r0 - lr mov r0, r0 ldr lr, [sp, #S_PC] @ Get PC add sp, sp, #S_FRAME_SIZE mov pc, lr @ return & move spsr_svc into cpsr .endm
更改data_abort代碼如下
data_abort:
get_bad_stack
irq_save_user_regs
bl do_data_abort
irq_restore_user_regs_mod
interrupts.c 改性do_data_abort到
void do_data_abort (struct pt_regs *pt_regs)
{
if (flag == 1)
{
flag = 0;
return;
}
printf ("data abort handler\n");
printf ("Originally installed by U-Boot\n");
show_regs (pt_regs);
bad_mode();
}
mypcie.c部的代碼試圖讀取可能無效地址
printf("Trying possibly invalid address\n");
flag = 1;
data = *((volatile unsigned int *)(0xbe200000)) ;
if (flag == 0) printf("Bad address \n");
flag = 1;
有關部分UBOOT日誌:
Trying possibly invalid address
data abort handler
Originally installed by U-Boot
pc : [<00012150>] lr : [<00012144>]
sp : 46069a00 ip : 78000000 fp : 00000000
r10: 07f7eca4 r9 : 00000000 r8 : 07f7efdc
r7 : 00000000 r6 : 000000f8 r5 : 00000001 r4 : bb000000
r3 : be200000 r2 : 00020b28 r1 : 00000020 r0 : 07f7ea49
Flags: nzcv IRQs on FIQs on Mode USER_32
U-Boot::Resetting CPU ...
我懷疑的是,* irq_restore_user_regs_mod *派遣UBOOT回* do_data_abort *。 因此,do_data_abort執行標誌時的第一次是1,do_data_abort將標誌更改爲0,irq_restore_user_regs_mod將UBoot發送回do_data_abort。由於標誌爲0,UBoot進入壞模式。
請告訴我,我是否應該使用
MOVS PC,LR
或
MOV PC,LR
在irq_restore_user_regs_mod(命令代碼段不同於文字)。
還請詳細說明爲什麼你使用MOV(S)PC,LR代替SUBS PC,LR,#4。
更新2:(在auselen的評論光)
ⅰ)從簡單int改爲標誌在揮發性 ⅱ)增補的printf(S)interrupts.c用於調試目的如如下:
printf("flag = %d\n",flag);
if (flag == 1)
{
flag = 0;
printf("FLAG = %d\n",flag);
return;
}
III)新增asm volatile("" ::: "memory");
之前,使數據可中止訪問後,在文件mypcie.c個
flag = 1;
asm volatile("" ::: "memory");
data = *((volatile unsigned int *)(0xbe200000)) ;
asm volatile("" ::: "memory");
if (flag == 0) printf("Bad address \n");
結果
UBOOT日誌1:
Trying possibly invalid address
flag = 1
FLAG = 0
flag = 1
FLAG = 0
(continues forever)
似乎控制保持返回標誌= 1;在mypcie.c 指令如果我註釋掉這個指令,並初始化標誌爲1個超出這個功能的,然後我得到以下日誌:
UBOOT日誌2:
Trying possibly invalid address
flag = 1
FLAG = 0
flag = 0
data abort handler
Originally installed by U-Boot
pc : [<00012174>] lr : [<5306b01e>]
sp : c6a69a08 ip : 78000000 fp : 00000000
r10: 07f7eca1 r9 : 00000000 r8 : 07f7efdc
r7 : 00000000 r6 : 000000fb r5 : 00000001 r4 : bb000000
r3 : be200000 r2 : 00000000 r1 : 00000020 r0 : 07f7ea4d
Flags: nzcv IRQs on FIQs on Mode USER_32
U-Boot::Resetting CPU ...
現在看起來好像下面的指令執行兩次:
data = *((volatile unsigned int *)(0xbe200000)) ;
在第二個執行標誌是0,所以我們點擊數據中止。
更新3 (在auselen的關於MOV,MOVS和SUBS評論的光) 取出-02在UBOOT目錄config.mk文件標誌。
UBOOT日誌
使用潛艇PC,LR,#4
Trying possibly invalid address
flag = 1
FLAG = 0
prefetch abort handler
Originally installed by U-Boot
pc : [<90000004>] lr : [<00012174>]
sp : 07f7eb80 ip : 78000000 fp : 00000000
r10: 00000000 r9 : 00000000 r8 : 07f7efdc
r7 : 00000000 r6 : 00000000 r5 : 00000000 r4 : 00008e00
r3 : 00000000 r2 : c6a68e1c r1 : 00010001 r0 : 00000003
Flags: nZCv IRQs on FIQs on Mode USER_32
U-Boot::Resetting CPU ...
使用潛艇PC,LR,#8
Trying possibly invalid address
flag = 1
FLAG = 0
flag = 0
data abort handler
Originally installed by U-Boot
pc : [<00012174>] lr : [<00008e7c>]
sp : c6a68cf4 ip : 78000000 fp : 00000000
r10: 07f7eca1 r9 : 00000000 r8 : 07f7efdc
r7 : 00000000 r6 : 000000fb r5 : 00000001 r4 : bb000000
r3 : be200000 r2 : 00000000 r1 : 00000020 r0 : 07f7ea4d
Flags: nzcv IRQs on FIQs on Mode USER_32
U-Boot::Resetting CPU ...
您也可以更改數據中止處理程序以及跳轉到下一條指令。 – auselen
感謝auselen,但不是最好不要在第一個地方得到例外嗎?就像是在進行交易之前檢查目標地址是否有效一樣。此外,處理器現在將處於中止模式。 – microMolvi
與芯片/供應商專用於檢測板卡的根聯合體進行通話。你可能不需要做一個完整的枚舉(反正這個並不複雜),但足以不盲目地談論那些可能導致數據中止的東西。我假設pcie控制器正在導致中止,並且只要您嘗試與那裏沒有的東西交談就會繼續。 –