hv: emulate cpuids and MSRs for VHWP

Changes made by this patch includes:
1. Emulate HWP and pstate MSRs/CPUIDs. Those are exposed to guest when
   the GUEST_FLAG_VHWP is set:
    - CPUID[6].EAX[7,9,10]: MSR_IA32_PM_ENABLE(enabled by hv, always read
      1), MSR_IA32_HWP_CAPABILITIES, MSR_IA32_HWP_REQUEST,
      MSR_IA32_HWP_STATUS,
    - CPUID[6].ECX[0]: MSR_IA32_MPERF, MSR_IA32_APERF
    - MSR_IA32_PERF_STATUS(read as base frequency when not owning pCPU)
    - MSR_IA32_PERF_CTL(ignore writes)
2. Always hide HWP interrupt and package control MSRs/CPUIDs:
    - CPUID[6].EAX[8]: MSR_IA32_HWP_INTERRUPT(currently ACRN is not able
      to deliver thermal LVT virtual interrupt to guests)
    - CPUID[6].EAX[11,22]: MSR_IA32_HWP_REQUEST_PKG, MSR_IA32_HWP_CTL

Tracked-On: #8414
Signed-off-by: Wu Zhou <wu.zhou@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Wu Zhou 2023-04-13 16:04:42 +08:00 committed by acrnsi-robot
parent 2edf141047
commit c5d019b836
5 changed files with 97 additions and 24 deletions

View File

