- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在 virtualbox 中编写自定义操作系统,但无法从 IOAPIC mmio 寄存器成功写入和读取。即它似乎忽略了索引寄存器写入。使用 IOAPIC 基地址(根据 ACPI 枚举确定为 0xFEC00000)加载 R8 后,我使用以下例程进行读/写:
; -----------------------------------------------------------------------------
; 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,我认为应该禁用缓存。
我尝试在每个 mov
之后使用 pause
。没有帮助。尝试了 mov
之间的 mfence
。没有帮助。
我已确认 0xFEC00000
地址已成功进行身份映射。
看起来仍在进行一些缓存。我错过了什么?
编辑
我发现这不是缓存问题,而是一个非常奇怪的问题 - 至少对于我无知的大脑来说是这样。我的身份分页按需工作,这样页面错误将在表中生成正确的物理页面。
这似乎有效,但对于 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
最佳答案
鉴于原始代码,看起来好像您正在正确设置页目录条目位以将 MMIO 区域标记为不可缓存。我确信还有其他问题。通过后续编辑,您向我们展示了页面错误处理程序 pageFault_identity_0x0
:
pageFault_identity_0x0E:
pop r8
push rsi rdi rax rcx rdx r9
当处理器将控制权转移到该页错误异常处理程序时,它将在堆栈顶部传递一个错误代码作为参数。问题是您将R8的内容替换为错误号,而没有保存然后恢复寄存器。
您必须修改异常处理程序以保留R8,将内容从错误号所在的正确堆栈偏移量移至R8。请记住确保错误号不再位于IRETQ之前的堆栈顶部。
您遇到的奇怪行为可能与R8在从页面错误返回时未正确恢复直接相关。
<小时/>可能有效的解决方案是:
pageFault_identity_0x0E:
push rsi
push rdi
push rax
push rcx
push rdx
push r9
push r8
mov r8, [rsp+7*8] ; Error Code is at offset RSP+7*8 after all the pushes
; Do exception handling work here
pop r8
pop r9
pop rdx
pop rcx
pop rax
pop rdi
pop rsi
add rsp, 8 ; Remove the error code
iretq
关于caching - 写入mmio寄存器时如何避免缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39822804/
我正在寻找一种最好使用 C/C++ 的软件模式,如何在并发环境中安全访问微 Controller (例如 ARM Cortex-M)中的 MMIO 外围设备 - 中断和主/线程(在操作系统的情况下)。
我希望对 PCIe 设备的所有读写请求都由 CPU 缓存缓存。然而,它并没有像我预期的那样工作。 这些是我对回写 MMIO 区域的假设。 写入 PCIe 设备仅在缓存回写时发生。 TLP 负载的大小是
我发现我的 MMIO 读/写延迟高得不合理。我希望有人能给我一些建议。 在内核空间中,我编写了一个简单的程序来读取 PCIe 设备 BAR0 地址中的一个 4 字节值。该设备是一个 PCIe Inte
有没有一个 *nix 命令可以给我所有的 MMIO/PIO 地址空间 对于特定设备(或所有设备)? 最佳答案 你试过了吗: cat /proc/ioports cat /proc/iomem 根据 r
要配置 UART tx,必须写入水位线(0 到 7)在位位置 [18:16] 上的内存映射 tx 控制寄存器上。 我的 RISC-V 汇编函数首先读取当前的控制寄存器值,执行一个按位与掩码清除位 [1
我正在尝试访问一些 MMIO GPIO 地址以进行 LED 控制和电池监控。但我不知道如何计算正确的地址。 文档说明如下: COMMUINTY_BASE = Bus 0 Device 0x0d Fun
我有带 AMD TR 2950x 的 Android Studio安卓模拟器运行完美然后突然开始给我这个错误带有此消息: 10:30 AM Emulator: qemu-system-x86_64.e
我找到的最接近的答案可能与 Eva 插件的 -absolute-valid-range 有关,但真的是这样吗?我是否必须想出读/写 ACSL 谓词来执行虚拟读/写? 示例代码: #include #
我是一名优秀的程序员,十分优秀!