ax-plat-loongarch64-qemu-virt
路径:
platforms/ax-plat-loongarch64-qemu-virt类型:库 crate 分层:组件层 / LoongArch64 板级平台包 版本:0.3.1-pre.6文档依据:当前仓库源码、Cargo.toml、README.md、axconfig.toml、src/boot.rs、src/init.rs、src/console.rs、src/time.rs、src/irq.rs、src/mem.rs、src/power.rs、src/mp.rs
ax-plat-loongarch64-qemu-virt 是 QEMU LoongArch 虚拟机在 axplat 体系下的完整平台实现。它不是“只提供启动代码”的薄封装,而是自己承担了控制台、时间、中断、电源、内存和可选多核的全部板级落地工作:从 LoongArch 启动头、DMW 映射和早期页表,到 16550 串口、LoongArch timer CSR、EIOINTC/PCH PIC、GED 关机寄存器,几乎都在本 crate 内部完成。
架构设计
1.1 真实定位
与 AArch64 那几个平台包不同,这个 crate 没有依赖独立的“通用外设 glue crate”。它自己同时实现了:
ConsoleIfInitIfTimeIfIrqIfMemIfPowerIf
这使它在平台栈中的位置非常清晰:
- 向下依赖
ax-cpu、loongArch64、uart_16550等架构/设备库。 - 向上直接把 LoongArch QEMU virt 的全部最小平台能力暴露给
axplat。 - 在仓库里既是
ax-hal的 LoongArch 默认平台之一。
这意味着它不是“仅供样例演示”的平台包,而是当前 LoongArch 路径里的主力参考 实现。
模块结构
| 模块 | 作用 | 关键内容 |
|---|---|---|
boot | 最早期引导 | LoongArch 启动头、DMW 配置、引导页表、MMU 打开、主核/次核入口 |
console | ConsoleIf 实现 | MMIO 16550 串口单例与收发逻辑 |
time | TimeIf 实现 | timer CSR、tick/纳秒换算、可选 LS7A RTC、oneshot timer |
irq | IrqIf 实现 | Timer/IPI/外部中断分发、EIOINTC 与 PCH PIC 接线 |
init | InitIf 实现 | trap、串口、时钟、中断初始化顺序 |
mem | MemIf 实现 | 双线性映射、RAM/MMIO 区间、boot_info/FDT 保留区 |
power | PowerIf 实现 | GED 关机、可选次核启动封装 |
mp | SMP bring-up | 通过 CSR mail 和 IPI 传递次核入口与栈顶 |
1.3 启动与双映射策略
这个 crate 最关键的设计,不是某个单独设备,而是引导期和运行期并存的两套地址语义:
PHYS_BOOT_OFFSET:引导期使用的直接映射窗口,配合 DMW 工作。PHYS_VIRT_OFFSET:内核运行期使用的高半区线性映射。
boot.rs 中的主线如下:
这套设计带来两个重要后果:
virt_to_phys()不能简单做一次固定偏移减法,而要区分地址到底来自 boot window 还是运行期 window。- 早期页表不仅要考虑内核代码所在高内存,还要覆盖 LoongArch QEMU virt 的低地址设备区。
代码里实际的引导页表策略是:
0..256 MiB映射为普通可执行内存。256 MiB..1 GiB在引导页表里按 device memory 处理,用于覆盖低地址设备区。0x8000_0000..0xC000_0000额外映射为普通可执行内存。
这说明它的引导页表是在“保证启动成功”和“覆盖平台必要设备”之间做的最小平衡,而不是最终内核页表的完整表示。
1.4 中断拓扑与运行期职责
LoongArch QEMU virt 的中断模型在这个 crate 里被明确分层了:
| IRQ 类型 | 来源 | 本 crate 中的实现位置 |
|---|---|---|
| Timer IRQ | LoongArch timer CSR | time.rs + irq.rs |
| IPI | IOCSR IPI 寄存器 | irq.rs |
| 外部中断入口 | EIOINTC | irq/eiointc.rs |
| 实际外设 IRQ | PCH PIC | irq/pch_pic.rs |
IrqIf::handle() 的关键逻辑不是简单查表,而是:
- 先判断当前 IRQ 是 timer、IPI 还是外部中断入口。
- 若是
EIOINTC_IRQ,再向 EIOINTC 认领真实外部 IRQ。 - 将真实 IRQ 分发到
HandlerTable。 - 最后按中断类型执行 timer clear 或 EIOINTC completion。
这说明该 crate 并不是“把某个现成中断控制器整体包起来”,而是把 LoongArch virt 的级联中断拓扑消化后,重新对上暴露 ax_plat::irq 语义。
1.5 与相邻层的边界
| 层 | 负责内容 | 不负责内容 |
|---|---|---|
ax-cpu | trap 初始化、MMU 打开、FP/LSX 使能、停机等 CPU 原语 | 串口、GED、EIOINTC/PCH PIC、平台地址窗口 |
ax-plat-loongarch64-qemu-virt | 启动头、地址映射、中断拓扑、串口、时间、关机、SMP glue | 调度、页表管理策略、驱动枚举、上层 HAL 组合 |
ax-hal | 上层统一内存视图、DTB/bootarg 进一步整合、运行时初始化组织 | LoongArch virt 本地寄存器初始化与外设语义 |
还要额外澄清两点:
boot.rs当前把第二个参数arg固定传成0,并留有TODO: parse dtb;也就是说,本 crate 目前并不真正解析设备树。mem.rs虽然保留了0..0x200000作为boot_info + fdt区,但这只是内存保留语义,不等于平台已经把 FDT 接进运行期配置系统。