Skip to content

Commit 6e3ba4a

Browse files
taoxu916bonzini
authored andcommitted
KVM: vmx: Emulate MSR IA32_UMWAIT_CONTROL
UMWAIT and TPAUSE instructions use 32bit IA32_UMWAIT_CONTROL at MSR index E1H to determines the maximum time in TSC-quanta that the processor can reside in either C0.1 or C0.2. This patch emulates MSR IA32_UMWAIT_CONTROL in guest and differentiate IA32_UMWAIT_CONTROL between host and guest. The variable mwait_control_cached in arch/x86/kernel/cpu/umwait.c caches the MSR value, so this patch uses it to avoid frequently rdmsr of IA32_UMWAIT_CONTROL. Co-developed-by: Jingqi Liu <[email protected]> Signed-off-by: Jingqi Liu <[email protected]> Signed-off-by: Tao Xu <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent e69e72f commit 6e3ba4a

File tree

4 files changed

+53
-0
lines changed

4 files changed

+53
-0
lines changed

arch/x86/kernel/cpu/umwait.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@
1717
*/
1818
static u32 umwait_control_cached = UMWAIT_CTRL_VAL(100000, UMWAIT_C02_ENABLE);
1919

20+
u32 get_umwait_control_msr(void)
21+
{
22+
return umwait_control_cached;
23+
}
24+
EXPORT_SYMBOL_GPL(get_umwait_control_msr);
25+
2026
/*
2127
* Cache the original IA32_UMWAIT_CONTROL MSR value which is configured by
2228
* hardware or BIOS before kernel boot.

arch/x86/kvm/vmx/vmx.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,12 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
17331733
#endif
17341734
case MSR_EFER:
17351735
return kvm_get_msr_common(vcpu, msr_info);
1736+
case MSR_IA32_UMWAIT_CONTROL:
1737+
if (!msr_info->host_initiated && !vmx_has_waitpkg(vmx))
1738+
return 1;
1739+
1740+
msr_info->data = vmx->msr_ia32_umwait_control;
1741+
break;
17361742
case MSR_IA32_SPEC_CTRL:
17371743
if (!msr_info->host_initiated &&
17381744
!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
@@ -1906,6 +1912,16 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
19061912
return 1;
19071913
vmcs_write64(GUEST_BNDCFGS, data);
19081914
break;
1915+
case MSR_IA32_UMWAIT_CONTROL:
1916+
if (!msr_info->host_initiated && !vmx_has_waitpkg(vmx))
1917+
return 1;
1918+
1919+
/* The reserved bit 1 and non-32 bit [63:32] should be zero */
1920+
if (data & (BIT_ULL(1) | GENMASK_ULL(63, 32)))
1921+
return 1;
1922+
1923+
vmx->msr_ia32_umwait_control = data;
1924+
break;
19091925
case MSR_IA32_SPEC_CTRL:
19101926
if (!msr_info->host_initiated &&
19111927
!guest_cpuid_has(vcpu, X86_FEATURE_SPEC_CTRL))
@@ -4211,6 +4227,8 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
42114227
vmx->rmode.vm86_active = 0;
42124228
vmx->spec_ctrl = 0;
42134229

4230+
vmx->msr_ia32_umwait_control = 0;
4231+
42144232
vcpu->arch.microcode_version = 0x100000000ULL;
42154233
vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
42164234
vmx->hv_deadline_tsc = -1;
@@ -6384,6 +6402,23 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
63846402
msrs[i].host, false);
63856403
}
63866404

6405+
static void atomic_switch_umwait_control_msr(struct vcpu_vmx *vmx)
6406+
{
6407+
u32 host_umwait_control;
6408+
6409+
if (!vmx_has_waitpkg(vmx))
6410+
return;
6411+
6412+
host_umwait_control = get_umwait_control_msr();
6413+
6414+
if (vmx->msr_ia32_umwait_control != host_umwait_control)
6415+
add_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL,
6416+
vmx->msr_ia32_umwait_control,
6417+
host_umwait_control, false);
6418+
else
6419+
clear_atomic_switch_msr(vmx, MSR_IA32_UMWAIT_CONTROL);
6420+
}
6421+
63876422
static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
63886423
{
63896424
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -6478,6 +6513,7 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
64786513
pt_guest_enter(vmx);
64796514

64806515
atomic_switch_perf_msrs(vmx);
6516+
atomic_switch_umwait_control_msr(vmx);
64816517

64826518
if (enable_preemption_timer)
64836519
vmx_update_hv_timer(vcpu);

arch/x86/kvm/vmx/vmx.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
extern const u32 vmx_msr_index[];
1515
extern u64 host_efer;
1616

17+
extern u32 get_umwait_control_msr(void);
18+
1719
#define MSR_TYPE_R 1
1820
#define MSR_TYPE_W 2
1921
#define MSR_TYPE_RW 3
@@ -211,6 +213,7 @@ struct vcpu_vmx {
211213
#endif
212214

213215
u64 spec_ctrl;
216+
u32 msr_ia32_umwait_control;
214217

215218
u32 secondary_exec_control;
216219

@@ -497,6 +500,12 @@ static inline void decache_tsc_multiplier(struct vcpu_vmx *vmx)
497500
vmcs_write64(TSC_MULTIPLIER, vmx->current_tsc_ratio);
498501
}
499502

503+
static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
504+
{
505+
return vmx->secondary_exec_control &
506+
SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
507+
}
508+
500509
void dump_vmcs(void);
501510

502511
#endif /* __KVM_X86_VMX_H */

arch/x86/kvm/x86.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,8 @@ static u32 msrs_to_save[] = {
11451145
MSR_IA32_RTIT_ADDR1_A, MSR_IA32_RTIT_ADDR1_B,
11461146
MSR_IA32_RTIT_ADDR2_A, MSR_IA32_RTIT_ADDR2_B,
11471147
MSR_IA32_RTIT_ADDR3_A, MSR_IA32_RTIT_ADDR3_B,
1148+
MSR_IA32_UMWAIT_CONTROL,
1149+
11481150
MSR_ARCH_PERFMON_FIXED_CTR0, MSR_ARCH_PERFMON_FIXED_CTR1,
11491151
MSR_ARCH_PERFMON_FIXED_CTR0 + 2, MSR_ARCH_PERFMON_FIXED_CTR0 + 3,
11501152
MSR_CORE_PERF_FIXED_CTR_CTRL, MSR_CORE_PERF_GLOBAL_STATUS,

0 commit comments

Comments
 (0)