KVM 特定的 MSRs

作者:

Glauber Costa <glommer@redhat.com>, Red Hat 公司, 2010

KVM 使用一些自定义 MSR 来处理某些请求。

自定义 MSR 有一个为其保留的范围,从 0x4b564d00 到 0x4b564dff。此区域之外也有 MSR,但它们已被弃用,不建议使用。

自定义 MSR 列表

当前支持的自定义 MSR 列表如下:

MSR_KVM_WALL_CLOCK_NEW

0x4b564d00

数据

内存区域的 4 字节对齐物理地址,该内存区域必须位于客户机 RAM 中。该内存区域预期将保存以下结构的副本:

struct pvclock_wall_clock {
       u32   version;
       u32   sec;
       u32   nsec;
 } __attribute__((__packed__));

其数据将由管理程序填充。管理程序只保证在 MSR 写入时更新此数据。如果用户希望多次可靠地查询此信息,则必须多次写入此 MSR。字段具有以下含义:

版本

客户机必须在获取时间信息前后检查版本,并确保它们既相等又是偶数。奇数版本表示正在进行更新。

启动时挂钟的秒数。

纳秒

启动时挂钟的纳秒数。

为了获取当前挂钟时间,需要加上 MSR_KVM_SYSTEM_TIME_NEW 中的 system_time。

请注意,尽管 MSR 是每个 CPU 的实体,但此特定 MSR 的效果是全局的。

在使用前,必须通过 0x4000001 cpuid 叶中的第 3 位检查此 MSR 的可用性。

MSR_KVM_SYSTEM_TIME_NEW

0x4b564d01

数据

内存区域的 4 字节对齐物理地址,该内存区域必须位于客户机 RAM 中,并且第 0 位是启用位。该内存区域预期将保存以下结构的副本:

struct pvclock_vcpu_time_info {
      u32   version;
      u32   pad0;
      u64   tsc_timestamp;
      u64   system_time;
      u32   tsc_to_system_mul;
      s8    tsc_shift;
      u8    flags;
      u8    pad[2];
} __attribute__((__packed__)); /* 32 bytes */

其数据将由管理程序定期填充。每个 VCPU 只需要一次写入或注册。此结构更新的间隔是任意的且取决于实现。管理程序可以随时更新此结构,直到向其写入任何 bit0 == 0 的值。

字段具有以下含义:

版本

客户机必须在获取时间信息前后检查版本,并确保它们既相等又是偶数。奇数版本表示正在进行更新。

tsc_timestamp

更新此结构时当前 VCPU 的 TSC 值。客户机可以从当前 TSC 中减去此值,以得出自结构更新以来的经过时间。

system_time

主机对单调时间的理解,包括此结构上次更新时的休眠时间。单位是纳秒。

tsc_to_system_mul

将 TSC 相关量转换为纳秒时使用的乘数

tsc_shift

将 TSC 相关量转换为纳秒时使用的移位。此移位将确保与 tsc_to_system_mul 的乘法不会溢出。正值表示左移,负值表示右移。

从 TSC 到纳秒的转换涉及额外向右移位 32 位。有了这些信息,客户机可以通过以下方式得出每个 CPU 的时间:

time = (current_tsc - tsc_timestamp)
if (tsc_shift >= 0)
        time <<= tsc_shift;
else
        time >>= -tsc_shift;
time = (time * tsc_to_system_mul) >> 32
time = time + system_time
标志

此字段中的位表示客户机和管理程序之间协调的扩展功能。特定标志的可用性必须在 0x40000001 cpuid 叶中检查。当前标志如下:

标志位

cpuid 位

含义

0

24

跨多个 CPU 进行的时间测量保证是单调的

1

不适用

客户机 vCPU 已被主机暂停。请参阅 api.txt 中的 4.70。

在使用前,必须通过 0x4000001 cpuid 叶中的第 3 位检查此 MSR 的可用性。

MSR_KVM_WALL_CLOCK

0x11

数据和功能

与 MSR_KVM_WALL_CLOCK_NEW 相同。请改用后者。

此 MSR 超出 KVM 保留范围,将来可能会被移除。其用法已被弃用。

在使用前,必须通过 0x4000001 cpuid 叶中的第 0 位检查此 MSR 的可用性。

MSR_KVM_SYSTEM_TIME

