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 位以允許客戶機的即時遷移。