virtualbox でカスタム os を作成していますが、IOAPIC mmio レジスタからの書き込みと読み取りに問題があります。つまり、インデックスレジスタの書き込みを無視しているようです。R8
IOAPIC ベース アドレス (ACPI 列挙から 0xFEC00000 と判断) をロードした後、次のルーチンを使用して読み取り/書き込みを行います。
; -----------------------------------------------------------------------------
; IN : RAX = ioapic address, EBX = index register
; OUT: ECX = return value
ioapic_read:
mov [r8], ebx
mov ecx, [r8 + 0x10]
ret
; -----------------------------------------------------------------------------
; IN : RAX = ioapic address, EBX = index register, ECX = value
; OUT: -
ioapic_write:
mov [r8], ebx
mov [r8 + 0x10], ecx
ret
ただし、ioapic_read は、使用されるインデックスに関係なく、(ioapic_write によって) 書き込まれた最後の値を常に返します。キャッシュを無効にする必要があると思われる 0x9B を使用するように ID ページングをセットアップしています。
pause
各sの後に使ってみましたmov
。役に立ちませんでした。mfence
s の間でs を試しましたmov
。役に立ちませんでした。
0xFEC00000
アドレスが正常に ID マッピングされていることを確認しました。
まだキャッシュが残っているようです。私は何が欠けていますか?
編集
私はそれがキャッシングの問題ではなく、もっと奇妙なことであることを発見しました - 少なくとも私の無知な脳にとっては。私の ID ページングは、ページ フォールトがテーブルに正しい物理ページを生成するようにオンデマンドで動作します。
これは機能しているように見えますが、IOAPIC mmio レジスタの場合、0xFEC00000 アドレスを使用する前にダミーの読み取りまたは書き込みを行ってページ フォールトを発生させる必要があります。さらに奇妙なことは、このダミー読み取りを事前に十分な命令を行う必要があるか、機能しないことです。例えば
これは機能します!
mov eax, [os_IOAPICAddress]
mov dword[rax], 0
mov r8, rax
.
.
.
call ioapic_read
...これは違います!
mov eax, [os_IOAPICAddress]
mov r8, rax
mov dword[rax], 0
.
.
.
call ioapic_read
パイプライン化/シリアル化の問題が疑われますが、アドレスを MMIO レジスタで使用する前にテーブルにページ フォールトする必要がある理由と、十分に前もってそれを行う必要がある理由の両方を知りたいと思っています。後者の場合、どのように修正すればシリアル化されるので、心配する必要はありません。
私のIDページングルーチン:
pageFault_identity_0x0E:
pop r8
push rsi rdi rax rcx rdx r9
test r8, 1
jnz exception_gate_14
mov rdx, cr2 ; faulting address
shr rdx, 39
and rdx, 0x1FF ; get 9 bit index
mov rdi, cr3
lea rsi, [rdi + rdx*8]
mov rdi, [rsi]
test rdi, 1
jnz @f
call set_new_page_table
@@:
shr rdi, 12 ; get rid of flags
shl rdi, 12
mov rdx, cr2
shr rdx, 30 ; get 9 bit index
and rdx, 0x1FF
lea rsi, [rdi + rdx*8]
mov rdi, [rsi]
test rdi, 1
jnz @f
call set_new_page_table
@@:
shr rdi, 12 ; get rid of flags
shl rdi, 12
mov rdx, cr2
shr rdx, 21
mov rax, rdx
and rdx, 0x1FF ; get 9 bit index
lea rsi, [rdi + rdx*8]
shl rax, 21
or rax, 0x83
mov [rsi], rax
shr rax, 21
shl rax, 21
pop r9 rdx rcx rax rdi rsi
iretq
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;
; IN: rsi = address of blank entry
; OUT: rdi = base address of new table, changes rax & rcx
;
set_new_page_table: ; make table, get it, zero it, insert base into previous table
movzx rdi, [page_table_count]
shl rdi, 12
add rdi, NEW_PAGE_TABLES
CLEAR_BLOCK rdi, 0x200 ; clears 4096 bytes in rdi, returns rdi + 4096
sub rdi, 0x1000
lea rax, [rdi + 0x3] ; table base address
mov [rsi], rax
inc [page_table_count]
ret