- 虚拟化
- 硬件仿真
【免费下载链接】qemu
Official QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.
导读
本文围绕 QEMU 官方文档 docs/system/s390x/protvirt.rst 展开,系统讲解如何在 IBM Z(s390x)平台上运行受保护虚拟机(Protected Virtual Machine,PVM):从 Ultravisor 固件与 KVM 能力前提,到-object s390-pv-guest与confidential-guest-support的完整命令行配置,再到两种安全镜像启动路径(磁盘引导与-kernel命令行引导)的底层实现。读完本文,你将掌握 PVM 的搭建方法、diag308子码 8/10 的加密过渡机制,并能结合本仓库源码(target/s390x/kvm/pv.c、target/s390x/diag.c)理解 QEMU 与 KVM 的完整协作链路。
一、受保护虚拟化(PVM)是什么
在传统的虚拟化环境中,hypervisor 拥有对客户机内存和寄存器状态的完全访问权,因而天然具备"VM 内省"(VM introspection)能力——管理员可以看到客户机内核、内存中的明文数据。s390x 的 Protected Virtualization 通过引入一个独立于 hypervisor 的固件实体Ultravisor改变这一局面。
根据 docs/system/s390x/protvirt.rst 的定义:
受保护虚拟机(PVM)的内存和大部分寄存器对 hypervisor 而言是加密的或不可访问的,从而在虚拟机运行时有效禁止 VM 内省。在静止(At rest)状态下,PVM 是加密的,只能由特定 IBM Z 机器上名为 Ultravisor 的固件实体解密。
这意味着 PVM 的完整生命周期分为两个层面:
- 运行时(Runtime):hypervisor 无法读取客户机内存与寄存器,即使宿主被攻破也无法直接窥探客户机内部;
- 静态(At rest):安全镜像本身是加密的,只有目标机器上的 Ultravisor 持有相应密钥才能解封(unpack)执行。
需要特别说明的是,PVM 并不等同于"不可入侵的绝对安全",它的安全边界是:信任 Ultravisor 固件与硬件本身,而对 hypervisor(KVM/QEMU)持不信任态度。这与 x86 平台的 SEV/SEV-SNP、TDX 属于同一类"机密计算"(Confidential Computing)范畴,但 s390x 的实现路径(固件实体 + 加密解封流程)具有明显的平台特色。
二、运行 PVM 的前提条件
文档明确列出了三层前提,缺一不可。本仓库源码中也对其中部分条件做了硬性校验,见下文"源码级剖析"一节。
2.1 硬件与固件:Ultravisor Call facility(stfle bit 158)
运行 PVM 的机器必须具有Protected Virtualization 特性,该特性由Ultravisor Call facility(stfle bit 158)指示。stfle(Store Facility List Extended)是 s390x 架构的 CPU 特性查询指令,bit 158 置位表示该机器硬件与固件支持调用 Ultravisor 服务。
2.2 宿主机内核参数:prot_virt=1
Ultravisor 需要在宿主机引导时完成初始化,方法是在宿主机内核命令行上设置:
prot_virt=1只有 Ultravisor 完成初始化,KVM 才能将虚拟机转入受保护模式。
2.3 必须使用 KVM 虚拟化
运行 PVM必须使用 KVM hypervisor(即 QEMU 需以-accel kvm运行)。在 QEMU 源码中这一约束被硬编码校验:s390_pv_kvm_init()会在未启用 KVM 时直接报错 "Protected Virtualization requires KVM"(见 target/s390x/kvm/pv.c)。
2.4 能力探测:KVM_CAP_S390_PROTECTED
当上述条件全部满足时,KVM 会通过能力位KVM_CAP_S390_PROTECTED指示该 LPAR(逻辑分区)上支持 PVM。QEMU 在初始化时通过kvm_check_extension()探测该能力:
- 探测代码见 target/s390x/kvm/kvm.c,结果保存在静态变量
cap_protected; - 当
cap_protected为真时,QEMU 会自动把Unpack facility(S390_FEAT_UNPACK)注入默认 CPU 模型的能力位图,见 target/s390x/kvm/kvm.c 中set_bit(S390_FEAT_UNPACK, model->features)的逻辑。
三、运行一个受保护虚拟机:命令行配置
3.1 核心命令片段
根据文档,运行 PVM 需要选择包含Unpack facility的 CPU 模型,并在 QEMU 命令行中加入以下两个选项:
qemu-system-s390x \ -cpu <支持 unpack 的型号> \ -object s390-pv-guest,id=pv0 \ -machine confidential-guest-support=pv0 ...其中:
-object s390-pv-guest,id=pv0:创建一个类型为s390-pv-guest的 QOM 对象。它本质上是一个"标记对象"(源码注释中明确写道"basically a dummy used to tell the confidential guest support system to use s390's PV mechanism",见 target/s390x/kvm/pv.c),作用是告知 QEMU 的机密客户机支持框架:本虚拟机采用 s390 的 PV 机制;-machine confidential-guest-support=pv0:将上述对象挂接到机器类型上,触发后续的 PV 初始化流程。
3.2 添加这些选项会发生什么
文档明确说明,添加上述选项后会依次产生三个效果:
- 确保
unpackfacility 可用:即确保 CPU 模型具备unpack特性(对应S390_FEAT_UNPACK,stfle bit 161),这是后续安全镜像解封的基础; - 默认对所有 I/O 设备启用 IOMMU:PVM 场景下客户机内存对 hypervisor 不可见,DMA 必须经过 IOMMU 翻译与保护,因此 QEMU 默认开启 IOMMU;
- 初始化 PV 机制:调用 KVM 的 PV 命令(
KVM_PV_ENABLE等)完成虚拟机级受保护状态建立。
3.3 CPU 模型选择与 unpack facility
unpack特性在 QEMU 特性定义表中的全貌如下(见 target/s390x/cpu_features_def.h.inc):
DEF_FEAT(UNPACK, "unpack", STFL, 161, "Unpack facility")也就是说,unpack是一个由 stfle 位 161 指示的 CPU 特性。你可以在命令行用-cpu max、-cpu host或任何包含该特性的具体型号。注意文档同时提示:当-machine confidential-guest-support=pv0生效时,QEMU 的 KVM 初始化会强制校验S390_FEAT_UNPACK,缺失时直接拒绝启动("CPU model does not support Protected Virtualization",见 target/s390x/kvm/pv.c),所以不必担心"漏配 CPU 特性导致静默失败"。
3.4 相关对象在 QMP 中的注册
s390-pv-guest对象在 QMP 的ObjectOptions枚举中有正式注册,属于用户可创建(user-creatable)对象,可通过 QMP 的object-add动态创建(见 qapi/qom.json)。这为脚本化/动态管理 PVM 提供了与命令行等价的能力。
四、源码级剖析:QEMU 如何初始化 PVM
4.1 启动校验链:s390_pv_kvm_init()
当confidential-guest-support挂接对象后,QEMU 调用 target/s390x/kvm/pv.c 中的s390_pv_kvm_init(),其校验顺序为:
- 确认对象类型是
s390-pv-guest(否则直接返回 0,不干预); - KVM 检查:
kvm_enabled()为假则报错退出; - CPU 特性检查:
S390_FEAT_UNPACK缺失则报错退出; - CPU 数量检查:调用
s390_pv_guest_check()→s390_pv_check_cpus()验证smp.max_cpus不超过 PV 上限; - 全部通过后置
cgs->ready = true。
4.2 PVM 的 CPU 上限从何而来
受保护模式下,客户机通过 Read SCP Info 服务调用能获取的信息被限制在一页(4 KiB)内,因此可表示的 CPU 条目数量有上限。s390_pv_get_max_cpus()(见 target/s390x/kvm/pv.c)据此计算:
return (TARGET_PAGE_SIZE - offset_cpu) / sizeof(CPUEntry);其中offset_cpu取决于是否启用 Extended-Length SCCB(ELS)特性。超出上限时 QEMU 会报错 "Protected VMs support a maximum of %d CPUs"。从源码结构看,这一限制是 PV 模式下 SCLP 通信页容量约束的直接体现。
4.3 机器级保护流程:s390_machine_protect()
真正执行"进入受保护模式"的是 hw/s390x/s390-virtio-ccw.c 中的保护流程,其步骤清晰对应文档描述:
- 禁止内存丢弃:
ram_block_discard_disable(true)——PVM 内存页需要显式的共享/取消共享语义,virtio-balloon 等内存回收机制在 PV 模式下无法正常工作; - 添加迁移阻止器:源码直接给出结论 "protected VMs are currently not migratable"(当前 PVM 不可迁移),通过
migrate_add_blocker阻止迁移操作; - 创建 SE VM:
s390_pv_vm_enable()向 KVM 发送KVM_PV_ENABLE命令(见 target/s390x/kvm/pv.c),这是"初始化 PV 机制"在 KVM 层的落地; - 查询 PV 信息:
s390_pv_query_info()通过KVM_PV_INFO获取 dump 相关参数(非关键路径,失败不致命); - 设置安全参数:
s390_ipl_prepare_pv_header()(见 hw/s390x/ipl.c)从 IPL 参数块中读取加密镜像的头部(pv_header_addr/pv_header_len),调用s390_pv_set_sec_parms()下发KVM_PV_SET_SEC_PARMS命令——若返回码为UV_RC_SSC_INVAL_HOSTKEY(0x0108),还会提示"检查镜像是否为此宿主正确加密"(见 target/s390x/kvm/pv.c); - 解封镜像:
s390_ipl_pv_unpack()(见 hw/s390x/ipl.c)遍历 IPL 参数块中列出的每个组件,逐一调用s390_pv_unpack()下发KVM_PV_UNPACK命令完成解密; - 完整性校验:
s390_pv_verify()下发KVM_PV_VERIFY验证镜像完整性。
上述所有 KVM 命令均通过kvm_vm_ioctl(kvm_state, KVM_S390_PV_COMMAND, &pv_cmd)发送(见 target/s390x/kvm/pv.c),失败时打印KVM PV command %d (%s) failed并附上 KVM 返回的rc/rrc码。
五、PVM 的启动过程(Boot Process)
文档将 PVM 的安全镜像启动分为两种方式:从磁盘引导与从 QEMU 命令行提供的镜像引导。两者最终都通过diag308的新子码触发"进入安全模式"的过渡。
5.1 方式一:从磁盘引导(s390-ccw BIOS 路径)
这种方式使用未修改的 s390-ccw BIOS,流程如下:
- BIOS 解释引导映射(bootmap);
- 将多个组件读入内存,并把控制权交给其中一个组件——zipl stage3;
- Stage3 做若干修正(fixups),再将控制权交给驻留在客户机内存中的某个程序,通常就是操作系统内核;
- 安全镜像在头部额外预置了一个组件stage3a,它使用新的
diag308子码8 和 10来触发进入安全模式的过渡。
在 QEMU 源码中,diag308(Diagnose 0x308,IPL 控制指令)的子码定义位于 include/hw/s390x/ipl/diag308.h:
#define DIAG308_SET 5 #define DIAG308_STORE 6 #define DIAG308_PV_SET 8 #define DIAG308_PV_STORE 9 #define DIAG308_PV_START 10- 子码 8(DIAG308_PV_SET):设置 PV 模式的 IPL 参数块(IPL Parameter Block,IPIB),在 target/s390x/diag.c 中与普通
DIAG308_SET共用处理路径,但使用iplb_valid_pv()校验; - 子码 9(DIAG308_PV_STORE):读取 PV IPIB;
- 子码 10(DIAG308_PV_START):正式请求启动 PV 复位(
S390_RESET_PV),见 target/s390x/diag.c。该路径还会检查:若宿主机为 PVM 启用了大页(kvm_s390_get_hpage()),则直接返回DIAG_308_RC_INVAL_FOR_PV并报告 "Protected VMs can currently not be backed with huge pages"。
此外,handle_diag_308()在入口处会先校验:只要子码大于等于DIAG308_PV_SET(8),就必须具备S390_FEAT_UNPACK特性,否则抛出规格异常(Specification Exception)中断(见 target/s390x/diag.c)。
5.2 方式二:命令行镜像引导(-kernel 路径)
如果镜像文件通过-kernel提供给 QEMU,则要求该文件具有与磁盘引导相同的内存布局,包括:
- 加密的组件(内核 kernel、initrd、命令行 cmdline);
- stage3a 加载器;
- 元数据。
关键限制:使用这种引导方式时,-initrd和-cmdline选项无效(因为镜像内部已经打包了相应的加密载荷,外部无法以明文方式注入)。PVM 镜像的制备由 s390-tools 软件包中的genprotimg工具完成。
5.3 与 Secure IPL 的关系
需要区分两个概念:Protected Virtualization(本文主题)关注"内存与寄存器对 hypervisor 不可见";而Secure IPL(安全引导)关注"引导时验证内核完整性"。二者是互补但独立的机制。QEMU 的 s390 Secure IPL 通过secure-boot与boot-certs机器参数实现(Normal/Audit/Secure 三种模式),相关用法可进一步参考仓库中的 docs/system/s390x/secure-ipl.rst。
六、限制与注意事项
文档明确列出了 PVM 当前的两类限制,源码中也给出了对应依据:
6.1 不支持 vfio 直通设备
Passthrough(vfio)设备目前不受支持。原因从架构上不难理解:直通设备需要将宿主机物理设备直接映射给客户机,其 DMA 会绕过 QEMU 的 IOMMU 保护层,这与 PVM 强制"所有 I/O 经过 IOMMU"的安全模型冲突。PVM 场景应使用 virtio 设备(virtio-blk/virtio-net 等)。
6.2 宿主机大页(Huge Page)不支持
宿主机大页后备(host huge page backing)不受支持,这一约束同样硬编码在DIAG308_PV_START路径中(见上文 5.1 节,target/s390x/diag.c)。
但需要注意文档的补充说明:客户机内部可以按自身 facility 使用大页。即限制的是"宿主机用大页给 PVM 提供内存后备",而非"客户机内核使用大页"。
6.3 其他源自源码的已知约束
- 不可迁移:PVM 启动时注册了迁移阻止器,迁移会明确失败(hw/s390x/s390-virtio-ccw.c);
- 内存丢弃被禁用:balloon 等依赖内存回收的机制在 PV 模式下受限(hw/s390x/s390-virtio-ccw.c);
- CPU 数量上限:受 SCLP 单页信息容量约束(见 4.2 节)。
七、快速上手检查清单
综合全文,搭建一个 PVM 环境的完整检查清单如下:
- 硬件:确认机器具备 Ultravisor Call facility(stfle bit 158);
- 宿主内核:在
/etc/default/grub(或等效引导配置)的内核命令行中加入prot_virt=1并重新引导; - 确认 KVM 能力:宿主上确认 KVM 已加载且
KVM_CAP_S390_PROTECTED可用(QEMU 会据此自动注入unpack特性); - 准备安全镜像:使用 s390-tools 的
genprotimg生成符合要求的 PVM 镜像(或准备含 stage3a 的磁盘引导镜像); - 启动命令:
qemu-system-s390x -machine s390-ccw-virtio \ -accel kvm \ -cpu max \ -object s390-pv-guest,id=pv0 \ -machine confidential-guest-support=pv0 \ -kernel <protimg 生成的镜像> \ ...- 注意限制:避免使用 vfio 直通、避免宿主大页、不依赖迁移与 balloon。
八、延伸阅读
- 本文主文档:docs/system/s390x/protvirt.rst
- Secure IPL(安全引导)使用指南:docs/system/s390x/secure-ipl.rst
- PV 核心实现(KVM 命令封装与 S390PVGuest 对象):target/s390x/kvm/pv.c
- diag308 的 PV 子码处理:target/s390x/diag.c、include/hw/s390x/ipl/diag308.h
- 机器级 PV 初始化与复位:hw/s390x/s390-virtio-ccw.c
unpack特性定义:target/s390x/cpu_features_def.h.incs390-pv-guest的 QMP 对象注册:qapi/qom.json
说明:受保护虚拟化是硬件、固件(Ultravisor)、宿主机内核(KVM)与 QEMU 四方协同的能力,本文涉及的 QEMU 侧行为均以当前仓库源码与文档为准;Ultravisor 内部的加密细节属于平台固件范畴,不在 QEMU 源码仓库中体现。
- 虚拟化
- 硬件仿真
【免费下载链接】qemu
Official QEMU mirror. Please see https://www.qemu.org/contribute/ for how to submit changes to QEMU. Pull Requests are disabled. Please only use release tarballs from the QEMU website.
相关推荐
Cube Sandbox PVM 部署指南:在无 /dev/kvm 的普通云服务器上启用 KVM 虚拟化
Cube Sandbox PVM 部署指南:在无 /dev/kvm 的普通云服务器上启用 KVM 虚拟化 适用场景:云服务器上 /dev/kvm 不可用(云服务
Agent 沙箱虚拟化云原生人工智能后端容器运行时高性能权限系统laravel-permission:千万级用户权限管理终极指南
高性能权限系统laravel permission:千万级用户权限管理终极指南 laravel permission是一款专为Laravel框架设计的高性能权限
虚拟化硬件仿真突破虚拟化瓶颈:ZeroTier One KVM/QEMU性能调优实战指南
突破虚拟化瓶颈:ZeroTier One KVM/QEMU性能调优实战指南 你是否在KVM/QEMU虚拟机中遇到ZeroTier One网络延迟高、吞吐量不足的
网络通信后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考