mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-26 15:31:35 +00:00
hv: Support WAITPKG instructions in guest VM
TPAUSE, UMONITOR or UMWAIT instructions execution in guest VM cause a #UD if "enable user wait and pause" (bit 26) of VMX_PROCBASED_CTLS2 is not set. To fix this issue, set the bit 26 of VMX_PROCBASED_CTLS2. Besides, these WAITPKG instructions uses MSR_IA32_UMWAIT_CONTROL. So load corresponding vMSR value during context switch in of a vCPU. Please note, the TPAUSE or UMWAIT instruction causes a VM exit if the "RDTSC exiting" and "enable user wait and pause" are both 1. In ACRN hypervisor, "RDTSC exiting" is always 0. So TPAUSE or UMWAIT doesn't cause a VM exit. Performance impact: MSR_IA32_UMWAIT_CONTROL read costs ~19 cycles; MSR_IA32_UMWAIT_CONTROL write costs ~63 cycles. Tracked-On: #6006 Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com>
This commit is contained in:
parent
ebadf00de8
commit
3fffa68665
@ -857,6 +857,7 @@ static void context_switch_in(struct thread_object *next)
|
||||
{
|
||||
struct acrn_vcpu *vcpu = container_of(next, struct acrn_vcpu, thread_obj);
|
||||
struct ext_context *ectx = &(vcpu->arch.contexts[vcpu->arch.cur_context].ext_ctx);
|
||||
uint64_t vmsr_val;
|
||||
|
||||
load_vmcs(vcpu);
|
||||
|
||||
@ -866,6 +867,13 @@ static void context_switch_in(struct thread_object *next)
|
||||
msr_write(MSR_IA32_FMASK, ectx->ia32_fmask);
|
||||
msr_write(MSR_IA32_KERNEL_GS_BASE, ectx->ia32_kernel_gs_base);
|
||||
|
||||
if (pcpu_has_cap(X86_FEATURE_WAITPKG)) {
|
||||
vmsr_val = vcpu_get_guest_msr(vcpu, MSR_IA32_UMWAIT_CONTROL);
|
||||
if (vmsr_val != msr_read(MSR_IA32_UMWAIT_CONTROL)) {
|
||||
msr_write(MSR_IA32_UMWAIT_CONTROL, vmsr_val);
|
||||
}
|
||||
}
|
||||
|
||||
load_iwkey(vcpu);
|
||||
|
||||
rstore_xsave_area(vcpu, ectx);
|
||||
|
@ -319,7 +319,7 @@ static void init_exec_ctrl(struct acrn_vcpu *vcpu)
|
||||
value32 = check_vmx_ctrl(MSR_IA32_VMX_PROCBASED_CTLS2,
|
||||
VMX_PROCBASED_CTLS2_VAPIC | VMX_PROCBASED_CTLS2_EPT |VMX_PROCBASED_CTLS2_VPID |
|
||||
VMX_PROCBASED_CTLS2_RDTSCP | VMX_PROCBASED_CTLS2_UNRESTRICT |
|
||||
VMX_PROCBASED_CTLS2_PAUSE_LOOP);
|
||||
VMX_PROCBASED_CTLS2_PAUSE_LOOP | VMX_PROCBASED_CTLS2_UWAIT_PAUSE);
|
||||
|
||||
/* SDM Vol3, 25.3, setting "enable INVPCID" VM-execution to 1 with "INVLPG exiting" disabled,
|
||||
* passes-through INVPCID instruction to guest if the instruction is supported.
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <asm/sgx.h>
|
||||
#include <asm/guest/guest_pm.h>
|
||||
#include <asm/guest/ucode.h>
|
||||
#include <asm/cpufeatures.h>
|
||||
#include <asm/rdt.h>
|
||||
#include <trace.h>
|
||||
#include <logmsg.h>
|
||||
@ -40,6 +41,7 @@ static const uint32_t emulated_guest_msrs[NUM_GUEST_MSRS] = {
|
||||
* MSRs don't need isolation between worlds
|
||||
* Number of entries: NUM_COMMON_MSRS
|
||||
*/
|
||||
MSR_IA32_UMWAIT_CONTROL,
|
||||
MSR_IA32_TSC_DEADLINE,
|
||||
MSR_IA32_BIOS_UPDT_TRIG,
|
||||
MSR_IA32_BIOS_SIGN_ID,
|
||||
@ -553,6 +555,16 @@ int32_t rdmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_UMWAIT_CONTROL:
|
||||
{
|
||||
/* Feature X86_FEATURE_WAITPKG is always presented */
|
||||
if (pcpu_has_cap(X86_FEATURE_WAITPKG)) {
|
||||
v = vcpu_get_guest_msr(vcpu, msr);
|
||||
} else {
|
||||
err = -EACCES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSR_TEST_CTL:
|
||||
{
|
||||
/* If has MSR_TEST_CTL, give emulated value
|
||||
@ -905,6 +917,17 @@ int32_t wrmsr_vmexit_handler(struct acrn_vcpu *vcpu)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSR_IA32_UMWAIT_CONTROL:
|
||||
{
|
||||
/* Feature X86_FEATURE_WAITPKG is always presented */
|
||||
if (pcpu_has_cap(X86_FEATURE_WAITPKG)) {
|
||||
vcpu_set_guest_msr(vcpu, msr, v);
|
||||
msr_write(msr, v);
|
||||
} else {
|
||||
err = -EACCES;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSR_TEST_CTL:
|
||||
{
|
||||
/* If VM has MSR_TEST_CTL, ignore write operation
|
||||
|
@ -80,6 +80,7 @@
|
||||
#define X86_FEATURE_CLFLUSHOPT ((FEAT_7_0_EBX << 5U) + 23U)
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007 (ECX)*/
|
||||
#define X86_FEATURE_WAITPKG ((FEAT_7_0_ECX << 5U) + 5U)
|
||||
#define X86_FEATURE_KEYLOCKER ((FEAT_7_0_ECX << 5U) + 23U)
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007 (EDX)*/
|
||||
|
@ -171,7 +171,7 @@ enum reset_mode;
|
||||
#define SECURE_WORLD 1
|
||||
|
||||
#define NUM_WORLD_MSRS 2U
|
||||
#define NUM_COMMON_MSRS 21U
|
||||
#define NUM_COMMON_MSRS 22U
|
||||
#define NUM_GUEST_MSRS (NUM_WORLD_MSRS + NUM_COMMON_MSRS)
|
||||
|
||||
#define EOI_EXIT_BITMAP_SIZE 256U
|
||||
|
@ -42,6 +42,7 @@
|
||||
#define MSR_IA32_PMC6 0x000000C7U
|
||||
#define MSR_IA32_PMC7 0x000000C8U
|
||||
#define MSR_IA32_CORE_CAPABILITIES 0x000000CFU
|
||||
#define MSR_IA32_UMWAIT_CONTROL 0x000000E1U
|
||||
/* Max. qualified performance clock counter */
|
||||
#define MSR_IA32_MPERF 0x000000E7U
|
||||
/* Actual performance clock counter */
|
||||
|
@ -317,6 +317,7 @@
|
||||
#define VMX_PROCBASED_CTLS2_RDSEED (1U<<16U)
|
||||
#define VMX_PROCBASED_CTLS2_EPT_VE (1U<<18U)
|
||||
#define VMX_PROCBASED_CTLS2_XSVE_XRSTR (1U<<20U)
|
||||
#define VMX_PROCBASED_CTLS2_UWAIT_PAUSE (1U<<26U)
|
||||
#define VMX_PROCBASED_CTLS3_LOADIWKEY (1U<<0U)
|
||||
|
||||
/* MSR_IA32_VMX_EPT_VPID_CAP: EPT and VPID capability bits */
|
||||
|
Loading…
Reference in New Issue
Block a user