]> git.itanic.dy.fi Git - linux-stable/commitdiff
KVM: VMX: Extend VMX controls macro shenanigans
authorVitaly Kuznetsov <vkuznets@redhat.com>
Tue, 30 Aug 2022 13:37:27 +0000 (15:37 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 26 Sep 2022 16:02:54 +0000 (12:02 -0400)
When VMX controls macros are used to set or clear a control bit, make
sure that this bit was checked in setup_vmcs_config() and thus is properly
reflected in vmcs_config.

Opportunistically drop pointless "< 0" check for adjust_vmx_controls()'s
return value.

No functional change intended.

Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/r/20220830133737.1539624-24-vkuznets@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx.h

index 45f53eef077cb9d541cfb99eb0b731cb5424c9c9..70f795c1a0e062b16cb30c2d5418f1c3a0b7f289 100644 (file)
@@ -864,7 +864,7 @@ unsigned int __vmx_vcpu_run_flags(struct vcpu_vmx *vmx)
        return flags;
 }
 
-static void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx,
+static __always_inline void clear_atomic_switch_msr_special(struct vcpu_vmx *vmx,
                unsigned long entry, unsigned long exit)
 {
        vm_entry_controls_clearbit(vmx, entry);
@@ -922,7 +922,7 @@ static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
        vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->host.nr);
 }
 
-static void add_atomic_switch_msr_special(struct vcpu_vmx *vmx,
+static __always_inline void add_atomic_switch_msr_special(struct vcpu_vmx *vmx,
                unsigned long entry, unsigned long exit,
                unsigned long guest_val_vmcs, unsigned long host_val_vmcs,
                u64 guest_val, u64 host_val)
@@ -2525,7 +2525,6 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
                                    struct vmx_capability *vmx_cap)
 {
        u32 vmx_msr_low, vmx_msr_high;
-       u32 min, opt, min2, opt2;
        u32 _pin_based_exec_control = 0;
        u32 _cpu_based_exec_control = 0;
        u32 _cpu_based_2nd_exec_control = 0;
@@ -2551,29 +2550,11 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
        };
 
        memset(vmcs_conf, 0, sizeof(*vmcs_conf));
-       min = CPU_BASED_HLT_EXITING |
-#ifdef CONFIG_X86_64
-             CPU_BASED_CR8_LOAD_EXITING |
-             CPU_BASED_CR8_STORE_EXITING |
-#endif
-             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;
-
-       opt = CPU_BASED_TPR_SHADOW |
-             CPU_BASED_USE_MSR_BITMAPS |
-             CPU_BASED_NMI_WINDOW_EXITING |
-             CPU_BASED_ACTIVATE_SECONDARY_CONTROLS |
-             CPU_BASED_ACTIVATE_TERTIARY_CONTROLS;
-       if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PROCBASED_CTLS,
-                               &_cpu_based_exec_control) < 0)
+
+       if (adjust_vmx_controls(KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL,
+                               KVM_OPTIONAL_VMX_CPU_BASED_VM_EXEC_CONTROL,
+                               MSR_IA32_VMX_PROCBASED_CTLS,
+                               &_cpu_based_exec_control))
                return -EIO;
 #ifdef CONFIG_X86_64
        if (_cpu_based_exec_control & CPU_BASED_TPR_SHADOW)
@@ -2581,36 +2562,10 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
                                           ~CPU_BASED_CR8_STORE_EXITING;
 #endif
        if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS) {
-               min2 = 0;
-               opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
-                       SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |
-                       SECONDARY_EXEC_WBINVD_EXITING |
-                       SECONDARY_EXEC_ENABLE_VPID |
-                       SECONDARY_EXEC_ENABLE_EPT |
-                       SECONDARY_EXEC_UNRESTRICTED_GUEST |
-                       SECONDARY_EXEC_PAUSE_LOOP_EXITING |
-                       SECONDARY_EXEC_DESC |
-                       SECONDARY_EXEC_ENABLE_RDTSCP |
-                       SECONDARY_EXEC_ENABLE_INVPCID |
-                       SECONDARY_EXEC_APIC_REGISTER_VIRT |
-                       SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
-                       SECONDARY_EXEC_SHADOW_VMCS |
-                       SECONDARY_EXEC_XSAVES |
-                       SECONDARY_EXEC_RDSEED_EXITING |
-                       SECONDARY_EXEC_RDRAND_EXITING |
-                       SECONDARY_EXEC_ENABLE_PML |
-                       SECONDARY_EXEC_TSC_SCALING |
-                       SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE |
-                       SECONDARY_EXEC_PT_USE_GPA |
-                       SECONDARY_EXEC_PT_CONCEAL_VMX |
-                       SECONDARY_EXEC_ENABLE_VMFUNC |
-                       SECONDARY_EXEC_BUS_LOCK_DETECTION |
-                       SECONDARY_EXEC_NOTIFY_VM_EXITING |
-                       SECONDARY_EXEC_ENCLS_EXITING;
-
-               if (adjust_vmx_controls(min2, opt2,
+               if (adjust_vmx_controls(KVM_REQUIRED_VMX_SECONDARY_VM_EXEC_CONTROL,
+                                       KVM_OPTIONAL_VMX_SECONDARY_VM_EXEC_CONTROL,
                                        MSR_IA32_VMX_PROCBASED_CTLS2,
-                                       &_cpu_based_2nd_exec_control) < 0)
+                                       &_cpu_based_2nd_exec_control))
                        return -EIO;
        }
 #ifndef CONFIG_X86_64
