計時器
Hypervisor 提供簡單的計時服務。 這些是以固定速率參考時間來源為基礎, (通常是 x64 系統上的 ACPI 計時器) 。
提供下列計時器服務:
- 每個分割區參考時間計數器。
- 每個虛擬處理器有四個綜合計時器。 每個綜合計時器都是單次或定期計時器,可在訊息到期時傳遞訊息或判斷提示中斷。
- 每個虛擬處理器一個虛擬 APIC 計時器。
- 分割區參考時間啟發,根據主機平臺對非變異時間戳記計數器的支援, (iTSC) 。
Hypervisor 會維護每個分割區參考時間計數器。 它具有連續存取的特性,它會以嚴格單純的方式傳回 (時間) 值,如分割區的任何和所有虛擬處理器所見。 此外,參考計數器是速率常數,不受處理器或匯流排速度轉換或深層處理器省電狀態影響。 建立資料分割時,分割區的參考時間計數器會初始化為零。 所有分割區的參考計數器都會以相同的速率計算,但隨時都會有不同的絕對值,因為分割區會有不同的建立時間。
只要至少有一個虛擬處理器未明確暫停,參考計數器就會繼續計算。
您可以透過整個分割區的 MSR 來存取分割區的參考計數器。
MSR 位址 | 註冊名稱 | 描述 |
---|---|---|
0x40000020 | HV_X64_MSR_TIME_REF_COUNT | 全分割) (時間參考計數 |
建立分割區時,TIME_REF_COUNT MSR 的值會設定為 0x0000000000000000。 虛擬處理器無法修改此值。 任何嘗試寫入它都會導致#GP錯誤。
分割區參考時間啟發式會將參考時間來源呈現給不需要攔截到 Hypervisor 的資料分割。 只有當基礎平臺支援非變異處理器時間戳記計數器時,才會提供此啟發式, (TSC) 或 iTSC。 在這類平臺中,處理器 TSC 頻率會維持不變,不論處理器時鐘頻率的變更為何,因為使用電源管理狀態,例如 ACPI 處理器效能狀態、處理器閒置睡眠狀態 (ACPI C 狀態) 等等。
分割區參考時間啟用會使用虛擬 TSC 值、位移和乘數,讓客體分割區在 100nS 單位中建立分割區之後計算標準化參考時間。 此機制也可讓客體分割區以不可部分完成的方式計算客體分割移轉至具有不同 TSC 速率的平臺時的參考時間,並提供後援機制來支援移轉至沒有固定速率 TSC 功能的平臺。
這項設施並非用來使用時鐘時間的來源,因為使用此設施計算的參考時間在儲存客體分割區直到後續還原為止,才會停止。
Hypervisor 提供整個分割區的虛擬參考 TSC 頁面,該頁面會重迭在分割區的 GPA 空間上。 資料分割的參考時間戳記計數器頁面是透過參考 TSC MSR 來存取。
參考 TSC 頁面是使用下列結構來定義:
typedef struct
{
volatile UINT32 TscSequence;
UINT32 Reserved1;
volatile UINT64 TscScale;
volatile INT64 TscOffset;
UINT64 Reserved2[509];
} HV_REFERENCE_TSC_PAGE;
想要存取其參考 TSC 頁面的來賓必須使用下列模型特定暫存器 (MSR) 。 擁有 AccessPartitionReferenceTsc 許可權的資料分割可能會存取 MSR。
MSR 位址 | 註冊名稱 | 描述 |
---|---|---|
0x40000021 | HV_X64_MSR_REFERENCE_TSC | 參考 TSC 頁面 |
Bits | 描述 | 屬性 |
---|---|---|
63:12 | GPA 頁碼 | 讀取/寫入 |
11:1 | 應保留 RsvdP (值) | 讀取/寫入 |
0 | 啟用 | 讀取/寫入 |
在客體分割建立期間,參考 TSC MSR 的值會0x0000000000000000。 因此,預設會停用參考 TSC 頁面。 來賓必須藉由設定位 0 來啟用參考 TSC 頁面。 如果指定的基底位址超出分割區 GPA 空間的結尾,則來賓將無法存取參考 TSC 頁面。 修改暫存器時,來賓應保留保留位的值 (1 到 11) ,以供日後相容性使用。
分割區參考時間是由下列公式計算:
ReferenceTime = ( (VirtualTsc * TscScale) >> 64) + TscOffset
乘法是 64 位乘法,會產生 128 位數位,然後向右移 64 次以取得高 64 位。
TscScale 值可用來調整跨移轉事件的虛擬 TSC 值,以降低從一個平臺到另一個平臺的 TSC 頻率變更。
如果小數位數和/或位移欄位在儲存/還原或即時移轉期間變更,TscSequence 值可用來同步存取覺察型參考時間。 此欄位會當做序號,每當修改小數位數和/或位移欄位時,就會遞增。 0x0的特殊值可用來指出此設施不再是可靠的參考時間來源,而且 VM 必須回復到不同的來源。
使用此啟發式計算資料分割參考時間的建議程式碼如下所示:
do
{
StartSequence = ReferenceTscPage->TscSequence;
if (StartSequence == 0)
{
// 0 means that the Reference TSC enlightenment is not available at
// the moment, and the Reference Time can only be obtained from
// reading the Reference Counter MSR.
ReferenceTime = rdmsr(HV_X64_MSR_TIME_REF_COUNT);
return ReferenceTime;
}
Tsc = rdtsc();
// Assigning Scale and Offset should neither happen before
// setting StartSequence, nor after setting EndSequence.
Scale = ReferenceTscPage->TscScale;
Offset = ReferenceTscPage->TscOffset;
EndSequence = ReferenceTscPage->TscSequence;
} while (EndSequence != StartSequence);
// The result of the multiplication is treated as a 128-bit value.
ReferenceTime = ((Tsc * Scale) >> 64) + Offset;
return ReferenceTime;
綜合計時器提供一種機制,可在未來的某個指定時間之後產生中斷。 同時支援一次性和定期計時器。 綜合計時器會根據設定方式,將訊息傳送至指定的 SynIC SINTx (綜合中斷來源) ,或判斷提示中斷。
Hypervisor 保證計時器到期訊號永遠不會在到期時間之前傳遞。 訊號可能會在到期時間之後的任何時間送達。
Hypervisor 會嘗試定期發出計時器訊號。 不過,如果用來發出到期訊號的虛擬處理器無法使用,某些計時器到期可能會延遲。 虛擬處理器可能無法使用,因為 (在攔截處理期間) ,或因為 Hypervisor 的排程器決定虛擬處理器不應該在邏輯 (處理器上排程,例如,因為另一個虛擬處理器正在使用邏輯處理器,或虛擬處理器已超過其配額) 。
如果虛擬處理器在很長的時間內無法使用,可能會遺漏完整計時器期間。 在此情況下,Hypervisor 會使用兩種技術之一。
第一個技術牽涉到計時器期間變雜,實際上會縮短期間,直到計時器「趕上」為止。 如果遺漏大量的計時器訊號,Hypervisor 可能無法使用期間調節來補償。 在此情況下,可能會完全略過某些計時器到期訊號。
對於標示為延遲的計時器,Hypervisor 會使用第二個技術來處理虛擬處理器長時間無法使用的情況。 在此情況下,計時器訊號會延後,直到此虛擬處理器可供使用為止。 如果在下一個計時器到期前不久才會變成可用,則會完全略過。
綜合和虛擬化計時器會在指定的到期時間或附近產生中斷。 由於硬體和其他排程互動,中斷可能會延遲。 任何一組計時器之間都不能假設任何排序。
「直接」綜合計時器會在計時器到期時判斷提示中斷,而不是將訊息傳送至 SynIc 綜合中斷來源。 綜合計時器設定為「直接」模式,方法是設定綜合計時器組態 MSR 的 「DirectMode」 欄位。 「ApicVector」 欄位會控制計時器到期時判斷提示的中斷向量。
綜合計時器是使用與每個虛擬處理器相關聯的模型特定暫存器, (MSR) 來設定。 四個綜合計時器的每一個都有一組相關聯的 MSR。
MSR 位址 | 註冊名稱 | 描述 |
---|---|---|
0x400000B0 | HV_X64_MSR_STIMER0_CONFIG | 綜合計時器 0 的組態暫存器。 |
0x400000B1 | HV_X64_MSR_STIMER0_COUNT | 綜合計時器 0 的到期時間或期間。 |
0x400000B2 | HV_X64_MSR_STIMER1_CONFIG | 綜合計時器 1 的組態暫存器。 |
0x400000B3 | HV_X64_MSR_STIMER1_COUNT | 綜合計時器 1 的到期時間或期間。 |
0x400000B4 | HV_X64_MSR_STIMER2_CONFIG | 綜合計時器 2 的組態暫存器。 |
0x400000B5 | HV_X64_MSR_STIMER2_COUNT | 綜合計時器 2 的到期時間或期間。 |
0x400000B6 | HV_X64_MSR_STIMER3_CONFIG | 綜合計時器 3 的組態暫存器。 |
0x400000B7 | HV_X64_MSR_STIMER4_COUNT | 綜合計時器 3 的到期時間或期間。 |
Bits | 描述 | 屬性 |
---|---|---|
63:20 | RsvdZ (值應該設定為零) | 讀取/寫入 |
19:16 | SINTx - 綜合中斷來源 | 讀取/寫入 |
15:13 | RsvdZ (值應該設定為零) | 讀取/寫入 |
12 | 直接模式 - 計時器到期時判斷提示和中斷。 | 讀取/寫入 |
11:4 | ApicVector - 控制直接模式中判斷提示的中斷向量 | 讀取/寫入 |
3 | AutoEnable - 如果寫入對應的計數器隱含地導致啟用計時器,請設定 | 讀取/寫入 |
2 | 延遲 - 設定計時器是否延遲 | 讀取/寫入 |
1 | 定期 - 設定計時器是否為定期 | 讀取/寫入 |
0 | 已啟用 - 如果已啟用計時器,請設定 | 讀取/寫入 |
建立並重設虛擬處理器時,) 暫存器的所有HV_X64_MSR_STIMERx_CONFIG (綜合計時器組態值都會設定為 0x0000000000000000。 因此,預設會停用所有綜合計時器。
如果已設定 AutoEnable,則將非零值寫入對應的計數暫存器會導致設定並啟用計數器。 否則,應該在撰寫對應的計數暫存器之後設定 Enable,以啟動計數器。 如需計數暫存器的相關資訊,請參閱下一節。
當單次計時器過期時,它會自動標示為已停用。 定期計時器會保持啟用狀態,直到明確停用為止。
如果啟用單次,且指定的計數在過去已過期,則會立即到期。
啟用的計時器 (未處於直接模式) ,不允許將 SINTx 欄位設定為零。 如果嘗試,計時器將會標示為已停用 (,也就是立即清除位 0) 。
撰寫已啟用之計時器的組態暫存器可能會導致未定義的行為。 例如,只將計時器從一次性變更為定期,可能不會產生預期的內容。 變更任何其他屬性之前,應該一律停用計時器。
Bits | 描述 | 屬性 |
---|---|---|
63:0 | Count — 單次計時器的到期時間、定期計時器的持續時間 | 讀取/寫入 |
程式設計為 Count 暫存器的值是以 100 奈秒單位測量的時間值。 將值零寫入 Count 暫存器將會停止計數器,藉此停用計時器,而與組態暫存器中的 AutoEnable 設定無關。
請注意,允許計數暫存器包裝。 不論任何計時器屬性為何,包裝都不會影響計時器的行為。
針對單次計時器,它代表絕對計時器到期時間。 當分割區的參考計數器等於或大於指定的計數值時,計時器就會過期。
針對定期計時器,計數代表計時器的期間。 第一個期間是從啟用綜合計時器時開始。
計時器事件引發時會傳送計時器到期訊息。 如需訊息承載的定義,請參閱 HV_TIMER_MESSAGE_PAYLOAD 。
如果已設定 Hypervisor 功能識別 CPUID 分葉0x40000003中的 AccessSyntheticTimerRegs 許可權和 EDX 位 23,可以使用綜合Time-Unhalted計時器 MSR。 客體軟體可以程式設計綜合時間未擷取計時器,以在以 100ns 單位執行指定的時間量之後產生定期中斷。 當中斷引發時,VP 輔助頁面中的 SyntheticTimeUnhaltedTimerExpired 欄位將會設定為 TRUE。 客體軟體可能會將此欄位重設為 FALSE。 不同于架構效能計數器,綜合計時器永遠不會由 Hypervisor 重設,並在中斷之間持續執行。 Vectors ==2 會傳送 NMI,其他向量則傳送固定中斷。
不同于客體停止時累積時間的一般綜合計時器 (,例如:閒置) ,綜合Time-Unhalted計時器只會在來賓停止時累積時間。
MSR 位址 | 註冊名稱 | 描述 |
---|---|---|
0x40000114 | HV_X64_MSR_STIME_UNHALTED_TIMER_CONFIG | 綜合Time-Unhalted計時器設定 MSR |
0x40000115 | HV_X64_MSR_STIME_UNHALTED_TIMER_COUNT | 綜合Time-Unhalted計時器計數 MSR |
Bits | 描述 | 屬性 |
---|---|---|
63:9 | RsvdZ (值應該設定為零) | 讀取/寫入 |
8 | 啟用 | 讀取/寫入 |
7:0 | 向量 | 讀取/寫入 |
Bits | 描述 | 屬性 |
---|---|---|
63:0 | 100 ns 單位的定期中斷速率 | 讀取/寫入 |