Linux KVM 超级调用

X86

KVM 超级调用包含一个三字节的 vmcall 或 vmmcall 指令序列。虚拟机监控程序可以将其替换为保证支持的指令。

最多可以将四个参数分别传递到 rbx、rcx、rdx 和 rsi 中。超级调用号应放置在 rax 中,返回值将放置在 rax 中。除非特定的超级调用明确声明,否则不会破坏其他寄存器。

S390

R2-R7 用于参数 1-6。此外,R1 用于超级调用号。返回值写入 R2。

S390 使用 diagnose 指令作为超级调用 (0x500),同时 R1 中包含超级调用号。

有关 KVM 支持的 S390 diagnose 调用的更多信息,请参阅KVM 上的 s390 DIAGNOSE 调用

PowerPC

它使用 R3-R10,并且超级调用号在 R11 中。R4-R11 用作输出寄存器。返回值放置在 R3 中。

KVM 超级调用使用 4 字节操作码,这些操作码通过设备树 /hypervisor 节点内的“hypercall-instructions”属性进行修补。有关更多信息,请参阅PPC KVM 半虚拟化接口

MIPS

KVM 超级调用使用 HYPCALL 指令,代码为 0,超级调用号在 $2 (v0) 中。最多可以将四个参数放置在 $4-$7 (a0-a3) 中,返回值放置在 $2 (v0) 中。

KVM 超级调用文档

每个超级调用的模板是:1. 超级调用名称。2. 架构 3. 状态(已废弃、已过时、活跃) 4. 目的

1. KVM_HC_VAPIC_POLL_IRQ

架构:

x86

状态:

活跃

目的:

触发客户机退出,以便宿主机在重新进入时检查挂起的中断。

2. KVM_HC_MMU_OP

架构:

x86

状态:

已废弃。

目的:

支持 MMU 操作,例如写入 PTE、刷新 TLB、释放 PT。

3. KVM_HC_FEATURES

架构:

PPC

状态:

活跃

目的:

向客户机公开超级调用可用性。在 x86 平台上,cpuid 用于枚举哪些超级调用可用。在 PPC 上,可以使用基于设备树的查找(这也是 EPAPR 规定的)或 KVM 特定枚举机制(即此超级调用)。

4. KVM_HC_PPC_MAP_MAGIC_PAGE

架构:

PPC

状态:

活跃

目的:

为了启用虚拟机监控程序和客户机之间的通信,有一个共享页面,其中包含部分对超级用户可见的寄存器状态。客户机可以使用此超级调用将此共享页面映射到通过内存访问其超级用户寄存器。

5. KVM_HC_KICK_CPU

架构:

x86

状态:

活跃

目的:

用于唤醒 HLT 状态的 vcpu 的超级调用

使用示例:

在客户机内核模式下忙等待事件发生(例如:自旋锁变为可用)的半虚拟化客户机的 vcpu,在忙等待超过阈值时间间隔后,可以执行 HLT 指令。执行 HLT 指令将导致虚拟机监控程序使 vcpu 睡眠,直到发生适当的事件。同一客户机的另一个 vcpu 可以通过发出 KVM_HC_KICK_CPU 超级调用来唤醒睡眠的 vcpu,指定要唤醒的 vcpu 的 APIC ID (a1)。超级调用中使用了附加参数 (a0) 用于将来用途。

6. KVM_HC_CLOCK_PAIRING

架构:

x86

状态:

活跃

目的:

用于同步宿主机和客户机时钟的超级调用。

用法

a0: 宿主机复制“struct kvm_clock_offset”结构的客户机物理地址。

a1: clock_type,目前仅支持 KVM_CLOCK_PAIRING_WALLCLOCK (0)(对应于宿主机的 CLOCK_REALTIME 时钟)。

struct kvm_clock_pairing {
        __s64 sec;
        __s64 nsec;
        __u64 tsc;
        __u32 flags;
        __u32 pad[9];
};
其中
  • sec: 来自 clock_type 时钟的秒数。

  • nsec: 来自 clock_type 时钟的纳秒数。

  • tsc: 用于计算秒/纳秒对的客户机 TSC 值

  • flags: 标志,目前未使用 (0)。

该超级调用允许客户机在宿主机和客户机之间计算精确的时间戳。客户机可以使用返回的 TSC 值在同一时刻计算其时钟的 CLOCK_REALTIME。

如果宿主机不使用 TSC 时钟源,或者时钟类型与 KVM_CLOCK_PAIRING_WALLCLOCK 不同,则返回 KVM_EOPNOTSUPP。

6. KVM_HC_SEND_IPI

架构:

x86

状态:

活跃

目的:

向多个 vCPU 发送 IPI。

  • a0: 目标 APIC ID 位图的低位部分

  • a1: 目标 APIC ID 位图的高位部分

  • a2: 位图中的最低 APIC ID

  • a3: APIC ICR

该超级调用允许客户机发送组播 IPI,在 64 位模式下每个超级调用最多 128 个目的地,在 32 位模式下每个超级调用最多 64 个 vCPU。目的地由前两个参数 (a0 和 a1) 中包含的位图表示。a0 的第 0 位对应于第三个参数 (a2) 中的 APIC ID,第 1 位对应于 APIC ID a2+1,依此类推。

返回成功发送 IPI 的 CPU 数量。

7. KVM_HC_SCHED_YIELD

架构:

x86

状态:

活跃

目的:

如果 IPI 目标 vCPU 被抢占,则使用超级调用进行让步

a0: 目标 APIC ID

使用示例:

当向 vCPU 发送 call-function IPI-many 时,如果任何 IPI 目标 vCPU 被抢占,则让步。

8. KVM_HC_MAP_GPA_RANGE

架构:

x86

状态:

活跃

目的:

请求 KVM 映射指定属性的 GPA 范围。

a0: 起始页的客户机物理地址 a1: 页数(4kb)(必须在 GPA 空间中连续) a2: 属性

其中“属性”
  • 位 3:0 - 首选页面大小编码 0 = 4kb, 1 = 2mb, 2 = 1gb, 等...

  • 位 4 - 明文 = 0, 加密 = 1

  • 位 63:5 - 保留(必须为零)

实现说明:此超级调用通过 KVM_CAP_EXIT_HYPERCALL 能力在用户空间中实现。用户空间必须在客户机 CPUID 中宣传 KVM_FEATURE_HC_MAP_GPA_RANGE 之前启用该能力。此外,如果客户机支持 KVM_FEATURE_MIGRATION_CONTROL,用户空间还必须设置 MSR 过滤器以处理对 MSR_KVM_MIGRATION_CONTROL 的写入。