implement VMX SUPPORT FOR THE IA32_SPEC_CTRL MSR announced in 319433-052
bugfix: "shadow stack prematurely busy" secondary vmexit control was wrongly mapped into bit2 insetad of bit3
This commit is contained in:
parent
c6b7961799
commit
247aca0956
@ -663,6 +663,18 @@ bool isValidMSR_FixedMTRR(Bit64u fixed_mtrr_val)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isValidMSR_IA32_SPEC_CTRL(Bit64u val_64)
|
||||
{
|
||||
// [0] - Enable IBRS: Indirect Branch Restricted Speculation
|
||||
// [1] - Enable STIBP: Single Thread Indirect Branch Predictors
|
||||
// [2] - Enable SSCB: Speculative Store Bypass Disable
|
||||
// [63:3] - reserved
|
||||
if (val_64 & ~(BX_CONST64(0x7)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if BX_CPU_LEVEL >= 5
|
||||
bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
|
||||
{
|
||||
@ -1091,11 +1103,7 @@ bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64)
|
||||
if (BX_CPU_THIS_PTR in_vmx_guest && vm->vmexec_ctrls3.VIRTUALIZE_IA32_SPEC_CTRL())
|
||||
val_64 = (BX_CPU_THIS_PTR msr.ia32_spec_ctrl & vm->ia32_spec_ctrl_mask) | (val_64 & ~vm->ia32_spec_ctrl_mask);
|
||||
#endif
|
||||
// [0] - Enable IBRS: Indirect Branch Restricted Speculation
|
||||
// [1] - Enable STIBP: Single Thread Indirect Branch Predictors
|
||||
// [2] - Enable SSCB: Speculative Store Bypass Disable
|
||||
// [63:3] - reserved
|
||||
if (val_64 & ~(BX_CONST64(0x7))) {
|
||||
if (! isValidMSR_IA32_SPEC_CTRL(val_64)) {
|
||||
BX_ERROR(("WRMSR: attempt to set reserved bits of IA32_SPEC_CTRL !"));
|
||||
return false;
|
||||
}
|
||||
|
@ -461,6 +461,12 @@ bool BX_CPU_C::vmcs_field_supported(Bit32u encoding)
|
||||
return is_cpu_extension_supported(BX_ISA_PKS);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
case VMCS_64BIT_GUEST_IA32_SPEC_CTRL:
|
||||
case VMCS_64BIT_GUEST_IA32_SPEC_CTRL_HI:
|
||||
return BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
/* VMCS 64-bit host state fields */
|
||||
/* binary 0010_11xx_xxxx_xxx0 */
|
||||
@ -483,6 +489,12 @@ bool BX_CPU_C::vmcs_field_supported(Bit32u encoding)
|
||||
return is_cpu_extension_supported(BX_ISA_PKS);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
case VMCS_64BIT_HOST_IA32_SPEC_CTRL:
|
||||
case VMCS_64BIT_HOST_IA32_SPEC_CTRL_HI:
|
||||
return BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION);
|
||||
#endif
|
||||
|
||||
/* VMCS natural width control fields */
|
||||
/* binary 0110_00xx_xxxx_xxx0 */
|
||||
case VMCS_CONTROL_CR0_GUEST_HOST_MASK:
|
||||
@ -894,8 +906,11 @@ void BX_CPU_C::init_secondary_vmexit_ctrls(void)
|
||||
|
||||
// secondary vmexit controls
|
||||
// -----------------------------------------------------------
|
||||
// [02] Prematurely busy shadow stack control
|
||||
// [02] load host MSR_IA32_SPEC_CTRL control
|
||||
// [03] Prematurely busy shadow stack control
|
||||
|
||||
if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION))
|
||||
cap->vmx_vmexit_ctrl2_supported_bits |= VMX_VMEXIT_CTRL2_LOAD_HOST_IA32_SPEC_CTRL;
|
||||
#if BX_SUPPORT_CET
|
||||
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CET))
|
||||
cap->vmx_vmexit_ctrl2_supported_bits |= VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL;
|
||||
@ -987,6 +1002,7 @@ void BX_CPU_C::init_vmentry_ctrls(void)
|
||||
// [17] Load guest CET state
|
||||
// [19] Load guest UINV state
|
||||
// [22] Load guest MSR_IA32_PKRS value
|
||||
// [24] Load guest MSR_IA32_SPEC_CTRL value
|
||||
|
||||
cap->vmx_vmentry_ctrl_supported_bits = VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS |
|
||||
VMX_VMENTRY_CTRL1_SMM_ENTER |
|
||||
@ -1016,6 +1032,8 @@ void BX_CPU_C::init_vmentry_ctrls(void)
|
||||
if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PKS))
|
||||
cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS;
|
||||
#endif
|
||||
if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_SPEC_CTRL_VIRTUALIZATION))
|
||||
cap->vmx_vmexit_ctrl2_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_GUEST_IA32_SPEC_CTRL;
|
||||
}
|
||||
|
||||
#endif // BX_SUPPORT_VMX
|
||||
|
@ -40,6 +40,7 @@ extern VMCS_Mapping vmcs_map;
|
||||
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
extern bool isValidMSR_PAT(Bit64u pat_msr);
|
||||
extern bool isValidMSR_IA32_SPEC_CTRL(Bit64u val_64);
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_CET
|
||||
@ -1234,6 +1235,14 @@ VMX_error_code BX_CPU_C::VMenterLoadCheckHostState(void)
|
||||
return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD;
|
||||
}
|
||||
}
|
||||
|
||||
if (vm->vmexit_ctrls2.LOAD_HOST_IA32_SPEC_CTRL()) {
|
||||
host_state->ia32_spec_ctrl_msr = VMread64(VMCS_64BIT_HOST_IA32_SPEC_CTRL);
|
||||
if (! isValidMSR_IA32_SPEC_CTRL(host_state->ia32_spec_ctrl_msr)) {
|
||||
BX_ERROR(("VMFAIL: invalid value in host IA32_SPEC_CTRL_MSR"));
|
||||
return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
host_state->rsp = (bx_address) VMread_natural(VMCS_HOST_RSP);
|
||||
@ -1843,6 +1852,14 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
if (vm->vmentry_ctrls.LOAD_GUEST_IA32_SPEC_CTRL()) {
|
||||
guest.ia32_spec_ctrl_msr = VMread64(VMCS_64BIT_GUEST_IA32_SPEC_CTRL);
|
||||
if (! isValidMSR_IA32_SPEC_CTRL(guest.ia32_spec_ctrl_msr)) {
|
||||
BX_ERROR(("VMFAIL: invalid value in guest MSR_IA32_SPEC_CTRL"));
|
||||
return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
guest.rip = VMread_natural(VMCS_GUEST_RIP);
|
||||
@ -2158,6 +2175,10 @@ Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification)
|
||||
if (vm->vmentry_ctrls.LOAD_PAT_MSR()) {
|
||||
BX_CPU_THIS_PTR msr.pat = guest.pat_msr;
|
||||
}
|
||||
|
||||
if (vm->vmentry_ctrls.LOAD_GUEST_IA32_SPEC_CTRL()) {
|
||||
BX_CPU_THIS_PTR msr.ia32_spec_ctrl = guest.ia32_spec_ctrl_msr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_VMX >= 2
|
||||
@ -2671,6 +2692,9 @@ void BX_CPU_C::VMexitLoadHostState(void)
|
||||
if (vm->vmexit_ctrls1.LOAD_PAT_MSR()) {
|
||||
BX_CPU_THIS_PTR msr.pat = host_state->pat_msr;
|
||||
}
|
||||
if (vm->vmexit_ctrls2.LOAD_HOST_IA32_SPEC_CTRL()) {
|
||||
BX_CPU_THIS_PTR msr.ia32_spec_ctrl = host_state->ia32_spec_ctrl_msr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// CS selector loaded from VMCS
|
||||
@ -4248,6 +4272,7 @@ void BX_CPU_C::register_vmx_state(bx_param_c *parent)
|
||||
#if BX_SUPPORT_X86_64
|
||||
BXRS_HEX_PARAM_FIELD(host, efer_msr, vm->host_state.efer_msr);
|
||||
#endif
|
||||
BXRS_HEX_PARAM_FIELD(host, ia32_spec_ctrl_msr, vm->host_state.ia32_spec_ctrl_msr);
|
||||
#endif
|
||||
#if BX_SUPPORT_CET
|
||||
BXRS_HEX_PARAM_FIELD(host, ia32_s_cet_msr, vm->host_state.msr_ia32_s_cet);
|
||||
|
@ -347,7 +347,7 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_
|
||||
#define VMCS_64BIT_GUEST_IA32_RTIT_CTL_HI 0x00002815
|
||||
#define VMCS_64BIT_GUEST_IA32_PKRS 0x00002818 /* Supervisor-Mode Protection Keys */
|
||||
#define VMCS_64BIT_GUEST_IA32_PKRS_HI 0x00002819
|
||||
#define VMCS_64BIT_GUEST_IA32_SPEC_CTRL 0x0000282E /* MSR_IA32_SPEC_CTRL virtualization (not implemented) */
|
||||
#define VMCS_64BIT_GUEST_IA32_SPEC_CTRL 0x0000282E /* MSR_IA32_SPEC_CTRL virtualization */
|
||||
#define VMCS_64BIT_GUEST_IA32_SPEC_CTRL_HI 0x0000282F
|
||||
#define VMCS_64BIT_GUEST_DEADLINE 0x00002830 /* APIC timer virtualization (not implemented) */
|
||||
#define VMCS_64BIT_GUEST_DEADLINE_HI 0x00002831
|
||||
@ -362,7 +362,7 @@ const Bit64u VMX_VMFUNC_EPTP_SWITCHING_MASK = (BX_CONST64(1) << VMX_VMFUNC_EPTP_
|
||||
#define VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL_HI 0x00002C05
|
||||
#define VMCS_64BIT_HOST_IA32_PKRS 0x00002C06 /* Supervisor-Mode Protection Keys */
|
||||
#define VMCS_64BIT_HOST_IA32_PKRS_HI 0x00002C07
|
||||
#define VMCS_64BIT_HOST_IA32_SPEC_CTRL 0x00002C1A /* MSR_IA32_SPEC_CTRL virtualization (not implemented) */
|
||||
#define VMCS_64BIT_HOST_IA32_SPEC_CTRL 0x00002C1A /* MSR_IA32_SPEC_CTRL virtualization */
|
||||
#define VMCS_64BIT_HOST_IA32_SPEC_CTRL_HI 0x00002C1B
|
||||
|
||||
/* VMCS 32_bit control fields */
|
||||
@ -652,6 +652,8 @@ typedef struct bx_VMCS_GUEST_STATE
|
||||
Bit64u pdptr[4];
|
||||
#endif
|
||||
|
||||
Bit64u ia32_spec_ctrl_msr;
|
||||
|
||||
#if BX_SUPPORT_CET
|
||||
Bit64u msr_ia32_s_cet;
|
||||
bx_address ssp;
|
||||
@ -696,6 +698,7 @@ typedef struct bx_VMCS_HOST_STATE
|
||||
Bit64u efer_msr;
|
||||
#endif
|
||||
Bit64u pat_msr;
|
||||
Bit64u ia32_spec_ctrl_msr;
|
||||
#endif
|
||||
|
||||
#if BX_SUPPORT_CET
|
||||
|
@ -239,6 +239,7 @@ public:
|
||||
#define VMX_VMENTRY_CTRL1_LOAD_GUEST_CET_STATE (1 << 20) /* CET */
|
||||
#define VMX_VMENTRY_CTRL1_LOAD_GUEST_LBR_CTRL (1 << 21) // not implemented
|
||||
#define VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS (1 << 22) /* Supervisor-Mode Protection Keys */
|
||||
#define VMX_VMENTRY_CTRL1_LOAD_GUEST_IA32_SPEC_CTRL (1 << 24)
|
||||
|
||||
bool LOAD_DBG_CTRLS() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS; }
|
||||
bool X86_64_GUEST() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_X86_64_GUEST; }
|
||||
@ -254,6 +255,7 @@ public:
|
||||
bool LOAD_GUEST_CET_STATE() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_CET_STATE; }
|
||||
bool LOAD_GUEST_LBR() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_LBR_CTRL; }
|
||||
bool LOAD_GUEST_PKRS() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_PKRS; }
|
||||
bool LOAD_GUEST_IA32_SPEC_CTRL() const { return vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_GUEST_IA32_SPEC_CTRL; }
|
||||
|
||||
bool query_any(Bit32u mask) const { return (vmentry_ctrls & mask) != 0; }
|
||||
bool query_all(Bit32u mask) const { return (vmentry_ctrls & mask) == mask; }
|
||||
@ -326,8 +328,10 @@ private:
|
||||
public:
|
||||
BxVmexit2Controls(Bit64u ctrls = 0): vmexit2_ctrls(ctrls) {}
|
||||
|
||||
#define VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL (1 << 2) /* Shadow stack prematurely busy */
|
||||
#define VMX_VMEXIT_CTRL2_LOAD_HOST_IA32_SPEC_CTRL (1 << 2)
|
||||
#define VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL (1 << 3) /* Shadow stack prematurely busy */
|
||||
|
||||
bool LOAD_HOST_IA32_SPEC_CTRL() const { return vmexit2_ctrls & VMX_VMEXIT_CTRL2_LOAD_HOST_IA32_SPEC_CTRL; }
|
||||
bool SHADOW_STACK_PREMATURELY_BUSY_CTRL() const { return vmexit2_ctrls & VMX_VMEXIT_CTRL2_SHADOW_STACK_BUSY_CTRL; }
|
||||
|
||||
bool query_any(Bit64u mask) const { return (vmexit2_ctrls & mask) != 0; }
|
||||
|
Loading…
Reference in New Issue
Block a user