在 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)
宿主机 CPUHUAWEI Kunpeng 920 3210 (HiSilicon)
虚拟机架构aarch64, machine virt-4.1
QEMUqemu-system-aarch64 (4.1.0.2)
虚拟化KVM (accel=kvm)
虚拟机内存/CPU1024 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 implementer0x480x48一致
CPU part0xd010xd01一致
CPU variant0x10x1一致
CPU revision00一致
Vendor IDHiSiliconHiSilicon一致
Model nameKunpeng-920Kunpeng-920一致

虚拟机内 CPU 的 implementer(0x48 = HiSilicon)与 part(0xd01 = Kunpeng-920)与宿主机完全一致,这是 CPU 透传(passthrough)的典型特征——guest 直接读取了物理 CPU 的 MIDR 寄存器值。

根因

  1. ARM 架构下,libvirt/QEMU 的 CPU 模型与特性禁用设置未对 guest 生效。

  2. 虚拟机内看到的 CPU 依然是透传的物理 CPU:

    • guest 的 Flags 仍包含本应被禁用的 asimddp、asimdfhm
    • guest 的 CPU implementer(0x48)、part(0xd01)与宿主机完全一致,直接暴露物理 CPU 身份
  3. QEMU 命令行参数已正确生成,说明问题不在 libvirt 的 XML 解析/翻译层,而在于 ARM/KVM 虚拟化层对 CPU 模型与特性的处理方式。

    ARM 架构下 KVM 默认将物理 CPU 特性透传给 guest,-cpu 指定的模型/特性开关在 aarch64 + KVM 场景下未产生实际约束效果。

  4. 仅资源拓扑层面生效:vCPU 数量、socket/core 拓扑、NUMA 拓扑等资源分配参数正常生效。

  5. 与 x86 的差异:x86 架构下 -cpu <model>,<feature>=off 会真实改变 guest 可见的 CPUID 特性;ARM 架构下该机制不适用,guest 直接读取物理 CPU 的 MIDR/特性寄存器。

小结

  • ARM 架构下,CPU 模型设置基本失效,实际只有 passthrough;
  • 要热迁移,就必须要保证物理机的 CPU 基本一样;
  • 同系列、不同型号的 CPU,把 flags 设置为一样,大概率可以热迁移,但需要测试;
  • 不同厂商的 ARM CPU,基本不可能热迁移;
  • 别在 ARM 上探索指令集、热迁移这些 x86 的玩法了,全部用 passthrough。