0x12

数据和功能

与 MSR_KVM_SYSTEM_TIME_NEW 相同。请改用后者。

此 MSR 超出 KVM 保留范围,将来可能会被移除。其用法已被弃用。

在使用前,必须通过 0x4000001 cpuid 叶中的第 0 位检查此 MSR 的可用性。

检测 kvmclock 存在的建议算法如下:

if (!kvm_para_available())    /* refer to cpuid.txt */
        return NON_PRESENT;

flags = cpuid_eax(0x40000001);
if (flags & 3) {
        msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
        msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
        return PRESENT;
} else if (flags & 0) {
        msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
        msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
        return PRESENT;
} else
        return NON_PRESENT;
MSR_KVM_ASYNC_PF_EN

0x4b564d02

数据

异步页错误 (APF) 控制 MSR。

第 63-6 位包含一个 64 字节内存区域的 64 字节对齐物理地址,该内存区域必须位于客户机 RAM 中。该内存预期将保存以下结构:

struct kvm_vcpu_pv_apf_data {
      /* Used for 'page not present' events delivered via #PF */
      __u32 flags;

      /* Used for 'page ready' events delivered via interrupt notification */
      __u32 token;

      __u8 pad[56];
};

MSR 的第 5-4 位是保留的,应为零。第 0 位在 VCPU 上启用异步页错误时设置为 1,禁用时设置为 0。如果 VCPU 在 cpl == 0 时可以注入异步页错误,则第 1 位为 1。如果异步页错误作为 #PF vmexits 传递给 L1,则第 2 位为 1。仅当 CPUID 中存在 KVM_FEATURE_ASYNC_PF_VMEXIT 时才能设置第 2 位。第 3 位启用基于中断的“页面就绪”事件传递。仅当 CPUID 中存在 KVM_FEATURE_ASYNC_PF_INT 时才能设置第 3 位。

“页面不存在”事件目前总是作为合成的 #PF 异常传递。在这些事件传递期间,APF CR2 寄存器包含一个令牌,该令牌将用于在缺失页面可用时通知客户机。此外,为了区分真实的 #PF 和 APF,管理程序将在注入时写入 64 字节内存位置(“flags”)的前 4 字节。目前只支持“flags”的第一位,当设置时,它表示客户机正在处理异步的“页面不存在”事件。如果在页错误期间 APF“flags”为“0”,则表示这是常规页错误。客户机在处理完 #PF 异常后应清除“flags”,以便可以传递下一个事件。

注意,由于 APF“页面不存在”事件与常规页错误使用相同的异常向量,客户机在执行可能生成常规页错误的操作之前,必须将“flags”重置为“0”。

64 字节内存位置(“token”)的第 4-7 字节将由管理程序在 APF“页面就绪”事件注入时写入。这些字节的内容是先前作为“页面不存在”事件在 CR2 中传递的令牌。该事件表示页面现在可用。客户机在处理完“页面就绪”事件并清除该位置后,应将“0”写入“token”,并将“1”写入 MSR_KVM_ASYNC_PF_ACK;写入 MSR 会强制 KVM 重新扫描其队列并传递下一个挂起的通知。

注意,在 MSR_KVM_ASYNC_PF_EN 中启用 APF 机制之前,需要写入指定“页面就绪”APF 传递中断向量的 MSR_KVM_ASYNC_PF_INT MSR,否则可能会注入中断 #0。仅当 CPUID 中存在 KVM_FEATURE_ASYNC_PF_INT 时,此 MSR 才可用。

注意,以前,“页面就绪”事件通过与“页面不存在”事件相同的 #PF 异常传递,但现在这已被弃用。如果未设置第 3 位(基于中断的传递),则不传递 APF 事件。

如果在存在未决 APF 的情况下禁用 APF,则它们将不会被传递。

目前,“页面就绪”APF 事件将始终在与“页面不存在”事件相同的 vCPU 上传递,但客户机不应依赖此行为。

MSR_KVM_STEAL_TIME

0x4b564d03

数据

内存区域的 64 字节对齐物理地址,该内存区域必须位于客户机 RAM 中,并且第 0 位是启用位。该内存区域预期将保存以下结构的副本:

