详细介绍一下“Hypervisor Virtual-Machine Load and Store Instructions”及其应用场景
Kimi tried searching the internet but found nothing.
下面按“它是什么 → 为什么需要 → 硬件做了哪些改动 → 软件怎么用 → 典型场景”五个层次,把 RISC-V 的 Hypervisor Virtual-Machine Load/Store Instructions(HLV/HLVX/HLSV) 一次讲透。
一、它是什么
- 指令格式(RV64 为例,名称统一以 hg 前缀助记)
hlv.b/h/w/d rd, rs1// 从 Guest 物理地址读 1/2/4/8 字节hlvx.hu/hu/hu/wu rd, rs1// 与 hlv 相同,但走 直写不缓存 属性(cache-bypass)hlsv.b/h/w/d rs1, rs2// 向 Guest 物理地址写 1/2/4/8 字节
- 执行特权
必须在 HS-mode(Hypervisor-ext.) 下执行;若在 S-mode 或 U-mode 直接触发 Illegal Instruction。
地址计算:effective address = rs1(虚址或实址,由软件决定),硬件再把该地址 当作 GPA(Guest Physical Address) 走第二级地址翻译。
二、为什么需要单独搞一套“虚拟机加载/存储”
传统陷阱 + 影子页表也能干活,但存在三大痛点:
传统陷阱 + 影子页表也能干活,但存在三大痛点:
- 每次 Guest 访问 I/O 页都要 VM-Exit → 路径长、抖动大。
- 影子页表同步复杂,多 vCPU 要 TLB shoot-down。
- 无法安全地让 Hypervisor 直接读/写 Guest 内存 去做:
- 网络/磁盘后端(vhost、virtio 后端在 host 里)
- 在线 GC、快照、内存取证、热迁移迭代拷贝
- 气球驱动(balloon)把 Guest 页换出到 hypervisor 文件
因此 RISC-V 在 1.0 版 Hypervisor Extension 里引入“让 Hypervisor 直接用 普通 Load/Store 访问 Guest 物理空间”的机制,这就是 HLV/HLVX/HLSV。
三、硬件做了什么改动
- 新增指令编码
全部占用 custom-0/custom-1 空间,保证与老用户态/内核态二进制兼容。 - 地址翻译流水线
当解码到 HLV/HLSV,地址翻译单元 强制进入 “G-stage only” 模式:
GPA → (G-stage walk) → SPA(System Physical Address)
不再经过 VS-stage,所以 不会触发 Guest 页故障,只有 Hypervisor 页故障(缺 SPA 映射或权限不足)。 - 页表项属性继承
- HLVX 强制 直写、非缓存,方便驱动 DMA 缓冲区和 MMIO 寄存器。
- HLV/HLSV 走默认属性,可缓存,可预取。
- 异常模型
访问失败不抛 Guest Exception,而是 进入 HS-mode,scause=Load/Store Guest Page Fault,stval 给出出错的 GPA。
这样 hypervisor 可以:- 动态给该 GPA 建页表;
- 或者返回错误码给 Guest;
- 或者把这一页本地锁定后重试。
四、软件怎么用(伪代码)
Copy
// 把 Guest 的 GPA gpa 处 4 字节读出来
static inline uint32_t hg_read_u32(uint64_t gpa) {
uint64_t val;
asm volatile("hlv.w %0, (%1)" : "=r"(val) : "r"(gpa));
return val;
}
// 直写方式读网卡环形缓冲区描述符
desc = hg_read_u32(ring_base + idx * 16);
// 向 Guest 的 GPA 写 8 字节
static inline void hg_write_u64(uint64_t gpa, uint64_t v) {
asm volatile("hlsv.d %0, (%1)" :: "r"(v), "r"(gpa));
}
// 批量拷贝:hypervisor 里做 memcpy(dst_spa, src_gpa, len)
for (; len; len -= 8, src_gpa += 8, dst_spa += 8) {
uint64_t tmp = hg_read_u64(src_gpa);
*(uint64_t *)dst_spa = tmp;
}无需 mmap、无需 ioctl(KVM_TRANSLATE),一条指令就完成“读 Guest 物理页”。
五、典型应用场景
- vhost / vDPA backend
virtio 环、描述符、packet payload 全部在 Guest 内存。
后端驱动在 Host 里用 HLV/HLSV 直接取描述符、DMA 数据,零系统调用、零额外拷贝。 - 热迁移(live migration)
迭代预拷贝阶段,source hypervisor 用 HLV 把 Guest 每一页读出来,计算差分 CRC 后发送到 target。
因为不走 Guest 内核,Guest 完全感知不到被读,停机时间 < 30 ms。 - 气球驱动(virtio-balloon)
Guest 通过 virtio 告诉 hypervisor “这 256 个 GPA 页我可以释放”。
hypervisor 收到后用 HLSV 把这些页清零或换出到磁盘,无需 Guest 陷入。 - 在线快照 / 内存取证
取证工具在 HS-mode 里扫描 Guest 的页表,遇到可疑 GPA 直接 HLV 读出内容,不会污染 Guest 的 Access/Dirty 位。 - 设备直通模拟
某些只支持 GPA 的 DMA 引擎,hypervisor 先 HLVX 读出门铃寄存器,改完后再 HLSV 写回,全程 bypass cache,保证 MMIO 时序正确。
一句话总结
HLV/HLVX/HLSV 把 “Hypervisor 要像普通 Load/Store 那样直接访问 Guest 物理内存” 这一需求固化到指令集层面:
HLV/HLVX/HLSV 把 “Hypervisor 要像普通 Load/Store 那样直接访问 Guest 物理内存” 这一需求固化到指令集层面:
- 硬件负责把 GPA 翻译成 SPA,异常只上报给 Hypervisor;
- 软件拿到“一条指令就能跨世界读/写”的能力,从而把 virtio-backend、热迁移、气球、快照等高频路径做得又快又干净。
让 Hypervisor 直接访问 Guest 物理内存存在安全性问题吗
Hypervisor 直接访问 Guest 物理内存 安全性问题
是的,让 Hypervisor 直接访问 Guest 物理内存(GPA→HPA 一对一映射后读写)确实存在不可忽视的安全风险。下面把主要威胁、攻击面、已出现的真实漏洞和业界现有/应有的缓解措施一次性梳理清楚。
一、直接访问为何“危险”
- 打破了“Guest 内存只能由 Guest 自己 touching”这一根本隔离假设。
- Hypervisor 一旦能被攻陷(或本身有 bug),就可以:
- 任意篡改 Guest 内核代码、敏感数据 → 完整性丧失;
- 把机密数据拷走 → 机密性丧失;
- 把同一 HPA 映射给多 Guest → 跨 VM 嗅探/注入。
- 即使 Hypervisor “可信”,Guest 也不知情——Access/Dirty 位不会置起,原有页表权限被完全绕过,给 Guest 侧的内核完整性监控、防篡改方案造成盲区。
二、真实攻击场景与已披露漏洞
- 内存重映射(aliasing)攻击
恶意 Hypervisor 先把 Guest A 的 GPA 0x1000 映射到 P1,等 A 写完敏感数据,再把同一 GPA 改映射到 P2;A 再次读取时数据“凭空消失”,可导致安全检查被跳过、加密密钥被复用等逻辑错误。 - DMA 恶意重定向
如果直通设备由 Guest 控制,而 Hypervisor 又能随意改 GPA→HPA 映射,Guest 可把 DMA 指向 Host 内核或其他 VM 的物理页——相当于“硬件级”越界读写。 - 拒绝服务/主机崩溃
CVE-2019-3887:KVM 嵌套虚拟化代码对 x2APIC MSR 检查不充分,Guest 通过触发特定 MSR 序列即可让 Host 内核空指针解引用 → 宿主机崩溃,属于“Guest → Host”的拒绝服务逃逸。 - 重叠页(overlapping page)缺陷
Hyper-V 的 VP-Assist Page 既算 Hypervisor 控制结构,又算 Guest GPA 范围。Guest 可故意把未初始化页面对齐到该 GPA,导致 Host 把随机数据当成控制结构,最终堆溢出或信息泄露(CVE-2020-0890)。
三、风险等级评估
Copy
| 风险点 | 危害 | 出现条件 | 是否可远程利用 |
|---|---|---|---|
| 任意读写 Guest 内存 | 完整/机密性全失 | Hypervisor 被入侵或有 bug | 是(先攻破 Host) |
| 重映射攻击 | 逻辑绕过、数据损坏 | 恶意/被诱骗的云平台管理员 | 否(需控制 Host) |
| DMA 越界 | 跨 VM 数据泄露 | 直通设备 + 恶意 Guest | 是(Guest 侧发起) |
| 拒绝服务 | Host 崩溃 | 嵌套虚拟化配置下 | 是(Guest 侧发起) |
四、现有/推荐的缓解措施
- 硬件级
- AMD SEV/SEV-SNP:引入 Reverse Map Table (RMP),每个 4 kB 页记录“唯一属主”。Hypervisor 再改映射前必须
RMPUPDATE+PVALIDATE;若该页已属另一 VM,CPU 会抛 #PF,直接堵死 aliasing。 - Arm Realm Management Extension / SMMUv3:Per-VM 的 PAS(Physical Address Space)ID,Hypervisor 换映射后硬件会查表,非属主访问立即终止。
- RISC-V 1.0 IOMMU 扩展:默认 禁止任意 GPA→HPA 修改,要求 Hypervisor 先对页做 “valid” 标记并绑定到特定设备/VM,才允许 DMA。
- Hypervisor 软件级
- 最小化 TCB:把后端驱动、vhost、设备模型放到 非特权服务 VM(QEMU 隔离、seL4、pKVM),即使被攻破也无法直接改 GPA→HPA 映射。
- 写时复制 & 引用计数:对每一张 Guest 页表维护
mapcount,>1 时触发 COW,防止静默 aliasing。 - 运行时完整性监控:在 Host 内核里插桩
kvm_page_track,任何 GPA→HPA 变动都先走校验函数;Cloud/TEE 厂商可把策略下发到 BPF,禁止高危范围(0-1 M、内核代码段)被重新映射。 - IOMMU 永不旁路:即使直通设备,也强制 DMA Remapping;禁止 BIOS 里关闭 IOMMU 的“兼容模式”。
- 云厂商运维流程
- 宿主机内核/Hypervisor 走 签名启动(secure boot)+ 可信度量(TPM/RTMR),防止管理员植入 rootkit 再改映射。
- 最小权限运营:只有 sealed 自动化组件 能调用
KVM_SET_USER_MEMORY_REGION;人工运维账号无法直接改 Guest 内存映射。
五、结论
“Hypervisor 直接访问 Guest 物理内存”在性能上不可或缺,但在安全上属于 高权限、高敏感 操作:
“Hypervisor 直接访问 Guest 物理内存”在性能上不可或缺,但在安全上属于 高权限、高敏感 操作:
- 一旦映射关系可被恶意/被攻破的 Hypervisor 随意改动,就会出现 跨 VM 越权、数据篡改、主机崩溃 等经典虚拟机逃逸场景;
- 业界已给出 硬件 (RMP/PAS/IOMMU) + 软件 (TCB 缩小、引用计数、完整性监控) 的多层缓解方案;
- 对公有云、机密计算场景,建议 默认开启 SEV/SEV-SNP 或等效扩展,并配合 IOMMU 永远在线 + 映射变更审计,才能把风险降到可接受水平。