3

virtualbox でカスタム os を作成していますが、IOAPIC mmio レジスタからの書き込みと読み取りに問題があります。つまり、インデックスレジスタの書き込みを無視しているようです。R8IOAPIC ベース アドレス (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。役に立ちませんでした。mfences の間で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
4

2 に答える 2