struct kvm_steal_time {
      __u64 steal;
      __u32 version;
      __u32 flags;
      __u8  preempted;
      __u8  u8_pad[3];
      __u32 pad[11];
}

其数据将由管理程序定期填充。每个 VCPU 只需要一次写入或注册。此结构更新的间隔是任意的且取决于实现。管理程序可以随时更新此结构,直到向其写入任何 bit0 == 0 的值。客户机必须确保此结构初始化为零。

字段具有以下含义:

版本

一个序列计数器。换句话说,客户机必须在获取时间信息前后检查此字段,并确保它们既相等又是偶数。奇数版本表示正在进行更新。

标志

此时,始终为零。将来可能用于指示此结构中的更改。

steal

此 vCPU 未运行的时间量,以纳秒为单位。vCPU 处于空闲状态的时间将不报告为窃取时间。

被抢占

指示拥有此结构的 vCPU 是否正在运行。非零值表示 vCPU 已被抢占。零表示 vCPU 未被抢占。注意,如果管理程序不支持此字段,则它始终为零。

MSR_KVM_EOI_EN

0x4b564d04

数据

当在 VCPU 上启用 PV 中断结束时,第 0 位为 1;禁用时为 0。第 1 位是保留的,必须为零。当启用 PV 中断结束时(第 0 位设置),第 63-2 位包含一个 4 字节内存区域的 4 字节对齐物理地址,该内存区域必须位于客户机 RAM 中且必须清零。

4 字节内存位置的第一个,即最低有效位将由管理程序写入,通常在中断注入时。值为 1 意味着客户机可以跳过向 APIC 写入 EOI(使用 MSR 或 MMIO 写入);相反,只需通过清除客户机内存中的位来发出 EOI 信号就足够了——此位置稍后将由管理程序轮询。值为 0 意味着需要写入 EOI。

客户机始终可以安全地忽略此优化并无论如何执行 APIC EOI 写入。

管理程序保证仅在当前 VCPU 上下文中修改此最低有效位,这意味着客户机无需使用锁前缀或内存排序原语与管理程序同步。

然而,管理程序可以随时设置和清除此内存位:因此,为确保管理程序不会中断客户机并在客户机测试该位以检测是否可以跳过 EOI APIC 写入与客户机清除该位以向管理程序发出 EOI 信号之间的时间窗口中清除内存区域中的最低有效位,客户机必须使用单个 CPU 指令(例如测试并清除,或比较并交换)同时读取和清除内存区域中的最低有效位。

MSR_KVM_POLL_CONTROL

0x4b564d05

控制主机端轮询。

数据

第 0 位启用 (1) 或禁用 (0) 主机端 HLT 轮询逻辑。

KVM 客户机可以请求主机不轮询 HLT,例如,如果它们自己正在执行轮询。

MSR_KVM_ASYNC_PF_INT

0x4b564d06

数据

第二个异步页错误 (APF) 控制 MSR。

第 0-7 位:用于传递“页面就绪”APF 事件的 APIC 向量。第 8-63 位:保留。

用于异步“页面就绪”通知传递的中断向量。在 MSR_KVM_ASYNC_PF_EN 中启用异步页错误机制之前,必须设置此向量。仅当 CPUID 中存在 KVM_FEATURE_ASYNC_PF_INT 时,此 MSR 才可用。

MSR_KVM_ASYNC_PF_ACK

0x4b564d07

数据

异步页错误 (APF) 确认。

当客户机处理完“页面就绪”APF 事件并清除“struct kvm_vcpu_pv_apf_data”中的“token”字段后,它应该向 MSR 的第 0 位写入“1”,这会使主机重新扫描其队列并检查是否有更多通知待处理。仅当 CPUID 中存在 KVM_FEATURE_ASYNC_PF_INT 时,此 MSR 才可用。

MSR_KVM_MIGRATION_CONTROL

0x4b564d08

数据

如果 CPUID 中存在 KVM_FEATURE_MIGRATION_CONTROL,则此 MSR 可用。第 0 位表示是否允许客户机的实时迁移。

当客户机启动时,如果客户机有加密内存,则第 0 位为 0;如果客户机没有加密内存,则第 0 位为 1。如果客户机使用 KVM_HC_MAP_GPA_RANGE hypercall 向主机通信页加密状态,则它可以设置此 MSR 中的第 0 位以允许客户机的实时迁移。