Ich schreibe eine benutzerdefinierte os in virtualbox und Probleme beim Schreiben und Lesen erfolgreich aus den IOAPIC mmio-Registern. h. es scheint das Schreiben des Indexregisters zu ignorieren. Nach dem Laden R8
mit der IOAPIC Basisadresse (bestimmt von ACPI-Enumeration 0xFEC00000 zu sein), verwende ich die folgenden Routinen zum Lesen/Schreiben:Wie vermeidet man Caching beim Schreiben in mmio Register?
; -----------------------------------------------------------------------------
; 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
Aber ein ioapic_read wird den letzten Wert geschrieben (von ioapic_write) immer wieder zurückkehren und zwar unabhängig des verwendeten Indexes. Ich habe Identity-Paging-Setup, um 0x9B verwenden, die ich denke, sollte Caching deaktivieren.
Ich habe versucht, pause
nach jedem der mov
s. Hat nicht geholfen. Versucht mfence
s zwischen mov
s. Hat nicht geholfen.
Ich habe bestätigt, dass die 0xFEC00000
Adresse erfolgreich Identität zugeordnet ist.
Es sieht so aus, als ob noch etwas Caching läuft. Was vermisse ich?
EDIT
ich entdeckt habe es kein Caching Problem ist aber etwas viel Fremde - zumindest für mein unwissend Gehirn. Mein Identitäts-Paging funktioniert bei Bedarf so, dass ein Seitenfehler die richtige physische Seite in den Tabellen generiert.
Dies scheint zu funktionieren, aber im Falle der IOAPIC mmio-Register muss ich einen Seitenfehler verursachen, indem ich einen Dummy-Lese- oder -Schreibvorgang an der Adresse 0xFEC00000 vor dem Versuch, es zu verwenden, mache. Die noch seltsamere Sache ist, dass ich diesen Dummy lesen muss, bevor ich genug Anweisungen gelesen habe oder es funktioniert nicht. z.B.
Das funktioniert!
mov eax, [os_IOAPICAddress]
mov dword[rax], 0
mov r8, rax
.
.
.
call ioapic_read
... dies NICHT!
mov eax, [os_IOAPICAddress]
mov r8, rax
mov dword[rax], 0
.
.
.
call ioapic_read
ich vermuten, dass ein Pipelining/Serialisierung Problem, aber ich würde wirklich lieben, beide zu erfahren, warum muss ich Seite bemängeln die Adresse in den Tabellen, bevor es in einem MMIO-Register verwendet wird, und warum muss ich es tun weit genug im Voraus. Im letzteren Fall, wie man es repariert, so dass es serialisiert wird, so dass ich mich nicht darum kümmern muss.
Meine Identität Paging-Routine:
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
Werden diese Funktionen 'ioapic_read' und' ioapic_write' von _C_ aufgerufen? –
Nein, die ganze Sache ist in Assembly – poby
Ist der Speicherbereich nicht cachefähig markiert? http://stackoverflow.com/questions/90204/why-would-a-region-of-memory-be-marked-non-cached – stark