@@ -2657,32 +2612,21 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
        if (!cpu_has_sgx())
                _cpu_based_2nd_exec_control &= ~SECONDARY_EXEC_ENCLS_EXITING;
 
-       if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS) {
-               u64 opt3 = TERTIARY_EXEC_IPI_VIRT;
-
-               _cpu_based_3rd_exec_control = adjust_vmx_controls64(opt3,
+       if (_cpu_based_exec_control & CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
+               _cpu_based_3rd_exec_control =
+                       adjust_vmx_controls64(KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL,
                                              MSR_IA32_VMX_PROCBASED_CTLS3);
-       }
 
-       min = VM_EXIT_SAVE_DEBUG_CONTROLS | VM_EXIT_ACK_INTR_ON_EXIT;
-#ifdef CONFIG_X86_64
-       min |= VM_EXIT_HOST_ADDR_SPACE_SIZE;
-#endif
-       opt = VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |
-             VM_EXIT_LOAD_IA32_PAT |
-             VM_EXIT_LOAD_IA32_EFER |
-             VM_EXIT_CLEAR_BNDCFGS |
-             VM_EXIT_PT_CONCEAL_PIP |
-             VM_EXIT_CLEAR_IA32_RTIT_CTL;
-       if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS,
-                               &_vmexit_control) < 0)
+       if (adjust_vmx_controls(KVM_REQUIRED_VMX_VM_EXIT_CONTROLS,
+                               KVM_OPTIONAL_VMX_VM_EXIT_CONTROLS,
+                               MSR_IA32_VMX_EXIT_CTLS,
+                               &_vmexit_control))
                return -EIO;
 
-       min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING;
-       opt = PIN_BASED_VIRTUAL_NMIS | PIN_BASED_POSTED_INTR |
-                PIN_BASED_VMX_PREEMPTION_TIMER;
-       if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS,
-                               &_pin_based_exec_control) < 0)
+       if (adjust_vmx_controls(KVM_REQUIRED_VMX_PIN_BASED_VM_EXEC_CONTROL,
+                               KVM_OPTIONAL_VMX_PIN_BASED_VM_EXEC_CONTROL,
+                               MSR_IA32_VMX_PINBASED_CTLS,
+                               &_pin_based_exec_control))
                return -EIO;
 
        if (cpu_has_broken_vmx_preemption_timer())
@@ -2691,18 +2635,10 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
                SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY))
                _pin_based_exec_control &= ~PIN_BASED_POSTED_INTR;
 
-       min = VM_ENTRY_LOAD_DEBUG_CONTROLS;
-#ifdef CONFIG_X86_64
-       min |= VM_ENTRY_IA32E_MODE;
-#endif
-       opt = 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;
-       if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS,
-                               &_vmentry_control) < 0)
+       if (adjust_vmx_controls(KVM_REQUIRED_VMX_VM_ENTRY_CONTROLS,
+                               KVM_OPTIONAL_VMX_VM_ENTRY_CONTROLS,
+                               MSR_IA32_VMX_ENTRY_CTLS,
+                               &_vmentry_control))
                return -EIO;
 
        for (i = 0; i < ARRAY_SIZE(vmcs_entry_exit_pairs); i++) {
index 35c7e6aef30162627c9f24caebab5b47b4d9729b..e927d35bece51c50343a98e1d9766c109ed549d9 100644 (file)
@@ -477,29 +477,138 @@ static inline u8 vmx_get_rvi(void)
        return vmcs_read16(GUEST_INTR_STATUS) & 0xff;
 }
 
