Я пишу пользовательские os в виртуальном боксе и затрудняюсь писать и читать из регистра IOAPIC mmio. т. е. он, как представляется, игнорирует запись в индексном регистре. После загрузки R8
с базовым адресом IOAPIC (определяется из ACPI перечисления быть 0xFEC00000), я использую следующие процедуры для чтения/записи:Как избежать кэширования при записи в регистры mmio?
; -----------------------------------------------------------------------------
; 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, который, я думаю, должен отключить кеширование.
Я попытался использовать pause
после каждого из mov
. Не помогло. Протестировано mfence
s между mov
s. Не помогло.
Я подтвердил, что адрес 0xFEC00000
успешно идентифицирован.
Похоже, что все еще происходит кеширование. Что мне не хватает?
EDIT
Я обнаружил, что это не проблема кэширования, но что-то много незнакомец - по крайней мере, на мой невежественный мозг. Мой идентификационный пейджинг работает по требованию, так что ошибка страницы приведет к созданию правильной физической страницы в таблицах.
Это похоже на работу, но в случае регистров 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, и почему мне нужно сделать это достаточно далеко заранее. В последнем случае, как исправить это, поэтому оно сериализовано так, что мне не нужно беспокоиться об этом.
Моя личность пейджинговой рутина:
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
Являются ли эти функции 'ioapic_read' и' ioapic_write' вызванными из _C_? –
Нет, все в сборе – poby
Является ли область памяти отмеченной не кешируемой? http://stackoverflow.com/questions/90204/why-would-a-region-of-memory-be-marked-non-cached – stark