mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
KVM VMX changes for 6.4:
- Fix a bug in emulation of ENCLS in compatibility mode - Allow emulation of NOP and PAUSE for L2 - Misc cleanups -----BEGIN PGP SIGNATURE----- iQJGBAABCgAwFiEEMHr+pfEFOIzK+KY1YJEiAU0MEvkFAmRGuYgSHHNlYW5qY0Bn b29nbGUuY29tAAoJEGCRIgFNDBL5kQUP/jV5Q8ZeVCzlf6ZCeAHnWX/Hahsv6i6H ooNL8W6p8FI5xlYOWh8J02JpmLUrNWURCPqvr0oYLm4r1UlJ/OGjyuKB8d7SZ7z/ RaLN7tppMod527J+Qm3ptHQbTKAGHe4dEoiX46cuvTEcCxrsVykYltvfD1rNuSQA VcaNJkkcHv/KuItUHLAuntCAiFvbD1gYNLfUAC7e0htGjLRLxg3+ugHEiFcJ3c6y z4ged1toYLGD962jWSIgokFbivfUNZT25WlZjBliMa/E8+ckTAzmc67UJYvhNBOM HyAHs0hp+XtSgfcCgNkI+WDrFXXgxa+QQcMFvRWacS3Hx6tgJoQ51FRMevmumn0O zBPk3+BOquhknqb5NbmwRZoLExffo+86fFlDcgszzvV4Y/vBfp/XTsuJZCnaiMDZ wdmJoF4mhRDtgt7yORltpjHqp3yRmLqMNUb3sxXLRA9D+edo9mr8SXujOnukmXoH o/ZpEollTPUQ7od/uDIvDyosWvb65IbYwsKGdOanfBacVrxy5OPM38mPF7u9AyzD Gn81H/OhwhpTSBAX7kLMGeK/QGkyIBEUM1levdmcAk0nKYQzHzsI7tMYfqwXuQSu qKAcF+qtpOReWmb4KaJZ7c0HQIBQHOKQ6exXxnQJuLjnAHS0674NxMDkT5a1EGRL Q9OPSTSYBMDC =FOnk -----END PGP SIGNATURE----- Merge tag 'kvm-x86-vmx-6.4' of https://github.com/kvm-x86/linux into HEAD KVM VMX changes for 6.4: - Fix a bug in emulation of ENCLS in compatibility mode - Allow emulation of NOP and PAUSE for L2 - Misc cleanups
This commit is contained in:
commit
b3c98052d4
|
|
@ -6756,36 +6756,9 @@ static u64 nested_vmx_calc_vmcs_enum_msr(void)
|
|||
return (u64)max_idx << VMCS_FIELD_INDEX_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* nested_vmx_setup_ctls_msrs() sets up variables containing the values to be
|
||||
* returned for the various VMX controls MSRs when nested VMX is enabled.
|
||||
* The same values should also be used to verify that vmcs12 control fields are
|
||||
* valid during nested entry from L1 to L2.
|
||||
* Each of these control msrs has a low and high 32-bit half: A low bit is on
|
||||
* if the corresponding bit in the (32-bit) control field *must* be on, and a
|
||||
* bit in the high half is on if the corresponding bit in the control field
|
||||
* may be on. See also vmx_control_verify().
|
||||
*/
|
||||
void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
||||
static void nested_vmx_setup_pinbased_ctls(struct vmcs_config *vmcs_conf,
|
||||
struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
struct nested_vmx_msrs *msrs = &vmcs_conf->nested;
|
||||
|
||||
/*
|
||||
* Note that as a general rule, the high half of the MSRs (bits in
|
||||
* the control fields which may be 1) should be initialized by the
|
||||
* intersection of the underlying hardware's MSR (i.e., features which
|
||||
* can be supported) and the list of features we want to expose -
|
||||
* because they are known to be properly supported in our code.
|
||||
* Also, usually, the low half of the MSRs (bits which must be 1) can
|
||||
* be set to 0, meaning that L1 may turn off any of these bits. The
|
||||
* reason is that if one of these bits is necessary, it will appear
|
||||
* in vmcs01 and prepare_vmcs02, when it bitwise-or's the control
|
||||
* fields of vmcs01 and vmcs02, will turn these bits off - and
|
||||
* nested_vmx_l1_wants_exit() will not pass related exits to L1.
|
||||
* These rules have exceptions below.
|
||||
*/
|
||||
|
||||
/* pin-based controls */
|
||||
msrs->pinbased_ctls_low =
|
||||
PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
|
||||
|
||||
|
|
@ -6798,8 +6771,11 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
msrs->pinbased_ctls_high |=
|
||||
PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
|
||||
PIN_BASED_VMX_PREEMPTION_TIMER;
|
||||
}
|
||||
|
||||
/* exit controls */
|
||||
static void nested_vmx_setup_exit_ctls(struct vmcs_config *vmcs_conf,
|
||||
struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
msrs->exit_ctls_low =
|
||||
VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR;
|
||||
|
||||
|
|
@ -6818,8 +6794,11 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
|
||||
/* We support free control of debug control saving. */
|
||||
msrs->exit_ctls_low &= ~VM_EXIT_SAVE_DEBUG_CONTROLS;
|
||||
}
|
||||
|
||||
/* entry controls */
|
||||
static void nested_vmx_setup_entry_ctls(struct vmcs_config *vmcs_conf,
|
||||
struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
msrs->entry_ctls_low =
|
||||
VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR;
|
||||
|
||||
|
|
@ -6835,8 +6814,11 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
|
||||
/* We support free control of debug control loading. */
|
||||
msrs->entry_ctls_low &= ~VM_ENTRY_LOAD_DEBUG_CONTROLS;
|
||||
}
|
||||
|
||||
/* cpu-based controls */
|
||||
static void nested_vmx_setup_cpubased_ctls(struct vmcs_config *vmcs_conf,
|
||||
struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
msrs->procbased_ctls_low =
|
||||
CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
|
||||
|
||||
|
|
@ -6868,12 +6850,12 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
/* We support free control of CR3 access interception. */
|
||||
msrs->procbased_ctls_low &=
|
||||
~(CPU_BASED_CR3_LOAD_EXITING | CPU_BASED_CR3_STORE_EXITING);
|
||||
}
|
||||
|
||||
/*
|
||||
* secondary cpu-based controls. Do not include those that
|
||||
* depend on CPUID bits, they are added later by
|
||||
* vmx_vcpu_after_set_cpuid.
|
||||
*/
|
||||
static void nested_vmx_setup_secondary_ctls(u32 ept_caps,
|
||||
struct vmcs_config *vmcs_conf,
|
||||
struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
msrs->secondary_ctls_low = 0;
|
||||
|
||||
msrs->secondary_ctls_high = vmcs_conf->cpu_based_2nd_exec_ctrl;
|
||||
|
|
@ -6951,8 +6933,11 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
|
||||
if (enable_sgx)
|
||||
msrs->secondary_ctls_high |= SECONDARY_EXEC_ENCLS_EXITING;
|
||||
}
|
||||
|
||||
/* miscellaneous data */
|
||||
static void nested_vmx_setup_misc_data(struct vmcs_config *vmcs_conf,
|
||||
struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
msrs->misc_low = (u32)vmcs_conf->misc & VMX_MISC_SAVE_EFER_LMA;
|
||||
msrs->misc_low |=
|
||||
MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
|
||||
|
|
@ -6960,7 +6945,10 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
VMX_MISC_ACTIVITY_HLT |
|
||||
VMX_MISC_ACTIVITY_WAIT_SIPI;
|
||||
msrs->misc_high = 0;
|
||||
}
|
||||
|
||||
static void nested_vmx_setup_basic(struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
/*
|
||||
* This MSR reports some information about VMX support. We
|
||||
* should return information about the VMX we emulate for the
|
||||
|
|
@ -6975,7 +6963,10 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
|
||||
if (cpu_has_vmx_basic_inout())
|
||||
msrs->basic |= VMX_BASIC_INOUT;
|
||||
}
|
||||
|
||||
static void nested_vmx_setup_cr_fixed(struct nested_vmx_msrs *msrs)
|
||||
{
|
||||
/*
|
||||
* These MSRs specify bits which the guest must keep fixed on
|
||||
* while L1 is in VMXON mode (in L1's root mode, or running an L2).
|
||||
|
|
@ -6992,6 +6983,51 @@ void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
|||
|
||||
if (vmx_umip_emulated())
|
||||
msrs->cr4_fixed1 |= X86_CR4_UMIP;
|
||||
}
|
||||
|
||||
/*
|
||||
* nested_vmx_setup_ctls_msrs() sets up variables containing the values to be
|
||||
* returned for the various VMX controls MSRs when nested VMX is enabled.
|
||||
* The same values should also be used to verify that vmcs12 control fields are
|
||||
* valid during nested entry from L1 to L2.
|
||||
* Each of these control msrs has a low and high 32-bit half: A low bit is on
|
||||
* if the corresponding bit in the (32-bit) control field *must* be on, and a
|
||||
* bit in the high half is on if the corresponding bit in the control field
|
||||
* may be on. See also vmx_control_verify().
|
||||
*/
|
||||
void nested_vmx_setup_ctls_msrs(struct vmcs_config *vmcs_conf, u32 ept_caps)
|
||||
{
|
||||
struct nested_vmx_msrs *msrs = &vmcs_conf->nested;
|
||||
|
||||
/*
|
||||
* Note that as a general rule, the high half of the MSRs (bits in
|
||||
* the control fields which may be 1) should be initialized by the
|
||||
* intersection of the underlying hardware's MSR (i.e., features which
|
||||
* can be supported) and the list of features we want to expose -
|
||||
* because they are known to be properly supported in our code.
|
||||
* Also, usually, the low half of the MSRs (bits which must be 1) can
|
||||
* be set to 0, meaning that L1 may turn off any of these bits. The
|
||||
* reason is that if one of these bits is necessary, it will appear
|
||||
* in vmcs01 and prepare_vmcs02, when it bitwise-or's the control
|
||||
* fields of vmcs01 and vmcs02, will turn these bits off - and
|
||||
* nested_vmx_l1_wants_exit() will not pass related exits to L1.
|
||||
* These rules have exceptions below.
|
||||
*/
|
||||
nested_vmx_setup_pinbased_ctls(vmcs_conf, msrs);
|
||||
|
||||
nested_vmx_setup_exit_ctls(vmcs_conf, msrs);
|
||||
|
||||
nested_vmx_setup_entry_ctls(vmcs_conf, msrs);
|
||||
|
||||
nested_vmx_setup_cpubased_ctls(vmcs_conf, msrs);
|
||||
|
||||
nested_vmx_setup_secondary_ctls(ept_caps, vmcs_conf, msrs);
|
||||
|
||||
nested_vmx_setup_misc_data(vmcs_conf, msrs);
|
||||
|
||||
nested_vmx_setup_basic(msrs);
|
||||
|
||||
nested_vmx_setup_cr_fixed(msrs);
|
||||
|
||||
msrs->vmcs_enum = nested_vmx_calc_vmcs_enum_msr();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ static int sgx_get_encls_gva(struct kvm_vcpu *vcpu, unsigned long offset,
|
|||
|
||||
/* Skip vmcs.GUEST_DS retrieval for 64-bit mode to avoid VMREADs. */
|
||||
*gva = offset;
|
||||
if (!is_long_mode(vcpu)) {
|
||||
if (!is_64_bit_mode(vcpu)) {
|
||||
vmx_get_segment(vcpu, &s, VCPU_SREG_DS);
|
||||
*gva += s.base;
|
||||
}
|
||||
|
||||
if (!IS_ALIGNED(*gva, alignment)) {
|
||||
fault = true;
|
||||
} else if (likely(is_long_mode(vcpu))) {
|
||||
} else if (likely(is_64_bit_mode(vcpu))) {
|
||||
fault = is_noncanonical_address(*gva, vcpu);
|
||||
} else {
|
||||
*gva &= 0xffffffff;
|
||||
|
|
|
|||
|
|
@ -7900,6 +7900,21 @@ static int vmx_check_intercept(struct kvm_vcpu *vcpu,
|
|||
/* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED. */
|
||||
break;
|
||||
|
||||
case x86_intercept_pause:
|
||||
/*
|
||||
* PAUSE is a single-byte NOP with a REPE prefix, i.e. collides
|
||||
* with vanilla NOPs in the emulator. Apply the interception
|
||||
* check only to actual PAUSE instructions. Don't check
|
||||
* PAUSE-loop-exiting, software can't expect a given PAUSE to
|
||||
* exit, i.e. KVM is within its rights to allow L2 to execute
|
||||
* the PAUSE.
|
||||
*/
|
||||
if ((info->rep_prefix != REPE_PREFIX) ||
|
||||
!nested_cpu_has2(vmcs12, CPU_BASED_PAUSE_EXITING))
|
||||
return X86EMUL_CONTINUE;
|
||||
|
||||
break;
|
||||
|
||||
/* TODO: check more intercepts... */
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user