我在 qemu-system-arm 上模擬 arm1176jzf-s。因為我正在嘗試為樹莓派零開發一個簡單的準系統作業系統,為此我使用來自 wiki.osdev.org 的引導代碼跳轉到 c 代碼。在其中,我試圖將一些資料寫入協處理器暫存器,確切地說是“協處理器控制訪問暫存器”。我可以很好地閱讀,但是當我嘗試寫作時,價值不會改變。代碼是這樣的:
uint32_t dest = 0, tmp = 0;
/* Read the coprocessor access control register. */
__asm ("mrc p15, 0, %[dst], c1, c0, 2"
: [dst] "=r" (dst));
log_uint(dst, 'h');
log_uint(dst, 'b');
/* Enable access for domain control access register.
Modifies dst to be 0xC0000040. */
SETBIT(dst, 6);
log_uint(dst, 'h');
log_uint(dst, 'b');
/* Write the changed value. */
__asm ("mcr p15, 0, %[dst], c1, c0, 2"
:
: [dst] "r" (dst));
/* Read the coprocessor access control register. */
__asm ("mrc p15, 0, %[tmp], c1, c0, 2"
: [tmp] "=r" (tmp));
log_uint(tmp, 'h');
log_uint(tmp, 'b');
log_uint,使用 uart 以二進制或十六進制形式列印一個整數。
輸出如下:
C0000000
11000000000000000000000000000000
C0000040
11000000000000000000000001000000
C0000000
11000000000000000000000000000000
根據處理器的技術參考手冊:您必須在更新協處理器訪問控制暫存器后立即執行指令記憶體屏障 (IMB) 序列。我已經嘗試過多種資料同步屏障操作和預取緩沖區重繪 操作的組合。但這不起作用,所以我不確定如何執行此 IMB 序列,也找不到它。
但是讓我煩惱的另一件事是,根據處理器手冊,協處理器訪問控制暫存器必須具有復位值0x00000000,但我讀到0xC0000000。
在內核中,在這段代碼之前,我只是初始化了 uart,沒有別的,所以一切都應該是復位值。
uj5u.com熱心網友回復:
您正在嘗試設定與協處理器 4 對應的 CPACR 位。這在 QEMU 的 1176 CPU 中不存在,因此它的 CPACR 位是 RAZ/WI。我不確定您要這樣做是為了什么——評論提到了“域控制訪問暫存器”,但 1176 域訪問控制暫存器 (DACR) 位于 cp15 中,而不是 cp4 中。如果您復制的代碼確實需要訪問“協處理器 4”,那么您需要修改它以不這樣做,因為無論它是什么,QEMU 都不會實作它。
嚴格來說,最高位中的始終為 1 的位是 QEMU 錯誤,但它們是無害的——我們正在為所有 v7 內核實作“如果 CPU 沒有 Neon 或 D16-D31,ASEDIS 和 D32DIS 是 RAO” ,但是像 1176 這樣的早期版本沒有這些欄位,并且這些位實際上應該讀為零。
uj5u.com熱心網友回復:
osdev subreddit 中的klange已經澄清了這個問題,解釋在評論中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/464753.html
