Linux KVM 虚拟机调用

X86

KVM 虚拟机调用具有 vmcall 或 vmmcall 指令的三字节序列。虚拟机监控程序可以用保证支持的指令替换它。

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

S390

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

S390 使用诊断指令作为虚拟机调用 (0x500),并在 R1 中包含虚拟机调用号。

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

PowerPC

它使用 R3-R10 和 R11 中的虚拟机调用号。R4-R11 用作输出寄存器。返回值放在 R3 中。

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

MIPS

KVM 虚拟机调用使用代码为 0 的 HYPCALL 指令和 $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:用于计算 sec/nsec 对的客户机 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 的写入。