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 CPUIDs and blocking the related MSR accesses. Including: - Remove CPUID.06H:EAX[7..11] (HWP) - Remove 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 - Emulate MSR_IA32_PERF_CTL. Value written to MSR_IA32_PERF_CTL is just stored for reading. This is like how the native environment would behavior when EIST is disabled from BIOS. - Emulate MSR_IA32_PERF_STATUS by filling it with base frequency state. This is consistent with Windows, which displays current frequency as base frequency when running in VM. - Hide the IA32_MISC_ENABLE bit 16 (EIST enable) from guests. This bit is dependent to CPUID.01H:ECX[7] according to SDM. - Remove CPID.06H:ECX[0] (hardware coordination feedback) - Inject #GP(0) upon accesses to IA32_MPERF, IA32_APERF Also DM do not need to generate _PSS/_PPC for post-launched VMs anymore. This is done by letting hypercall HC_PM_GET_CPU_STATE sub command ACRN_PMCMD_GET_PX_CNT and ACRN_PMCMD_GET_PX_DATA return (-1). Tracked-On: #8168 Signed-off-by: Wu Zhou <wu.zhou@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
f0eddc6a4c
commit
6a430de814
|
@ -115,6 +115,13 @@ 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);
|
||||
entry->ecx &= ~CPUID_ECX_HCFC;
|
||||
break;
|
||||
|
||||
case 0x07U:
|
||||
if (subleaf == 0U) {
|
||||
uint64_t cr4_reserved_mask = get_cr4_reserved_bits();
|
||||
|
@ -627,6 +634,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;
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@ static void init_guest_vmx(struct acrn_vcpu *vcpu, uint64_t cr0, uint64_t cr3,
|
|||
/* init guest ia32_misc_enable value for guest read */
|
||||
vcpu_set_guest_msr(vcpu, MSR_IA32_MISC_ENABLE, msr_read(MSR_IA32_MISC_ENABLE));
|
||||
|
||||
vcpu_set_guest_msr(vcpu, MSR_IA32_PERF_CTL, msr_read(MSR_IA32_PERF_CTL));
|
||||
|
||||
/* fixed values */
|
||||
exec_vmwrite32(VMX_GUEST_IA32_SYSENTER_CS, 0U);
|
||||
exec_vmwrite(VMX_GUEST_IA32_SYSENTER_ESP, 0UL);
|
||||
|
|
|
@ -51,6 +51,7 @@ static uint32_t emulated_guest_msrs[NUM_EMULATED_MSRS] = {
|
|||
MSR_IA32_BIOS_SIGN_ID,
|
||||
MSR_IA32_TIME_STAMP_COUNTER,
|
||||
MSR_IA32_APIC_BASE,
|
||||
MSR_IA32_PERF_STATUS,
|
||||
MSR_IA32_PERF_CTL,
|
||||
MSR_IA32_FEATURE_CONTROL,
|
||||
|
||||
|
@ -256,6 +257,29 @@ 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,
|
||||
/* Hardware Coordination Feedback Capability disabled:
|
||||
* CPUID.06H:ECX[0]
|
||||
*/
|
||||
MSR_IA32_MPERF,
|
||||
MSR_IA32_APERF,
|
||||
};
|
||||
|
||||
/* emulated_guest_msrs[] shares same indexes with array vcpu->arch->guest_msrs[] */
|
||||
|
@ -550,6 +574,26 @@ static int32_t write_pat_msr(struct acrn_vcpu *vcpu, uint64_t value)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief get emulated IA32_PERF_STATUS reg value
|
||||
*
|
||||
* Use the base frequency state of pCPU as the emulated reg field:
|
||||
* - IA32_PERF_STATUS[15:0] Current performance State Value
|
||||
*
|
||||
* Assuming (base frequency ratio << 8) is a valid state value for all CPU models.
|
||||
*/
|
||||
static uint64_t get_perf_status(void)
|
||||
{
|
||||
uint32_t eax, ecx, unused;
|
||||
/*
|
||||
* CPUID.16H:eax[15:0] Base CPU Frequency (MHz)
|
||||
* CPUID.16H:ecx[15:0] Bus Frequency (MHz)
|
||||
* ratio = CPU_frequency/bus_frequency
|
||||
*/
|
||||
cpuid_subleaf(0x16U, 0U, &eax, &unused, &ecx, &unused);
|
||||
return (uint64_t)(((eax/ecx) & 0xFFU) << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @pre vcpu != NULL
|
||||
*/
|
||||
|
@ -624,9 +668,14 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||
v = get_microcode_version();
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_PERF_STATUS:
|
||||
{
|
||||
v = get_perf_status();
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_PERF_CTL:
|
||||
{
|
||||
v = msr_read(msr);
|
||||
v = vcpu_get_guest_msr(vcpu, MSR_IA32_PERF_CTL);
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_PAT:
|
||||
|
@ -664,6 +713,8 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||
case MSR_IA32_MISC_ENABLE:
|
||||
{
|
||||
v = vcpu_get_guest_msr(vcpu, MSR_IA32_MISC_ENABLE);
|
||||
/* As CPUID.01H:ECX[7] is removed from guests, guests should not see EIST enable bit. */
|
||||
v &= ~MSR_IA32_MISC_ENABLE_EIST;
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_SGXLEPUBKEYHASH0:
|
||||
|
@ -999,12 +1050,13 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_PERF_STATUS:
|
||||
{
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_PERF_CTL:
|
||||
{
|
||||
if (validate_pstate(vcpu->vm, v) != 0) {
|
||||
break;
|
||||
}
|
||||
msr_write(msr, v);
|
||||
vcpu_set_guest_msr(vcpu, MSR_IA32_PERF_CTL, v);
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_PAT:
|
||||
|
|
|
@ -1027,6 +1027,12 @@ int32_t hcall_reset_ptdev_intr_info(struct acrn_vcpu *vcpu, struct acrn_vm *targ
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool is_pt_pstate(__unused const struct acrn_vm *vm)
|
||||
{
|
||||
/* Currently VM's CPU frequency is managed in hypervisor. So no pass through for all VMs. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get VCPU Power state.
|
||||
*
|
||||
|
@ -1047,6 +1053,10 @@ int32_t hcall_get_cpu_pm_state(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm
|
|||
if (is_created_vm(target_vm)) {
|
||||
switch (cmd & PMCMD_TYPE_MASK) {
|
||||
case ACRN_PMCMD_GET_PX_CNT: {
|
||||
if (!is_pt_pstate(target_vm)) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = copy_to_gpa(vm, &(target_vm->pm.px_cnt), param2, sizeof(target_vm->pm.px_cnt));
|
||||
break;
|
||||
}
|
||||
|
@ -1054,6 +1064,10 @@ int32_t hcall_get_cpu_pm_state(struct acrn_vcpu *vcpu, struct acrn_vm *target_vm
|
|||
uint8_t pn;
|
||||
struct acrn_pstate_data *px_data;
|
||||
|
||||
if (!is_pt_pstate(target_vm)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* For now we put px data as per-vm,
|
||||
* If it is stored as per-cpu in the future,
|
||||
* we need to check PMCMD_VCPUID_MASK in cmd.
|
||||
|
|
|
@ -72,6 +72,18 @@
|
|||
#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.06H:ECX.Hardware_Coordination_Feedback_Capability */
|
||||
#define CPUID_ECX_HCFC (1U<<0U)
|
||||
/* CPUID.07H:EBX.FSGSBASE*/
|
||||
#define CPUID_EBX_FSGSBASE (1U<<0U)
|
||||
/* CPUID.07H:EBX.TSC_ADJUST*/
|
||||
|
|
|
@ -173,7 +173,7 @@ enum reset_mode;
|
|||
#define SECURE_WORLD 1
|
||||
|
||||
#define NUM_WORLD_MSRS 2U
|
||||
#define NUM_COMMON_MSRS 23U
|
||||
#define NUM_COMMON_MSRS 24U
|
||||
|
||||
#ifdef CONFIG_VCAT_ENABLED
|
||||
#define NUM_CAT_L2_MSRS MAX_CACHE_CLOS_NUM_ENTRIES
|
||||
|
|
|
@ -575,7 +575,7 @@
|
|||
#define MSR_IA32_MISC_ENABLE_BTS_UNAVAIL (1UL << 11U)
|
||||
#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1UL << 12U)
|
||||
#define MSR_IA32_MISC_ENABLE_TM2_ENABLE (1UL << 13U)
|
||||
#define MSR_IA32_MISC_ENABLE_EITS (1UL << 16U)
|
||||
#define MSR_IA32_MISC_ENABLE_EIST (1UL << 16U)
|
||||
#define MSR_IA32_MISC_ENABLE_MONITOR_ENA (1UL << 18U)
|
||||
#define MSR_IA32_MISC_ENABLE_LIMIT_CPUID (1UL << 22U)
|
||||
#define MSR_IA32_MISC_ENABLE_xTPR (1UL << 23U)
|
||||
|
|
Loading…
Reference in New Issue