@ -115,11 +115,10 @@ 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;
/* Always hide package level HWP controls and HWP interrupt*/
entry->eax &= ~(CPUID_EAX_HWP_CTL | CPUID_EAX_HWP_PLR | CPUID_EAX_HWP_N);
break;
case 0x07U:
@ -548,6 +547,15 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm)
/* MONITOR/MWAIT */
case 0x05U:
break;
case 0x06U:
init_vcpuid_entry(i, 0U, CPUID_CHECK_SUBLEAF, &entry);
/* For VMs without vhwp, HWP and HCFC are always hidden. */
if (!is_vhwp_configured(vm)) {
entry.eax &= ~(CPUID_EAX_HWP | CPUID_EAX_HWP_AW | CPUID_EAX_HWP_EPP);
entry.ecx &= ~CPUID_ECX_HCFC;
}
result = set_vcpuid_entry(vm, &entry);
break;
case 0x07U:
init_vcpuid_entry(i, 0U, CPUID_CHECK_SUBLEAF, &entry);
if (entry.eax != 0U) {

View File

@ -79,6 +79,13 @@ static uint32_t emulated_guest_msrs[NUM_EMULATED_MSRS] = {
MSR_PLATFORM_INFO,
MSR_IA32_PM_ENABLE,
MSR_IA32_HWP_CAPABILITIES,
MSR_IA32_HWP_REQUEST,
MSR_IA32_HWP_STATUS,
MSR_IA32_MPERF,
MSR_IA32_APERF,
/* VMX: CPUID.01H.ECX[5] */
#ifdef CONFIG_NVMX_ENABLED
LIST_OF_VMX_MSRS,
@ -260,28 +267,19 @@ static const uint32_t unsupported_msrs[] = {
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]
/*
* HWP package ctrl disabled:
* CPUID.06H.EAX[11] (MSR_IA32_HWP_REQUEST_PKG)
* CPUID.06H.EAX[22] (MSR_IA32_HWP_CTL)
*/
MSR_IA32_HWP_REQUEST_PKG,
/* Hardware Coordination Feedback Capability disabled:
* CPUID.06H:ECX[0]
MSR_IA32_HWP_CTL,
/*
* HWP interrupt disabled:
* CPUID.06H.EAX[8]
*/
MSR_IA32_MPERF,
MSR_IA32_APERF,
MSR_IA32_HWP_INTERRUPT,
};
/* emulated_guest_msrs[] shares same indexes with array vcpu->arch->guest_msrs[] */
@ -672,7 +670,11 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
}
case MSR_IA32_PERF_STATUS:
{
if (is_vhwp_configured(vcpu->vm)) {
v = msr_read(msr);
} else {
v = get_perf_status();
}
break;
}
case MSR_IA32_PERF_CTL:
@ -680,6 +682,20 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
v = vcpu_get_guest_msr(vcpu, MSR_IA32_PERF_CTL);
break;
}
case MSR_IA32_PM_ENABLE:
case MSR_IA32_HWP_CAPABILITIES:
case MSR_IA32_HWP_REQUEST:
case MSR_IA32_HWP_STATUS:
case MSR_IA32_MPERF:
case MSR_IA32_APERF:
{
if (is_vhwp_configured(vcpu->vm)) {
v = msr_read(msr);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_PAT:
{
/*
@ -1059,6 +1075,48 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
vcpu_set_guest_msr(vcpu, MSR_IA32_PERF_CTL, v);
break;
}
case MSR_IA32_PM_ENABLE:
{
if (!is_vhwp_configured(vcpu->vm)) {
err = -EACCES;
}
/* Set by HV. Writing from guests will have no effect */
break;
}
case MSR_IA32_HWP_CAPABILITIES:
{
/* RO */
break;
}
case MSR_IA32_HWP_REQUEST:
{
if (is_vhwp_configured(vcpu->vm) &&
((v & (MSR_IA32_HWP_REQUEST_RSV_BITS | MSR_IA32_HWP_REQUEST_PKG_CTL)) == 0)) {
msr_write(msr, v);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_HWP_STATUS:
{
if (is_vhwp_configured(vcpu->vm) && ((v & MSR_IA32_HWP_STATUS_RSV_BITS) == 0)) {
msr_write(msr, v);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_MPERF:
case MSR_IA32_APERF:
{
if (is_vhwp_configured(vcpu->vm)) {
msr_write(msr, v);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_PAT:
{
err = write_pat_msr(vcpu, v);

View File

@ -84,6 +84,8 @@
#define CPUID_EAX_HWP_EPP (1U<<10U)
/* CPUID.06H:EAX.HWP_Package_Level_Request */
#define CPUID_EAX_HWP_PLR (1U<<11U)
/* CPUID.06H:EAX.HWP_control */
#define CPUID_EAX_HWP_CTL (1U<<22U)
/* CPUID.06H:ECX.Hardware_Coordination_Feedback_Capability */
#define CPUID_ECX_HCFC (1U<<0U)
/* CPUID.07H:EBX.FSGSBASE*/

View File

@ -175,7 +175,7 @@ enum reset_mode;
#define SECURE_WORLD 1
#define NUM_WORLD_MSRS 2U
#define NUM_COMMON_MSRS 25U
#define NUM_COMMON_MSRS 31U
#ifdef CONFIG_VCAT_ENABLED
#define NUM_CAT_L2_MSRS MAX_CACHE_CLOS_NUM_ENTRIES

View File

@ -294,6 +294,7 @@
#define MSR_IA32_HWP_INTERRUPT 0x00000773U
#define MSR_IA32_HWP_REQUEST 0x00000774U
#define MSR_IA32_HWP_PECI_REQUEST_INFO 0x00000775U
#define MSR_IA32_HWP_CTL 0x00000776U
#define MSR_IA32_HWP_STATUS 0x00000777U
#define MSR_IA32_EXT_XAPICID 0x00000802U
@ -679,4 +680,8 @@ void update_msr_bitmap_x2apic_passthru(struct acrn_vcpu *vcpu);
#define MSR_PLATFORM_INFO_MIN_OPERATING_RATIO_MASK (0x00ff000000000000UL) /* 55:48 */
#define MSR_PLATFORM_INFO_SAMPLE_PART (1UL << 27U)
#define MSR_IA32_HWP_STATUS_RSV_BITS (~0x3DUL)
#define MSR_IA32_HWP_REQUEST_RSV_BITS (0x7FFF80000000000UL)
#define MSR_IA32_HWP_REQUEST_PKG_CTL (1UL << 42U)
#endif /* MSR_H */