axplat-x86-qemu-q35 技术文档
路径:
platform/x86-qemu-q35类型:库 crate 分层:平台层 / x86_64 Q35 板级平台包 版本:0.2.0文档依据:当前仓库源码、Cargo.toml、README.md、build.rs、linker.lds.S、src/lib.rs、src/boot.rs、src/multiboot.S、src/init.rs、src/mem.rs、src/console.rs、src/time.rs、src/apic.rs、src/mp.rs、src/power.rs
axplat-x86-qemu-q35 是面向 QEMU Q35 机型的 x86_64 axplat 平台实现,当前主要服务于 Axvisor 的宿主侧启动路径。它把 Multiboot 引导、临时 GDT/页表、COM1 控制台、TSC/LAPIC/IOAPIC、AP 启动页、Q35 MMIO 窗口和关机/重启策略收敛成 axplat 契约。它不是通用 x86 PC 平台抽象,也不是虚拟化核心本身;它解决的是“Axvisor 在 Q35 这台机器上怎样把宿主环境带起来”的问题。
1. 架构设计分析
1.1 真实定位
这个 crate 和仓库里另一个 ax-plat-x86-pc 很容易被混淆,但它们的定位并不相同:
ax-plat-x86-pc位于components/axplat_crates,更偏 ArceOS 侧的标准 PC 参考平台。axplat-x86-qemu-q35位于根目录platform/,是 Axvisor 当前 x86_64 宿主平台依赖。- 前者走
axplat_crates的常规平台组织方式;后者把 Q35 和 Axvisor 的构建约束直接内嵌进自己的build.rs与链接脚本。
它在平台栈中的职责可以概括为:
- 向下依赖 x86 架构库和 Multiboot 解析库。
- 向上实现
ConsoleIf、InitIf、MemIf、TimeIf、IrqIf、PowerIf。 - 通过
build.rs和linker.lds.S在构建期注入内核基址与 CPU 数。 - 为 Axvisor 提供宿主侧最小板级环境,但不介入 VMX/EPT、VM exit 或虚拟设备模拟。
1.2 模块划分
| 模块 | 作用 | 关键内容 |
|---|---|---|
boot | 启动配置汇总 | Multiboot 常量、CR0/CR4/EFER 参数、启动栈和 multiboot.S 组合 |
multiboot.S | 最早期入 口 | 32 位到 64 位切换、临时 GDT/页表、主核/次核入口汇编 |
console | ConsoleIf 实现 | COM1 串口收发 |
mem | MemIf 实现 | Multiboot 内存图解析、MMIO 窗口、线性映射 |
time | TimeIf 实现 | TSC 单调时间、可选 RTC、LAPIC one-shot timer |
apic | IrqIf 实现核心 | LAPIC/x2APIC、IOAPIC、向量分发、IPI |
mp | SMP bring-up | AP 启动页、INIT-SIPI-SIPI、栈与入口灌入 |
init | InitIf 实现 | trap、串口、时间、内存、APIC 初始化顺序 |
power | PowerIf 实现 | QEMU 关机/重启策略、次核启动封装 |
1.3 构建期配置与启动主线
这个平台包有一个和 axplat_crates 平台明显不同的地方:它不是基于 axconfig.toml 生成配置,而是基于 build.rs + linker.lds.S + 环境变量 决定构建结果。
构建期主要有两项关键配置:
BASE_ADDRESS:由build.rs固定写入链接脚本,当前为0xffff800000200000。SMP:由环境变量AXVISOR_SMP写入链接脚本,随后通过绝对符号SMP成为运行期 CPU 数。
cpu_count() 之所以能返回 CPU 数,正是因为它读取的是链接脚本中绝对符号 SMP 的地址值,而不是做运行时枚举。
启动主线如下:
这条链路里有几个实现事实需要特别注意:
- 临时页表使用 1 GiB huge page 同时建立低地址和高半区映射。
multiboot.S已经同时准备了 BSP 和 AP 的进入长模式路径。- BSP 的第二个参数是 Multiboot 信息指针,不是设备树或 ACPI 句柄。
- 次核路径复用同一套高半区映射,只是在
ap_start.S中先从低地址启动页进入。
1.4 内存与设备模型
mem.rs 的平台模型分为三层:
mem::init(mbi)从 Multiboot 内存图提取 RAM 区间。reserved_phys_ram_ranges()固定保留低0x200000,防止启动页、boot info 等低地址内容被拿去分配。MMIO_RANGES用常量写死 Q35 所需的关键窗口:- PCI config space
- PCI devices window
- IO APIC
- HPET
- Local APIC
- 额外高地址 PCI 窗口
需要明确的是:
- 本 crate 只负责暴露这些窗口,不做 ACPI 解析。
- 它也不在本层完成 PCI 枚举或驱动装载。
phys_to_virt()/virt_to_phys()完全建立在固定PHYS_VIRT_OFFSET上。