在 ARM(aarch64)架构下,libvirt/QEMU 的 CPU 模型与特性禁用设置不生效,虚拟机看到的 CPU 依然是透传的物理 CPU。所以 ARM 架构下,别探索什么指令集、热迁移了,全部用 passthrough。
现象
将虚拟机 CPU 设置为 custom 模式,指定 Kunpeng-920 指令集,并通过 <feature policy="disable"> 禁用 asimddp、asimdfhm 两个 CPU 特性。
对比宿主机与虚拟机内的 lscpu / /proc/cpuinfo 输出,发现设置未生效。
尽管 QEMU 进程命令行已携带 -cpu Kunpeng-920,asimddp=off,asimdfhm=off,虚拟机内部看到的 CPU 依然是透传的物理 CPU(特性、implementer、part 号与宿主机完全一致)。
排查
测试环境
| 项目 | 值 |
|---|---|
| 宿主机架构 | aarch64 (ARM64) |
| 宿主机 CPU | HUAWEI Kunpeng 920 3210 (HiSilicon) |
| 虚拟机架构 | aarch64, machine virt-4.1 |
| QEMU | qemu-system-aarch64 (4.1.0.2) |
| 虚拟化 | KVM (accel=kvm) |
| 虚拟机内存/CPU | 1024 MiB / 1 vCPU |
虚拟机 XML 的 CPU 部分
<cpu mode="custom" match="exact">
<model>Kunpeng-920</model>
<feature policy="disable" name="asimddp"/>
<feature policy="disable" name="asimdfhm"/>
<topology sockets="1" cores="1" threads="1"></topology>
<numa>
<cell id="0" cpus="0" memory="1048576" unit="KiB" discard="yes"></cell>
</numa>
</cpu>
QEMU 进程的 -cpu 参数
虚拟机启动后,QEMU 进程实际命令行中的 CPU 相关参数:
-cpu Kunpeng-920,asimddp=off,asimdfhm=off
完整命令行关键片段:
-machine virt-4.1,accel=kvm,usb=off,dump-guest-core=off,gic-version=3
-cpu Kunpeng-920,asimddp=off,asimdfhm=off
-smp 1,sockets=1,dies=1,cores=1,threads=1
-numa node,nodeid=0,cpus=0,mem=1024
说明 QEMU 命令行确实携带了 Kunpeng-920 模型及 asimddp=off,asimdfhm=off 特性禁用参数,说明 libvirt 已正确将 XML 翻译为 QEMU 参数。
宿主机 lscpu(物理机)
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 48
On-line CPU(s) list: 0-47
Thread(s) per core: 1
Core(s) per socket: 24
Socket(s): 2
NUMA node(s): 2
Vendor ID: HiSilicon
Model name: Kunpeng-920
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma dcpop asimddp asimdfhm
虚拟机内 lscpu
Architecture: aarch64
CPU op-mode(s): 64-bit
Byte Order: Little Endian
CPU(s): 1
On-line CPU(s) list: 0
Vendor ID: HiSilicon
Model name: Kunpeng-920
Flags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma dcpop asimddp asimdfhm
NUMA node(s): 1
NUMA node0 CPU(s): 0
关键差异点:asimddp / asimdfhm 特性
| 项目 | 宿主机 | 虚拟机 | 预期(若设置生效) |
|---|---|---|---|
Flags 中的 asimddp | 存在 | 存在 | 应被禁用 |
Flags 中的 asimdfhm | 存在 | 存在 | 应被禁用 |
| QEMU 参数 | - | -cpu Kunpeng-920,asimddp=off,asimdfhm=off | - |
核心矛盾:QEMU 命令行明确携带 asimddp=off,asimdfhm=off,但虚拟机内 lscpu 与 /proc/cpuinfo 的 Flags 中仍然包含 asimddp asimdfhm。
说明特性禁用参数在 ARM/KVM 下未对 guest 生效。
CPU 身份信息对比
| 项目 | 宿主机 | 虚拟机 | 是否一致 |
|---|---|---|---|
| CPU implementer | 0x48 | 0x48 | 一致 |
| CPU part | 0xd01 | 0xd01 | 一致 |
| CPU variant | 0x1 | 0x1 | 一致 |
| CPU revision | 0 | 0 | 一致 |
| Vendor ID | HiSilicon | HiSilicon | 一致 |
| Model name | Kunpeng-920 | Kunpeng-920 | 一致 |
虚拟机内 CPU 的 implementer(0x48 = HiSilicon)与 part(0xd01 = Kunpeng-920)与宿主机完全一致,这是 CPU 透传(passthrough)的典型特征——guest 直接读取了物理 CPU 的 MIDR 寄存器值。
根因
ARM 架构下,libvirt/QEMU 的 CPU 模型与特性禁用设置未对 guest 生效。
虚拟机内看到的 CPU 依然是透传的物理 CPU:
- guest 的 Flags 仍包含本应被禁用的
asimddp、asimdfhm - guest 的 CPU implementer(0x48)、part(0xd01)与宿主机完全一致,直接暴露物理 CPU 身份
- guest 的 Flags 仍包含本应被禁用的
QEMU 命令行参数已正确生成,说明问题不在 libvirt 的 XML 解析/翻译层,而在于 ARM/KVM 虚拟化层对 CPU 模型与特性的处理方式。
ARM 架构下 KVM 默认将物理 CPU 特性透传给 guest,
-cpu指定的模型/特性开关在 aarch64 + KVM 场景下未产生实际约束效果。仅资源拓扑层面生效:vCPU 数量、socket/core 拓扑、NUMA 拓扑等资源分配参数正常生效。
与 x86 的差异:x86 架构下
-cpu <model>,<feature>=off会真实改变 guest 可见的 CPUID 特性;ARM 架构下该机制不适用,guest 直接读取物理 CPU 的 MIDR/特性寄存器。
小结
- ARM 架构下,CPU 模型设置基本失效,实际只有 passthrough;
- 要热迁移,就必须要保证物理机的 CPU 基本一样;
- 同系列、不同型号的 CPU,把 flags 设置为一样,大概率可以热迁移,但需要测试;
- 不同厂商的 ARM CPU,基本不可能热迁移;
- 别在 ARM 上探索指令集、热迁移这些 x86 的玩法了,全部用 passthrough。