]> git.itanic.dy.fi Git - linux-stable/commitdiff
KVM: nVMX: Invert 'unsupported by eVMCSv1' check
authorVitaly Kuznetsov <vkuznets@redhat.com>
Fri, 4 Nov 2022 14:47:06 +0000 (15:47 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 27 Dec 2022 11:02:55 +0000 (06:02 -0500)
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: Vitaly Kuznetsov <vkuznets@redhat.com>
Message-Id: <20221104144708.435865-3-vkuznets@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/hyperv.c
arch/x86/kvm/vmx/hyperv.h

index 04ea0259ab7feb14d4b02d639b3cbb10f98729ef..77027f6a9b41e1a574ebb1e9131bc12b540b9bcf 100644 (file)
@@ -368,32 +368,32 @@ enum evmcs_ctrl_type {
        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] = {
-               [EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_VMEXIT_CTRL,
+               [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMEXIT_CTRL,
        },
        [EVMCS_ENTRY_CTRLS] = {
-               [EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_VMENTRY_CTRL,
+               [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_VMENTRY_CTRL,
        },
        [EVMCS_EXEC_CTRL] = {
-               [EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_EXEC_CTRL,
+               [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_EXEC_CTRL,
        },
        [EVMCS_2NDEXEC] = {
-               [EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_2NDEXEC,
+               [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_2NDEXEC & ~SECONDARY_EXEC_TSC_SCALING,
        },
        [EVMCS_PINCTRL] = {
-               [EVMCSv1_LEGACY] = EVMCS1_UNSUPPORTED_PINCTRL,
+               [EVMCSv1_LEGACY] = EVMCS1_SUPPORTED_PINCTRL,
        },
        [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;
 
-       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)
@@ -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_high = (u32)(*pdata >> 32);
-       u32 unsupported_ctrls;
+       u32 supported_ctrls;
 
        /*
         * 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 *
        switch (msr_index) {
        case MSR_IA32_VMX_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))
-                       unsupported_ctrls |= VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
-               ctl_high &= ~unsupported_ctrls;
+                       supported_ctrls &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
+               ctl_high &= supported_ctrls;
                break;
        case MSR_IA32_VMX_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))
-                       unsupported_ctrls |= VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
-               ctl_high &= ~unsupported_ctrls;
+                       supported_ctrls &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+               ctl_high &= supported_ctrls;
                break;
        case MSR_IA32_VMX_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;
        case MSR_IA32_VMX_PROCBASED_CTLS2:
-               ctl_high &= ~evmcs_get_unsupported_ctls(EVMCS_2NDEXEC);
+               ctl_high &= evmcs_get_supported_ctls(EVMCS_2NDEXEC);
                break;
        case MSR_IA32_VMX_TRUE_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;
        case MSR_IA32_VMX_VMFUNC:
-               ctl_low &= ~evmcs_get_unsupported_ctls(EVMCS_VMFUNC);
+               ctl_low &= evmcs_get_supported_ctls(EVMCS_VMFUNC);
                break;
        }
 
@@ -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,
                                           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)
index 571e7929d14e7b83058228291158f0e96933bf68..a9da47c69a2be69e1c52f503405f96f00cd06f75 100644 (file)
@@ -48,22 +48,82 @@ DECLARE_STATIC_KEY_FALSE(enable_evmcs);
  * Currently unsupported in KVM:
  *     GUEST_IA32_RTIT_CTL             = 0x00002814,
  */
-#define EVMCS1_UNSUPPORTED_PINCTRL (PIN_BASED_POSTED_INTR | \
-                                   PIN_BASED_VMX_PREEMPTION_TIMER)
-#define EVMCS1_UNSUPPORTED_EXEC_CTRL (CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
-#define EVMCS1_UNSUPPORTED_2NDEXEC                                     \
-       (SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |                         \
-        SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |                      \
-        SECONDARY_EXEC_APIC_REGISTER_VIRT |                            \
-        SECONDARY_EXEC_ENABLE_PML |                                    \
-        SECONDARY_EXEC_ENABLE_VMFUNC |                                 \
-        SECONDARY_EXEC_SHADOW_VMCS |                                   \
+#define EVMCS1_SUPPORTED_PINCTRL                                       \
+       (PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |                          \
+        PIN_BASED_EXT_INTR_MASK |                                      \
+        PIN_BASED_NMI_EXITING |                                        \
+        PIN_BASED_VIRTUAL_NMIS)
+
+#define EVMCS1_SUPPORTED_EXEC_CTRL                                     \
+       (CPU_BASED_ALWAYSON_WITHOUT_TRUE_MSR |                          \
+        CPU_BASED_HLT_EXITING |                                        \
+        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_PAUSE_LOOP_EXITING)
-#define EVMCS1_UNSUPPORTED_VMEXIT_CTRL                                 \
-       (VM_EXIT_SAVE_VMX_PREEMPTION_TIMER)
-#define EVMCS1_UNSUPPORTED_VMENTRY_CTRL (0)
-#define EVMCS1_UNSUPPORTED_VMFUNC (VMX_VMFUNC_EPTP_SWITCHING)
+        SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE |                         \
+        SECONDARY_EXEC_PT_USE_GPA |                                    \
+        SECONDARY_EXEC_PT_CONCEAL_VMX |                                \
+        SECONDARY_EXEC_BUS_LOCK_DETECTION |                            \
+        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 {
        u16 offset;