[PATCH V2 6/7] hv: remove CPU frequency control from guests


Zhou, Wu
 

The design of ACRN CPU performance management is to let hardware
do the autonomous frequency selection(or set to a fixed value),
and remove guest's ability to control CPU frequency.

This patch is to remove guest's ability to control CPU frequency by
removing the guests' HWP/EIST CPUID bits and blocking the related MSR
accesses. Including:
- Hide CPUID.06H:EAX[7..11] (HWP)
- Hide CPUID.01H:ECX[7] (EIST)
- Inject #GP(0) upon accesses to MSR_IA32_PM_ENABLE,
MSR_IA32_HWP_CAPABILITIES, MSR_IA32_HWP_REQUEST,
MSR_IA32_HWP_STATUS, MSR_IA32_HWP_INTERRUPT,
MSR_IA32_HWP_REQUEST_PKG
- Intercept the write access to MSR_IA32_PERF_CTL

Signed-off-by: Wu Zhou <wu.zhou@...>
---
hypervisor/arch/x86/guest/vcpuid.c | 8 ++++++++
hypervisor/arch/x86/guest/vmsr.c | 25 +++++++++++++++++++++----
hypervisor/include/arch/x86/asm/cpuid.h | 10 ++++++++++
3 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/hypervisor/arch/x86/guest/vcpuid.c b/hypervisor/arch/x86/guest/vcpuid.c
index 580098719..d73cf7ae3 100644
--- a/hypervisor/arch/x86/guest/vcpuid.c
+++ b/hypervisor/arch/x86/guest/vcpuid.c
@@ -115,6 +115,12 @@ static void init_vcpuid_entry(uint32_t leaf, uint32_t subleaf,
entry->flags = flags;

switch (leaf) {
+
+ case 0x06U:
+ cpuid_subleaf(leaf, subleaf, &entry->eax, &entry->ebx, &entry->ecx, &entry->edx);
+ entry->eax &= ~(CPUID_EAX_HWP | CPUID_EAX_HWP_N | CPUID_EAX_HWP_AW | CPUID_EAX_HWP_EPP | CPUID_EAX_HWP_PLR);
+ break;
+
case 0x07U:
if (subleaf == 0U) {
uint64_t cr4_reserved_mask = get_cr4_reserved_bits();
@@ -627,6 +633,8 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
/* mask Safer Mode Extension */
*ecx &= ~CPUID_ECX_SMX;

+ *ecx &= ~CPUID_ECX_EST;
+
/* mask SDBG for silicon debug */
*ecx &= ~CPUID_ECX_SDBG;

diff --git a/hypervisor/arch/x86/guest/vmsr.c b/hypervisor/arch/x86/guest/vmsr.c
index 6509d34b0..163e24db0 100644
--- a/hypervisor/arch/x86/guest/vmsr.c
+++ b/hypervisor/arch/x86/guest/vmsr.c
@@ -256,6 +256,27 @@ static const uint32_t unsupported_msrs[] = {
MSR_IA32_PL2_SSP,
MSR_IA32_PL3_SSP,
MSR_IA32_INTERRUPT_SSP_TABLE_ADDR,
+
+ /*
+ * HWP disabled:
+ * CPUID.06H.EAX[7]
+ * CPUID.06H.EAX[9]
+ * CPUID.06H:EAX[10]
+ */
+ MSR_IA32_PM_ENABLE,
+ MSR_IA32_HWP_CAPABILITIES,
+ MSR_IA32_HWP_REQUEST,
+ MSR_IA32_HWP_STATUS,
+ /*
+ * HWP_Notification disabled:
+ * CPUID.06H:EAX[8]
+ */
+ MSR_IA32_HWP_INTERRUPT,
+ /*
+ * HWP_package_level disabled:
+ * CPUID.06H:EAX[11]
+ */
+ MSR_IA32_HWP_REQUEST_PKG,
};

/* emulated_guest_msrs[] shares same indexes with array vcpu->arch->guest_msrs[] */
@@ -1001,10 +1022,6 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
}
case MSR_IA32_PERF_CTL:
{
- if (validate_pstate(vcpu->vm, v) != 0) {
- break;
- }
- msr_write(msr, v);
break;
}
case MSR_IA32_PAT:
diff --git a/hypervisor/include/arch/x86/asm/cpuid.h b/hypervisor/include/arch/x86/asm/cpuid.h
index 491758bab..929ec6960 100644
--- a/hypervisor/include/arch/x86/asm/cpuid.h
+++ b/hypervisor/include/arch/x86/asm/cpuid.h
@@ -72,6 +72,16 @@
#define CPUID_EDX_TM1 (1U<<29U)
#define CPUID_EDX_IA64 (1U<<30U)
#define CPUID_EDX_PBE (1U<<31U)
+/* CPUID.06H:EAX.HWP */
+#define CPUID_EAX_HWP (1U<<7U)
+/* CPUID.06H:EAX.HWP_Notification */
+#define CPUID_EAX_HWP_N (1U<<8U)
+/* CPUID.06H:EAX.HWP_Activity_Window */
+#define CPUID_EAX_HWP_AW (1U<<9U)
+/* CPUID.06H:EAX.HWP_Energy_Performance_Preference */
+#define CPUID_EAX_HWP_EPP (1U<<10U)
+/* CPUID.06H:EAX.HWP_Package_Level_Request */
+#define CPUID_EAX_HWP_PLR (1U<<11U)
/* CPUID.07H:EBX.FSGSBASE*/
#define CPUID_EBX_FSGSBASE (1U<<0U)
/* CPUID.07H:EBX.TSC_ADJUST*/
--
2.25.1


Eddie Dong
 

-----Original Message-----
From: acrn-dev@... <acrn-dev@...> On
Behalf Of Zhou, Wu
Sent: Friday, September 2, 2022 7:52 AM
To: acrn-dev@...
Cc: Zhou, Wu <wu.zhou@...>
Subject: [acrn-dev] [PATCH V2 6/7] hv: remove CPU frequency control from
guests

The design of ACRN CPU performance management is to let hardware do the
autonomous frequency selection(or set to a fixed value), and remove guest's
ability to control CPU frequency.

This patch is to remove guest's ability to control CPU frequency by removing
the guests' HWP/EIST CPUID bits and blocking the related MSR accesses.
Including:
- Hide CPUID.06H:EAX[7..11] (HWP)
- Hide CPUID.01H:ECX[7] (EIST)
- Inject #GP(0) upon accesses to MSR_IA32_PM_ENABLE,
MSR_IA32_HWP_CAPABILITIES, MSR_IA32_HWP_REQUEST,
MSR_IA32_HWP_STATUS, MSR_IA32_HWP_INTERRUPT,
MSR_IA32_HWP_REQUEST_PKG
- Intercept the write access to MSR_IA32_PERF_CTL

Signed-off-by: Wu Zhou <wu.zhou@...>
---
hypervisor/arch/x86/guest/vcpuid.c | 8 ++++++++
hypervisor/arch/x86/guest/vmsr.c | 25 +++++++++++++++++++++----
hypervisor/include/arch/x86/asm/cpuid.h | 10 ++++++++++
3 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/hypervisor/arch/x86/guest/vcpuid.c
b/hypervisor/arch/x86/guest/vcpuid.c
index 580098719..d73cf7ae3 100644
--- a/hypervisor/arch/x86/guest/vcpuid.c
+++ b/hypervisor/arch/x86/guest/vcpuid.c
@@ -115,6 +115,12 @@ static void init_vcpuid_entry(uint32_t leaf, uint32_t
subleaf,
entry->flags = flags;

switch (leaf) {
+
+ case 0x06U:
+ cpuid_subleaf(leaf, subleaf, &entry->eax, &entry->ebx,
&entry->ecx, &entry->edx);
+ entry->eax &= ~(CPUID_EAX_HWP | CPUID_EAX_HWP_N |
CPUID_EAX_HWP_AW | CPUID_EAX_HWP_EPP | CPUID_EAX_HWP_PLR);
+ break;
+
case 0x07U:
if (subleaf == 0U) {
uint64_t cr4_reserved_mask =
get_cr4_reserved_bits(); @@ -627,6 +633,8 @@ static void
guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx
/* mask Safer Mode Extension */
*ecx &= ~CPUID_ECX_SMX;

+ *ecx &= ~CPUID_ECX_EST;
+
/* mask SDBG for silicon debug */
*ecx &= ~CPUID_ECX_SDBG;

diff --git a/hypervisor/arch/x86/guest/vmsr.c
b/hypervisor/arch/x86/guest/vmsr.c
index 6509d34b0..163e24db0 100644
--- a/hypervisor/arch/x86/guest/vmsr.c
+++ b/hypervisor/arch/x86/guest/vmsr.c
@@ -256,6 +256,27 @@ static const uint32_t unsupported_msrs[] = {
MSR_IA32_PL2_SSP,
MSR_IA32_PL3_SSP,
MSR_IA32_INTERRUPT_SSP_TABLE_ADDR,
+
+ /*
+ * HWP disabled:
+ * CPUID.06H.EAX[7]
+ * CPUID.06H.EAX[9]
+ * CPUID.06H:EAX[10]
+ */
+ MSR_IA32_PM_ENABLE,
+ MSR_IA32_HWP_CAPABILITIES,
+ MSR_IA32_HWP_REQUEST,
+ MSR_IA32_HWP_STATUS,
+ /*
+ * HWP_Notification disabled:
+ * CPUID.06H:EAX[8]
+ */
+ MSR_IA32_HWP_INTERRUPT,
+ /*
+ * HWP_package_level disabled:
+ * CPUID.06H:EAX[11]
+ */
+ MSR_IA32_HWP_REQUEST_PKG,
};

/* emulated_guest_msrs[] shares same indexes with array vcpu->arch-
guest_msrs[] */ @@ -1001,10 +1022,6 @@ int32_t
wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
}
case MSR_IA32_PERF_CTL:
{
- if (validate_pstate(vcpu->vm, v) != 0) {
- break;
- }
- msr_write(msr, v);

So you ignore guest write, but let guest readback the physical value?

SDM says:
Use CPUID to check the P-State hardware coordination feedback capability bit. CPUID.06H.ECX[Bit 0] = 1
indicates IA32_MPERF MSR and IA32_APERF MSR are present.

Do we need to remove those MSRs too (inject #GP)?

break;
}
case MSR_IA32_PAT:
diff --git a/hypervisor/include/arch/x86/asm/cpuid.h
b/hypervisor/include/arch/x86/asm/cpuid.h
index 491758bab..929ec6960 100644
--- a/hypervisor/include/arch/x86/asm/cpuid.h
+++ b/hypervisor/include/arch/x86/asm/cpuid.h
@@ -72,6 +72,16 @@
#define CPUID_EDX_TM1 (1U<<29U)
#define CPUID_EDX_IA64 (1U<<30U)
#define CPUID_EDX_PBE (1U<<31U)
+/* CPUID.06H:EAX.HWP */
+#define CPUID_EAX_HWP (1U<<7U)
+/* CPUID.06H:EAX.HWP_Notification */
+#define CPUID_EAX_HWP_N (1U<<8U)
+/* CPUID.06H:EAX.HWP_Activity_Window */
+#define CPUID_EAX_HWP_AW (1U<<9U)
+/* CPUID.06H:EAX.HWP_Energy_Performance_Preference */
+#define CPUID_EAX_HWP_EPP (1U<<10U)
+/* CPUID.06H:EAX.HWP_Package_Level_Request */
+#define CPUID_EAX_HWP_PLR (1U<<11U)
/* CPUID.07H:EBX.FSGSBASE*/
#define CPUID_EBX_FSGSBASE (1U<<0U)
/* CPUID.07H:EBX.TSC_ADJUST*/
--
2.25.1