内存映射输入输出与寄存器所有权
Memory-Mapped Input/Output(内存映射输入输出,MMIO)把设备寄存器物理区间映射为内核可访问的虚拟地址。memory/mmio-api 只定义映射能力、映射结果和寄存器访问入口;components/axklib/src/mmio.rs、ax-mm::iomap() 与平台内存实现负责建立带设备属性的实际映射。MMIO 不分配设备传输缓冲区,也不能把设备寄存器区加入普通物理页分配器。
1. 分层边界
MMIO 的核心一致性条件是“寄存器窗口不是普通内存”。驱动只持有映射对象并执行易失性读写,操作系统适配层决定物理地址如何进入内核地址空间,页表层负责使用设备内存属性建立页表项。
1.1 组件职责
各层按寄存器窗口的发现、映射和消费分工,避免驱动直接依赖 ArceOS 地址空间或特定平台的物理直映规则。
| 组件 | 主要职责 | 不负责的内容 |
|---|---|---|
mmio-api | 定义 MmioOp、MmioAddr、MmioRaw、Mmio 和 MapError | 选择页表格式、分配物理页、解析设备树 |
axklib::mmio | 注册 KlibMmio,把映射请求接到 Klib::mem_iomap() | 保存设备对象、解释寄存器语义 |
ax-runtime::KlibImpl | 在启用分页时调用 ax_mm::iomap(),否则返回不支持 | 在未启用分页时猜测直映地址 |
ax-mm 与 ax-hal | 检查范围、选择平台映射或通用映射、设置设备页属性 | 把设备窗口交给 Buddy 分配器 |
| 驱动核心 | 持有映射对象,以正确宽度和偏移访问寄存器 | 调用页分配器、修改内核页表 |
Direct Memory Access(直接内存访问,DMA)管理设备可访问的内存缓冲区及其缓存所有权,MMIO 管理设备寄存器窗口。二者可能被同一个驱动同时使用,但没有互相包装或释放的关系。
1.2 依赖方向
映射请求从驱动向平台逐层收敛,映射结果以 Mmio 或 MmioRaw 返回。mmio-api 不反向依赖 ax-mm,因此可移植驱动不会绑定到 ArceOS。
platforms/axplat-dyn/src/boot.rs 也实现 MmioOp,把动态平台探测阶段的请求转交给同一个 axklib::mmio::op()。platforms/somehal/src/setup.rs::set_kernel_op() 在平台与内核运行时接线时注册能力,平台驱动因此不需要直接引用 ax-mm。
1.3 架构差异
公共 Mmio owner 和易失性访问接口不区分架构,物理窗口如何变成可访问虚拟地址、页表项如何编码设备属性以及设备访问前后的屏障由平台实现。
| 架构 | MMIO 虚拟地址 | 设备属性 | 访问顺序 |
|---|---|---|---|
| x86_64 | 平台直映或 ax-mm::iomap() 建立内核映射 | `NO_CACHE | WRITE_THROUGH` |
| AArch64 | iomap() 建立映射或平台启动窗口 | Device-nGnRE MAIR 槽位 | 设备寄存器协议配合 DMB/DSB |
| RISC-V 64 | 平台物理窗口经内核映射 | 标准页表权限;平台扩展表达强序/非缓存 | 设备协议配合 fence |
| LoongArch64 | _io() 使用独立 IO_BASE,并检查物理地址宽度 | MAT 强序非缓存 | 设备协议配合 dbar |
易失性读写只约束编译器,不自动执行上述架构屏障。驱动核心表达“提交 descriptor 后敲 doorbell”等协议顺序,平台 capability 提供具体指令。