-#define BUILD_CONTROLS_SHADOW(lname, uname, bits)                              \
-static inline void lname##_controls_set(struct vcpu_vmx *vmx, u##bits val)     \
-{                                                                              \
-       if (vmx->loaded_vmcs->controls_shadow.lname != val) {                   \
-               vmcs_write##bits(uname, val);                                   \
-               vmx->loaded_vmcs->controls_shadow.lname = val;                  \
-       }                                                                       \
-}                                                                              \
-static inline u##bits __##lname##_controls_get(struct loaded_vmcs *vmcs)       \
-{                                                                              \
-       return vmcs->controls_shadow.lname;                                     \
-}                                                                              \
-static inline u##bits lname##_controls_get(struct vcpu_vmx *vmx)               \
-{                                                                              \
-       return __##lname##_controls_get(vmx->loaded_vmcs);                      \
-}                                                                              \
-static inline void lname##_controls_setbit(struct vcpu_vmx *vmx, u##bits val)  \
-{                                                                              \
-       lname##_controls_set(vmx, lname##_controls_get(vmx) | val);             \
-}                                                                              \
-static inline void lname##_controls_clearbit(struct vcpu_vmx *vmx, u##bits val)        \
-{                                                                              \
-       lname##_controls_set(vmx, lname##_controls_get(vmx) & ~val);            \
+#define __KVM_REQUIRED_VMX_VM_ENTRY_CONTROLS                           \
+       (VM_ENTRY_LOAD_DEBUG_CONTROLS)
+#ifdef CONFIG_X86_64
+       #define KVM_REQUIRED_VMX_VM_ENTRY_CONTROLS                      \
+               (__KVM_REQUIRED_VMX_VM_ENTRY_CONTROLS |                 \
+                VM_ENTRY_IA32E_MODE)
+#else
+       #define KVM_REQUIRED_VMX_VM_ENTRY_CONTROLS                      \
+               __KVM_REQUIRED_VMX_VM_ENTRY_CONTROLS
+#endif
+#define KVM_OPTIONAL_VMX_VM_ENTRY_CONTROLS                             \
+       (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 __KVM_REQUIRED_VMX_VM_EXIT_CONTROLS                            \
+       (VM_EXIT_SAVE_DEBUG_CONTROLS |                                  \
+        VM_EXIT_ACK_INTR_ON_EXIT)
+#ifdef CONFIG_X86_64
+       #define KVM_REQUIRED_VMX_VM_EXIT_CONTROLS                       \
+               (__KVM_REQUIRED_VMX_VM_EXIT_CONTROLS |                  \
+                VM_EXIT_HOST_ADDR_SPACE_SIZE)
+#else
+       #define KVM_REQUIRED_VMX_VM_EXIT_CONTROLS                       \
+               __KVM_REQUIRED_VMX_VM_EXIT_CONTROLS
+#endif
+#define KVM_OPTIONAL_VMX_VM_EXIT_CONTROLS                              \
+             (VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL |                     \
+              VM_EXIT_LOAD_IA32_PAT |                                  \
+              VM_EXIT_LOAD_IA32_EFER |                                 \
+              VM_EXIT_CLEAR_BNDCFGS |                                  \
+              VM_EXIT_PT_CONCEAL_PIP |                                 \
+              VM_EXIT_CLEAR_IA32_RTIT_CTL)
+
+#define KVM_REQUIRED_VMX_PIN_BASED_VM_EXEC_CONTROL                     \
+       (PIN_BASED_EXT_INTR_MASK |                                      \
+        PIN_BASED_NMI_EXITING)
+#define KVM_OPTIONAL_VMX_PIN_BASED_VM_EXEC_CONTROL                     \
+       (PIN_BASED_VIRTUAL_NMIS |                                       \
+        PIN_BASED_POSTED_INTR |                                        \
+        PIN_BASED_VMX_PREEMPTION_TIMER)
+
+#define __KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL                   \
+       (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)
+
+#ifdef CONFIG_X86_64
+       #define KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL              \
+               (__KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL |         \
+                CPU_BASED_CR8_LOAD_EXITING |                           \
+                CPU_BASED_CR8_STORE_EXITING)
+#else
+       #define KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL              \
+               __KVM_REQUIRED_VMX_CPU_BASED_VM_EXEC_CONTROL
+#endif
+
+#define KVM_OPTIONAL_VMX_CPU_BASED_VM_EXEC_CONTROL                     \
+       (CPU_BASED_TPR_SHADOW |                                         \
+        CPU_BASED_USE_MSR_BITMAPS |                                    \
+        CPU_BASED_NMI_WINDOW_EXITING |                                 \
+        CPU_BASED_ACTIVATE_SECONDARY_CONTROLS |                        \
+        CPU_BASED_ACTIVATE_TERTIARY_CONTROLS)
+
+#define KVM_REQUIRED_VMX_SECONDARY_VM_EXEC_CONTROL 0
+#define KVM_OPTIONAL_VMX_SECONDARY_VM_EXEC_CONTROL                     \
+       (SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |                      \
+        SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE |                        \
+        SECONDARY_EXEC_WBINVD_EXITING |                                \
+        SECONDARY_EXEC_ENABLE_VPID |                                   \
+        SECONDARY_EXEC_ENABLE_EPT |                                    \
+        SECONDARY_EXEC_UNRESTRICTED_GUEST |                            \
+        SECONDARY_EXEC_PAUSE_LOOP_EXITING |                            \
+        SECONDARY_EXEC_DESC |                                          \
+        SECONDARY_EXEC_ENABLE_RDTSCP |                                 \
+        SECONDARY_EXEC_ENABLE_INVPCID |                                \
+        SECONDARY_EXEC_APIC_REGISTER_VIRT |                            \
+        SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |                         \
+        SECONDARY_EXEC_SHADOW_VMCS |                                   \
+        SECONDARY_EXEC_XSAVES |                                        \
+        SECONDARY_EXEC_RDSEED_EXITING |                                \
+        SECONDARY_EXEC_RDRAND_EXITING |                                \
+        SECONDARY_EXEC_ENABLE_PML |                                    \
+        SECONDARY_EXEC_TSC_SCALING |                                   \
+        SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE |                         \
+        SECONDARY_EXEC_PT_USE_GPA |                                    \
+        SECONDARY_EXEC_PT_CONCEAL_VMX |                                \
+        SECONDARY_EXEC_ENABLE_VMFUNC |                                 \
+        SECONDARY_EXEC_BUS_LOCK_DETECTION |                            \
+        SECONDARY_EXEC_NOTIFY_VM_EXITING |                             \
+        SECONDARY_EXEC_ENCLS_EXITING)
+
+#define KVM_REQUIRED_VMX_TERTIARY_VM_EXEC_CONTROL 0
+#define KVM_OPTIONAL_VMX_TERTIARY_VM_EXEC_CONTROL                      \
+       (TERTIARY_EXEC_IPI_VIRT)
+
+#define BUILD_CONTROLS_SHADOW(lname, uname, bits)                                              \
+static inline void lname##_controls_set(struct vcpu_vmx *vmx, u##bits val)                     \
+{                                                                                              \
+       if (vmx->loaded_vmcs->controls_shadow.lname != val) {                                   \
+               vmcs_write##bits(uname, val);                                                   \
+               vmx->loaded_vmcs->controls_shadow.lname = val;                                  \
+       }                                                                                       \
+}                                                                                              \
+static inline u##bits __##lname##_controls_get(struct loaded_vmcs *vmcs)                       \
+{                                                                                              \
+       return vmcs->controls_shadow.lname;                                                     \
+}                                                                                              \
+static inline u##bits lname##_controls_get(struct vcpu_vmx *vmx)                               \
+{                                                                                              \
+       return __##lname##_controls_get(vmx->loaded_vmcs);                                      \
+}                                                                                              \
+static __always_inline void lname##_controls_setbit(struct vcpu_vmx *vmx, u##bits val)         \
+{                                                                                              \
+       BUILD_BUG_ON(!(val & (KVM_REQUIRED_VMX_##uname | KVM_OPTIONAL_VMX_##uname)));           \
+       lname##_controls_set(vmx, lname##_controls_get(vmx) | val);                             \
+}                                                                                              \
+static __always_inline void lname##_controls_clearbit(struct vcpu_vmx *vmx, u##bits val)       \
+{                                                                                              \
+       BUILD_BUG_ON(!(val & (KVM_REQUIRED_VMX_##uname | KVM_OPTIONAL_VMX_##uname)));           \
+       lname##_controls_set(vmx, lname##_controls_get(vmx) & ~val);                            \
 }
 BUILD_CONTROLS_SHADOW(vm_entry, VM_ENTRY_CONTROLS, 32)
 BUILD_CONTROLS_SHADOW(vm_exit, VM_EXIT_CONTROLS, 32)