hv: expose thermal MSRs to VM.

In this phase, we only use one VM to control thermal.
So we make thermal MSRs readable and writable by this VM.

This VM is flagged with GUEST_FLAG_VTM, and can
read/write thermal MSRs.
For the VMs not flagged with GUEST_FLAG_VTM,
can only read these thermal MSRs to get current status.

Tracked-On: #8595
Signed-off-by: Zhangwei6 <wei6.zhang@intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Zhangwei6 2024-05-10 14:16:13 +08:00 committed by acrnsi-robot
parent 5d7e217f55
commit 78243c3f49
5 changed files with 106 additions and 1 deletions

View File

@ -86,6 +86,17 @@ static uint32_t emulated_guest_msrs[NUM_EMULATED_MSRS] = {
MSR_IA32_MPERF,
MSR_IA32_APERF,
/*
* Thermal MSRs:
* CPUID.01H.EDX[22] IA32_THERM_INTERRUPT, IA32_THERM_STATUS, MSR_IA32_CLOCK_MODULATION
* CPUID.06H:EAX[6] IA32_PACKAGE_THERM_INTERRUPT, IA32_PACKAGE_THERM_STATUS
*/
MSR_IA32_CLOCK_MODULATION,
MSR_IA32_THERM_INTERRUPT,
MSR_IA32_THERM_STATUS,
MSR_IA32_PACKAGE_THERM_INTERRUPT,
MSR_IA32_PACKAGE_THERM_STATUS,
/* VMX: CPUID.01H.ECX[5] */
#ifdef CONFIG_NVMX_ENABLED
LIST_OF_VMX_MSRS,
@ -615,6 +626,17 @@ bool is_iwkey_backup_support(struct acrn_vcpu *vcpu)
return (ebx & CPUID_EBX_KL_BACKUP_MSR) == CPUID_EBX_KL_BACKUP_MSR;
}
/**
* @pre vcpu != NULL
*/
bool is_ecmd_supported(struct acrn_vcpu *vcpu)
{
uint32_t eax = 0x6U, ebx = 0U, ecx = 0U, edx = 0U;
/* ECMD. Check clock modulation duty cycle extension is supported */
guest_cpuid(vcpu, &eax, &ebx, &ecx, &edx);
return (eax & CPUID_EAX_ECMD) == CPUID_EAX_ECMD;
}
/**
* @pre vcpu != NULL
*/
@ -652,6 +674,15 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
v = vcpu_get_guest_msr(vcpu, MSR_IA32_TSC_ADJUST);
break;
}
case MSR_IA32_CLOCK_MODULATION:
case MSR_IA32_THERM_STATUS:
case MSR_IA32_THERM_INTERRUPT:
case MSR_IA32_PACKAGE_THERM_INTERRUPT:
case MSR_IA32_PACKAGE_THERM_STATUS:
{
v = msr_read(msr);
break;
}
case MSR_IA32_MTRR_CAP:
case MSR_IA32_MTRR_DEF_TYPE:
case MSR_IA32_MTRR_FIX64K_00000:
@ -1046,6 +1077,59 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
set_guest_tsc(vcpu, v);
break;
}
case MSR_IA32_CLOCK_MODULATION:
{
if (is_vtm_configured(vcpu->vm)) {
/*if extended clock modulation duty(ECMD) is not supported,
*bit 0 is reserved.
*/
if (is_ecmd_supported(vcpu)) {
err = msr_write_safe(msr, v, MSR_IA32_CLOCK_MODULATION_RSV_BITS);
} else {
err = msr_write_safe(msr, v, MSR_IA32_CLOCK_MODULATION_RSV_BITS |
0x1UL);
}
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_THERM_STATUS:
{
if (is_vtm_configured(vcpu->vm)) {
err = msr_write_safe(msr, v, MSR_IA32_THERM_STATUS_RSV_BITS);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_THERM_INTERRUPT:
{
if (is_vtm_configured(vcpu->vm)) {
err = msr_write_safe(msr, v, MSR_IA32_THERM_INTERRUPT_RSV_BITS);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_PACKAGE_THERM_INTERRUPT:
{
if (is_vtm_configured(vcpu->vm)) {
err = msr_write_safe(msr, v, MSR_IA32_PACKAGE_THERM_INTERRUPT_RSV_BITS);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_PACKAGE_THERM_STATUS:
{
if (is_vtm_configured(vcpu->vm)) {
err = msr_write_safe(msr, v, MSR_IA32_PACKAGE_THERM_STATUS_RSV_BITS);
} else {
err = -EACCES;
}
break;
}
case MSR_IA32_MTRR_DEF_TYPE:
case MSR_IA32_MTRR_FIX64K_00000:
case MSR_IA32_MTRR_FIX16K_80000:

View File

@ -40,6 +40,7 @@
#include <util.h>
#include <acrn_common.h>
#include <asm/msr.h>
#include <errno.h>
/* Define CPU stack alignment */
#define CPU_STACK_ALIGN 16UL
@ -704,6 +705,17 @@ static inline void msr_write(uint32_t reg_num, uint64_t value64)
cpu_msr_write(reg_num, value64);
}
static inline int32_t msr_write_safe(uint32_t reg_num, uint64_t value64, uint64_t rsvd)
{
int32_t err = 0;
if ((value64 & rsvd) == 0) {
msr_write(reg_num, value64);
} else {
err = -EACCES;
}
return err;
}
/* wrmsr/rdmsr smp call data */
struct msr_data_struct {

View File

@ -74,6 +74,8 @@
#define CPUID_EDX_TM1 (1U<<29U)
#define CPUID_EDX_IA64 (1U<<30U)
#define CPUID_EDX_PBE (1U<<31U)
/* CPUID.06H:EAX.ECMD */
#define CPUID_EAX_ECMD (1U<<5U)
/* CPUID.06H:EAX.HWP */
#define CPUID_EAX_HWP (1U<<7U)
/* CPUID.06H:EAX.HWP_Notification */

View File

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

View File

@ -689,4 +689,11 @@ void update_msr_bitmap_x2apic_passthru(struct acrn_vcpu *vcpu);
#define MSR_IA32_HWP_REQUEST_RSV_BITS (0x7FFF80000000000UL)
#define MSR_IA32_HWP_REQUEST_PKG_CTL (1UL << 42U)
/* Thermal MSR reserved bits */
#define MSR_IA32_CLOCK_MODULATION_RSV_BITS (~0x1FUL)
#define MSR_IA32_THERM_STATUS_RSV_BITS (~0xAAAUL)
#define MSR_IA32_THERM_INTERRUPT_RSV_BITS (~0x1FFFF1FUL)
#define MSR_IA32_PACKAGE_THERM_STATUS_RSV_BITS (~0xAA2UL)
#define MSR_IA32_PACKAGE_THERM_INTERRUPT_RSV_BITS (~0x1FFFF17UL)
#endif /* MSR_H */