Commit 70b31e50 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Paolo Bonzini

KVM: nVMX: Invert 'unsupported by eVMCSv1' check

When a new feature gets implemented in KVM, EVMCS1_UNSUPPORTED_* defines
need to be adjusted to avoid the situation when the feature is exposed
to the guest but there's no corresponding eVMCS field[s] for it. This
is not obvious and fragile. Invert 'unsupported by eVMCSv1' check and
make it 'supported by eVMCSv1' instead, this way it's much harder to
make a mistake. New features will get added to EVMCS1_SUPPORTED_*
defines when the corresponding fields are added to eVMCS definition.

No functional change intended. EVMCS1_SUPPORTED_* defines are composed
by taking KVM_{REQUIRED,OPTIONAL}_VMX_ defines and filtering out what
was previously known as EVMCS1_UNSUPPORTED_*.

From all the controls, SECONDARY_EXEC_TSC_SCALING requires special
handling as it's actually present in eVMCSv1 definition but is not
currently supported for Hyper-V-on-KVM, just for KVM-on-Hyper-V. As
evmcs_supported_ctrls will be used for both scenarios, just add it
there instead of EVMCS1_SUPPORTED_2NDEXEC.
Signed-off-by: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20221104144708.435865-3-vkuznets@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent bbbaf8cd
...@@ -368,32 +368,32 @@ enum evmcs_ctrl_type { ...@@ -368,32 +368,32 @@ enum evmcs_ctrl_type {
NR_EVMCS_CTRLS, NR_EVMCS_CTRLS,
}; };
static const u32 evmcs_unsupported_ctrls[NR_EVMCS_CTRLS][NR_EVMCS_REVISIONS] = { static const u32 evmcs_supported_ctrls[NR_EVMCS_CTRLS][NR_EVMCS_REVISIONS] = {
[EVMCS_EXIT_CTRLS] = { [EVMCS_EXIT_CTRLS] = {
[EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_VMEXIT_CTRL, [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMEXIT_CTRL,
}, },
[EVMCS_ENTRY_CTRLS] = { [EVMCS_ENTRY_CTRLS] = {
[EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_VMENTRY_CTRL, [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMENTRY_CTRL,
}, },
[EVMCS_EXEC_CTRL] = { [EVMCS_EXEC_CTRL] = {
[EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_EXEC_CTRL, [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_EXEC_CTRL,
}, },
[EVMCS_2NDEXEC] = { [EVMCS_2NDEXEC] = {
[EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_2NDEXEC, [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_2NDEXEC & ~SECONDARY_EXEC_TSC_SCALING,
}, },
[EVMCS_PINCTRL] = { [EVMCS_PINCTRL] = {
[EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_PINCTRL, [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_PINCTRL,
}, },
[EVMCS_VMFUNC] = { [EVMCS_VMFUNC] = {
[EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_VMFUNC, [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMFUNC,
}, },
}; };
static u32 evmcs_get_unsupported_ctls(enum evmcs_ctrl_type ctrl_type) static u32 evmcs_get_supported_ctls(enum evmcs_ctrl_type ctrl_type)
{ {
enum evmcs_revision evmcs_rev = EVMCSv1_LEGACY; enum evmcs_revision evmcs_rev = EVMCSv1_LEGACY;
return evmcs_unsupported_ctrls[ctrl_type][evmcs_rev]; return evmcs_supported_ctrls[ctrl_type][evmcs_rev];
} }
static bool evmcs_has_perf_global_ctrl(struct kvm_vcpu *vcpu) static bool evmcs_has_perf_global_ctrl(struct kvm_vcpu *vcpu)
...@@ -417,7 +417,7 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 * ...@@ -417,7 +417,7 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *
{ {
u32 ctl_low = (u32)*pdata; u32 ctl_low = (u32)*pdata;
u32 ctl_high = (u32)(*pdata >> 32); u32 ctl_high = (u32)(*pdata >> 32);
u32 unsupported_ctrls; u32 supported_ctrls;
/* /*
* Hyper-V 2016 and 2019 try using these features even when eVMCS * Hyper-V 2016 and 2019 try using these features even when eVMCS
...@@ -426,31 +426,31 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 * ...@@ -426,31 +426,31 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *
switch (msr_index) { switch (msr_index) {
case MSR_IA32_VMX_EXIT_CTLS: case MSR_IA32_VMX_EXIT_CTLS:
case MSR_IA32_VMX_TRUE_EXIT_CTLS: case MSR_IA32_VMX_TRUE_EXIT_CTLS:
unsupported_ctrls = evmcs_get_unsupported_ctls(EVMCS_EXIT_CTRLS); supported_ctrls = evmcs_get_supported_ctls(EVMCS_EXIT_CTRLS);
if (!evmcs_has_perf_global_ctrl(vcpu)) if (!evmcs_has_perf_global_ctrl(vcpu))
unsupported_ctrls |= VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL; supported_ctrls &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
ctl_high &= ~unsupported_ctrls; ctl_high &= supported_ctrls;
break; break;
case MSR_IA32_VMX_ENTRY_CTLS: case MSR_IA32_VMX_ENTRY_CTLS:
case MSR_IA32_VMX_TRUE_ENTRY_CTLS: case MSR_IA32_VMX_TRUE_ENTRY_CTLS:
unsupported_ctrls = evmcs_get_unsupported_ctls(EVMCS_ENTRY_CTRLS); supported_ctrls = evmcs_get_supported_ctls(EVMCS_ENTRY_CTRLS);
if (!evmcs_has_perf_global_ctrl(vcpu)) if (!evmcs_has_perf_global_ctrl(vcpu))
unsupported_ctrls |= VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL; supported_ctrls &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
ctl_high &= ~unsupported_ctrls; ctl_high &= supported_ctrls;
break; break;
case MSR_IA32_VMX_PROCBASED_CTLS: case MSR_IA32_VMX_PROCBASED_CTLS:
case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: case MSR_IA32_VMX_TRUE_PROCBASED_CTLS:
ctl_high &= ~evmcs_get_unsupported_ctls(EVMCS_EXEC_CTRL); ctl_high &= evmcs_get_supported_ctls(EVMCS_EXEC_CTRL);
break; break;
case MSR_IA32_VMX_PROCBASED_CTLS2: case MSR_IA32_VMX_PROCBASED_CTLS2:
ctl_high &= ~evmcs_get_unsupported_ctls(EVMCS_2NDEXEC); ctl_high &= evmcs_get_supported_ctls(EVMCS_2NDEXEC);
break; break;
case MSR_IA32_VMX_TRUE_PINBASED_CTLS: case MSR_IA32_VMX_TRUE_PINBASED_CTLS:
case MSR_IA32_VMX_PINBASED_CTLS: case MSR_IA32_VMX_PINBASED_CTLS:
ctl_high &= ~evmcs_get_unsupported_ctls(EVMCS_PINCTRL); ctl_high &= evmcs_get_supported_ctls(EVMCS_PINCTRL);
break; break;
case MSR_IA32_VMX_VMFUNC: case MSR_IA32_VMX_VMFUNC:
ctl_low &= ~evmcs_get_unsupported_ctls(EVMCS_VMFUNC); ctl_low &= evmcs_get_supported_ctls(EVMCS_VMFUNC);
break; break;
} }
...@@ -460,7 +460,7 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 * ...@@ -460,7 +460,7 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *
static bool nested_evmcs_is_valid_controls(enum evmcs_ctrl_type ctrl_type, static bool nested_evmcs_is_valid_controls(enum evmcs_ctrl_type ctrl_type,
u32 val) u32 val)
{ {
return !(val & evmcs_get_unsupported_ctls(ctrl_type)); return !(val & ~evmcs_get_supported_ctls(ctrl_type));
} }
int nested_evmcs_check_controls(struct vmcs12 *vmcs12) int nested_evmcs_check_controls(struct vmcs12 *vmcs12)
......
...@@ -48,22 +48,82 @@ DECLARE_STATIC_KEY_FALSE(enable_evmcs); ...@@ -48,22 +48,82 @@ DECLARE_STATIC_KEY_FALSE(enable_evmcs);
* Currently unsupported in KVM: * Currently unsupported in KVM:
* GUEST_IA32_RTIT_CTL = 0x00002814, * GUEST_IA32_RTIT_CTL = 0x00002814,
*/ */
#define EVMCS1_UNSUPPORTED_PINCTRL (PIN_BASED_POSTED_INTR | \ #define EVMCS1_SUPPORTED_PINCTRL \
PIN_BASED_VMX_PREEMPTION_TIMER) (PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \
#define EVMCS1_UNSUPPORTED_EXEC_CTRL (CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) PIN_BASED_EXT_INTR_MASK | \
#define EVMCS1_UNSUPPORTED_2NDEXEC \ PIN_BASED_NMI_EXITING | \
(SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | \ PIN_BASED_VIRTUAL_NMIS)
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | \
SECONDARY_EXEC_APIC_REGISTER_VIRT | \ #define EVMCS1_SUPPORTED_EXEC_CTRL \
SECONDARY_EXEC_ENABLE_PML | \ (CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR | \
SECONDARY_EXEC_ENABLE_VMFUNC | \ CPU_BASED_HLT_EXITING | \
SECONDARY_EXEC_SHADOW_VMCS | \ CPU_BASED_CR3_LOAD_EXITING | \
CPU_BASED_CR3_STORE_EXITING | \
CPU_BASED_UNCOND_IO_EXITING | \
CPU_BASED_MOV_DR_EXITING | \
CPU_BASED_USE_TSC_OFFSETTING | \
CPU_BASED_MWAIT_EXITING | \
CPU_BASED_MONITOR_EXITING | \
CPU_BASED_INVLPG_EXITING | \
CPU_BASED_RDPMC_EXITING | \
CPU_BASED_INTR_WINDOW_EXITING | \
CPU_BASED_CR8_LOAD_EXITING | \
CPU_BASED_CR8_STORE_EXITING | \
CPU_BASED_RDTSC_EXITING | \
CPU_BASED_TPR_SHADOW | \
CPU_BASED_USE_IO_BITMAPS | \
CPU_BASED_MONITOR_TRAP_FLAG | \
CPU_BASED_USE_MSR_BITMAPS | \
CPU_BASED_NMI_WINDOW_EXITING | \
CPU_BASED_PAUSE_EXITING | \
CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
#define EVMCS1_SUPPORTED_2NDEXEC \
(SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | \
SECONDARY_EXEC_WBINVD_EXITING | \
SECONDARY_EXEC_ENABLE_VPID | \
SECONDARY_EXEC_ENABLE_EPT | \
SECONDARY_EXEC_UNRESTRICTED_GUEST | \
SECONDARY_EXEC_DESC | \
SECONDARY_EXEC_ENABLE_RDTSCP | \
SECONDARY_EXEC_ENABLE_INVPCID | \
SECONDARY_EXEC_XSAVES | \
SECONDARY_EXEC_RDSEED_EXITING | \
SECONDARY_EXEC_RDRAND_EXITING | \
SECONDARY_EXEC_TSC_SCALING | \ SECONDARY_EXEC_TSC_SCALING | \
SECONDARY_EXEC_PAUSE_LOOP_EXITING) SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE | \
#define EVMCS1_UNSUPPORTED_VMEXIT_CTRL \ SECONDARY_EXEC_PT_USE_GPA | \
(VM_EXIT_SAVE_VMX_PREEMPTION_TIMER) SECONDARY_EXEC_PT_CONCEAL_VMX | \
#define EVMCS1_UNSUPPORTED_VMENTRY_CTRL (0) SECONDARY_EXEC_BUS_LOCK_DETECTION | \
#define EVMCS1_UNSUPPORTED_VMFUNC (VMX_VMFUNC_EPTP_SWITCHING) SECONDARY_EXEC_NOTIFY_VM_EXITING | \
SECONDARY_EXEC_ENCLS_EXITING)
#define EVMCS1_SUPPORTED_VMEXIT_CTRL \
(VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR | \
VM_EXIT_SAVE_DEBUG_CONTROLS | \
VM_EXIT_ACK_INTR_ON_EXIT | \
VM_EXIT_HOST_ADDR_SPACE_SIZE | \
VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | \
VM_EXIT_SAVE_IA32_PAT | \
VM_EXIT_LOAD_IA32_PAT | \
VM_EXIT_SAVE_IA32_EFER | \
VM_EXIT_LOAD_IA32_EFER | \
VM_EXIT_CLEAR_BNDCFGS | \
VM_EXIT_PT_CONCEAL_PIP | \
VM_EXIT_CLEAR_IA32_RTIT_CTL)
#define EVMCS1_SUPPORTED_VMENTRY_CTRL \
(VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR | \
VM_ENTRY_LOAD_DEBUG_CONTROLS | \
VM_ENTRY_IA32E_MODE | \
VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | \
VM_ENTRY_LOAD_IA32_PAT | \
VM_ENTRY_LOAD_IA32_EFER | \
VM_ENTRY_LOAD_BNDCFGS | \
VM_ENTRY_PT_CONCEAL_PIP | \
VM_ENTRY_LOAD_IA32_RTIT_CTL)
#define EVMCS1_SUPPORTED_VMFUNC (0)
struct evmcs_field { struct evmcs_field {
u16 offset; u16 offset;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment