Axvisor 客户机配置架构
客户机 TOML 是 VM 需求的持久化格式。axvmconfig 定义 schema,负责反序列化和配置内校验;os/axvisor 把它转换成 AxVMConfigParams,再由 AxVM 的 boot prepare 和设备 prepare 阶段补齐运行时事实。配置只表达客户机身份、启动输入、内存和设备选择,不允许用户填写设备地址、IRQ、MSI 或 LPI 等框架资源。
平台固定资源和分配算法见 Machine 与资源规划架构,设备图之后的注册与中断路径见 设备运行时与中断架构。model 的实现、注册和资源声明见 Axvisor 模拟设备框架。
1. 代码组成与运行阶段
客户机 TOML 从读取到变成设备图要经过四个阶段:axvmconfig 负责解析和校验,Axvisor 应用层完成参数转换,boot prepare 补齐启动资源,device prepare 把虚拟设备请求实例化为图节点。下表列出各阶段的代码位置与职责;修改配置行为时应先确定改动属于哪个阶段,再定位对应的模块。
| 位置 | 主要类型或入口 | 职责 | 运行阶段 |
|---|---|---|---|
virtualization/axvmconfig/src/lib.rs | GuestConfig、VMBaseConfig、VMKernelConfig、GuestDevices、VirtualDeviceRequest | 定义持久化 schema,完成 Serde 解析、boot/device 校验和兼容字段读取 | 配置读取 |
virtualization/axvmconfig/src/error.rs | AxVmConfigError | 区分 TOML 形状错误、启动组合错误和设备选择错误 | 配置读取与校验 |
os/axvisor/src/config.rs:183 | build_axvm_config | 把配置字段转换为 AxVM 参数,注入应用拥有的串口后端,并在默认 catalog 上注册 virtio-blk、virtio-net | 应用层转换 |
virtualization/axvm/src/config.rs:115 | AxVMConfigParams、AxVMConfig | 承接 CPU、镜像、地址空间策略、内存、物理设备 selector、虚拟设备请求和 catalog | VM 创建前 |
virtualization/axvm/src/boot/prepared.rs:45 | prepare_guest_boot、PreparedGuestBoot | 按架构处理 DTB、固件和启动资源,返回准备后的 GuestConfig 与客户机 DTB | boot prepare |
os/axvisor/src/config.rs:132-134 | sync_axvm_config_from_crate_config、set_boot_policy | 把准备阶段新增的内存区域同步到 draft AxVMConfig,并设置 boot policy | 应用层同步 |
virtualization/axvm/src/configured.rs:184 | ConfiguredDeviceCatalog、instantiate_node | 按 model 查找构造器,把 VirtualDeviceRequest 的 model/options 转成 DeviceNodeSpec | device prepare |
virtualization/axvm/src/configured/append.rs:13 | append_configured_devices | 合并默认串口请求和用户请求,逐项调用 catalog,加入待规划设备图 | device prepare |
scripts/axbuild/src/axvisor/mod.rs:320 | jkconfig::run::<GuestConfig> | 通过 schemars::JsonSchema 生成 menuconfig 所需 schema 并编辑 TOML | 构建工具运行期 |
axvmconfig 不依赖具体 Machine,也不分配硬件资源。ConfiguredDeviceCatalog 是请求进入设备图的转换点;catalog 的内置 model 和应用扩展项不是持久化 schema 的枚举。
2. 从 TOML 到设备图
GuestConfig::from_toml() 的顺序固定在 axvmconfig/src/lib.rs:691:先调用 toml::from_str,再执行 validate_boot_config() 和 GuestDevices::validate(),最后记录用户提供的 memory_regions 数量。这个计数不序列化,用于 boot prepare 区分用户内存和准备阶段追加的区域。
应用层转换本身主要是类型与所有权边界转换:
guest_type转为AddressSpacePolicy;passthrough、disabled转为尚未解析的平台 selector 。entry_point、镜像加载地址、CPU 参数和memory_regions写入AxVMConfigParams。devices.virtual原样保留为请求,catalog 由 AxVM 内置注册项与 Axvisor 的virtio-blk、virtio-net注册项组成。- 若
guest_type = "passthrough"、用户没有填写devices.passthrough,且 Machine 提供default_passthrough_device_path,build_axvm_config()会注入一个内部 selector。当前 AArch64、RISC-V 和 LoongArch Machine 使用/作为发现根;x86_64 不注入。 prepare_guest_boot()可以根据 host 固件和架构启动方式补充 DTB 或保留内存,返回持有准备后GuestConfig与客户机 DTB 的PreparedGuestBoot。随后应用层在os/axvisor/src/config.rs:132-134调用sync_axvm_config_from_crate_config(),把新增memory_regions写回 draftAxVMConfig,再设置 boot policy。设备 prepare 在这之后才把请求实例化为图节点。
Machine 负责选择固定串口、中断控制器与地址池,规划器负责解析图节点的资源。配置层只保留用户请求。相关算法见 Machine 与资源规划架构。
3. 持久化 schema
顶层只有 base、kernel、devices 三个表。三者都使用 #[serde(default, deny_unknown_fields)];PhysicalDeviceRef 也拒绝未知字段。这里的 deny_unknown_fields 只适用于固定形状 结构。VirtualDeviceRequest.options 是开放的 TOML 表,由具体 model 在装配时解释。
3.1 base
VMBaseConfig 描述 VM 身份与 CPU 拓扑,是三个表中字段最少的一段,且每个字段都有缺省值。guest_type 决定地址空间基线,其语义在 3.4 节展开;其余字段的转换目标都集中在 PhysCpuList。
| 字段 | TOML 类型 | 缺省值 | 含义与约束 |
|---|---|---|---|
id | 非负整数 | 0 | VM ID;注册阶段还会拒绝与现有 VM 重复的 ID |
name | 字符串 | 空字符串 | VM 名称 |
guest_type | "virtualized" 或 "passthrough" | "virtualized" | 决定地址空间的初始策略,见 3.4 节 |
cpu_num | 非负整数 | 0 | vCPU 数量 |
phys_cpu_ids | 整数数组或省略 | None | 按数组位置覆盖各 vCPU 对客户机暴露的物理 CPU ID;未覆盖的位置保留 vCPU ID,多余项忽略 |
phys_cpu_sets | 整数数组或省略 | None | 按数组位置覆盖各 vCPU 的宿主 pCPU affinity 位图;未覆盖的位置保持无显式 affinity,多余项忽略 |
phys_cpu_ids 和 phys_cpu_sets 是 CPU selector,不是设备资源。当前 PhysCpuList::new() 不校验数组长度;phys_cpu_ids 长度与 cpu_num 不同时只记录日志,default_vcpu_affinities() 仍按已有位置应用,缺项使用默认值,多余项忽略。配置方不能依赖长度或拓扑不匹配一定在 prepare 阶段被拒绝,应主动保证数组长度与 cpu_num 一致,并使用目标平台存在的 CPU ID 和 affinity 位。
3.2 kernel
VMKernelConfig 覆盖入口地址、镜像来源、固件输入和内存描述,是三个表中字段最多的一段。其中多数地址字段在 boot prepare 阶段还会按架构和镜像格式调整,因此配置值是初始输入,不等于最终的加载布局。
| 字段 | TOML 类型 | 缺省值 | 含义与当前约束 |
|---|---|---|---|
entry_point | 非负整数 | 0 | BSP 和 AP 的初始入口 GPA |
kernel_path | 字符串 | 空字符串 | 内核镜像路径;fs 模式按文件路径读取,memory 模式由 image provider 按 VM ID 选择内置镜像,不使用此路径定位 |
kernel_load_addr | 非负整数 | 0 | 内核加载 GPA;部分架构启动流程会按镜像格式进一步调整 |
enable_bios | 布尔值 | false | 旧启动开关;必须与 boot_protocol 一致 |
boot_protocol | "direct"、"multiboot"、"uefi" 或省略 | 省略 | 省略时由 enable_bios 推导,见 3.3 节 |
bios_path | 字符串或省略 | None | Multiboot 固件路径;UEFI 下也可作为兼容固件路径 |
uefi_firmware_path | 字符串或省略 | None | UEFI 固件路径,优先于 bios_path |
bios_load_addr | 非负整数或省略 | None | BIOS/UEFI 固件加载 GPA |
dtb_path | 字符串或省略 | None | 客户机 DTB 镜像路径;架构 prepare 也可能生成或改写 DTB |
dtb_load_addr | 非负整数或省略 | None | DTB 加载 GPA;prepare 可能依据内存布局重新计算 |
ramdisk_path | 字符串或省略 | None | initramfs/ramdisk 镜像路径 |
ramdisk_load_addr | 非负整数或省略 | None | ramdisk 加载 GPA |
image_location | "memory" 或 "fs" | None | 镜像来源;fs 需要相应文件系统 feature。其他值或省略值会在 boot image prepare/load 阶段失败 |
cmdline | 字符串或省略 | None | 客户机内核命令行;x86 Linux direct boot 要求提供 |
memory_regions | 四元数组列表 | 空列表 | 客户机内存描述,格式为 [gpa, size, flags, map_type] |
configured_memory_region_count 是 VMKernelConfig 的运行时辅助字段,带有 #[serde(skip)],不属于 TOML schema。至少一段可用内存、2 MiB 布局对齐、镜像落点等检查发生在 memory/boot prepare;因此 TOML 能解析不代表镜像和内存布局一定可执行。
memory_regions 的 map_type 使用数字表示:
| 值 | 内部类型 |
|---|