2017-08-18 47 views
1

我在armv8(aarch64)中編寫了一個簡單的內核。如何調試aarch64翻譯錯誤?

MMU配置:

  • 48 VA位(T1SZ = 64-48 = 16)
  • 4K頁大小
  • 映射到內核虛擬存儲器(上TTBR1_EL1)所有物理RAM平坦 (MMU與TTBR0_EL1 = 0活性,所以我只使用在地址爲0xFFFF <地址>,所有平面映射到物理存儲器)

我映射新的地址空間(從1開始的< < 40)到一些自由的物理區域。當我嘗試訪問的地址1 < < 40,I( 「使用SP1 EL1,同步」 式的)得到一個異常:

ESR_EL1=0x96000044 
FAR_EL1=0xffff010000000000 

檢查其他寄存器,我有:

TTBR1_EL1=0x82000000 
TTBR1_EL1[2]=0x0000000082003003 

所以,基於ARM架構參考手冊ARMv8(ARMv8-A剖面):

  • ESR(異常綜合徵寄存器)轉化爲:異常類= 100101(數據中止機智在第D7-1933頁上的例外水平)發生變化。 WnR = 1(錯誤指令是寫入); DFSC = 0b000100(級別0的翻譯錯誤)D7-1958頁;
  • FAR_EL1是錯誤地址;它表示使用了TTBR1_EL1(因爲高位全爲1)。 VA前9位爲0b000000010,表示表中使用了表項2;
  • 表中的條目2表示物理地址0x82003000處的下一級表(低位0b11)。

因此,翻譯失敗在0級,它不應該。

我的問題是:我做錯了什麼?我是否錯過了一些可能導致翻譯錯誤的信息?而且,更一般地說,如何調試翻譯錯誤?

更新:
在啓用MMU之前寫入表時,Everthing會起作用。
無論何時在啓用MMU(通過平面映射表區域)後寫入表格,映射都不會起作用。我想知道爲什麼發生這種情況我也嘗試手動寫入選定的表(以消除我的映射函數中的任何副作用):相同的結果(在MMU打開之前寫入完成後,它工作;之後失敗)。

我試過tlbidsb sy指令,其次是isb,沒有效果。此時只有一個CPU正在運行,所以緩存不應該成爲問題 - 寫入指令和MMU與相同的緩存對話(但我會在下一次測試它)。

回答

1

我忽略了單個內核中的緩存問題。問題在於,打開MMU之後,CPU和表格散步單元沒有相同的內存視圖。ARMv8 Cortex-A編程指南指出,在修改表後,必須將緩存清理/無效化爲統一點(單個內核的相同視圖)。

兩種可能性可以解釋這種行爲(我不完全理解緩存是如何工作尚未):

  1. 第一種可能性:的MMU沒有在其內部的步行緩存所需的地址。
    在這種情況下,更新常規數據並使其可用於其他內核的L1時,dsb指令只是等待所有內核具有同步狀態(由於一致性網絡):其他內核將知道該行必須更新,當他們嘗試訪問它時,它會更新到L2或從前一個核心的L1遷移到L1。
    MMU(沒有一致性參與)不會發生這種情況,所以它仍然會看到L2中的舊值。然而,如果是這種情況,在MMU開啓之前應該發生同樣的事情(因爲之前激活了緩存),除非在MMU被激活之前所有內存都被認爲是L1不可緩存的(這是可能的,我必須仔細檢查一下)。
    解決此問題的最簡單方法可能是更改表頁面的緩存策略,但緩存維護仍然有必要從MMU中清除可能的舊值。
  2. 第二種可能性:在所有測試情況下,MMU已經在其內部步行高速緩存中存在與數據L1或L2不一致的錯誤地址。
    在這種情況下,只有一個顯式的invalidate可以從MMU緩存中彈出舊行。在MMU打開之前,緩存不包含任何內容,並且永遠不會獲得舊值(0),只有新值。
    我仍然認爲這種情況不太可能,因爲我測試了很多情況,有時預先映射的內存(例如,1級表中的條目0)與新映射的內存(例如,相同級別1中的條目128表)大於緩存行大小(在這種情況下爲1024字節,比任何緩存行大小都大)。

所以,我仍然不確定究竟是什麼原因導致問題,但清理/無效所有更新的地址的作品。