]> git.hungrycats.org Git - linux/commitdiff
x86/l1tf: Handle EPT disabled state proper
authorThomas Gleixner <tglx@linutronix.de>
Fri, 13 Jul 2018 14:23:18 +0000 (16:23 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 15 Aug 2018 16:11:04 +0000 (18:11 +0200)
commit a7b9020b06ec6d7c3f3b0d4ef1a9eba12654f4f7 upstream

If Extended Page Tables (EPT) are disabled or not supported, no L1D
flushing is required. The setup function can just avoid setting up the L1D
flush for the EPT=n case.

Invoke it after the hardware setup has be done and enable_ept has the
correct state and expose the EPT disabled state in the mitigation status as
well.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Jiri Kosina <jkosina@suse.cz>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
Link: https://lkml.kernel.org/r/20180713142322.612160168@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/include/asm/vmx.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kvm/vmx.c

index 28c0e4bbe0e63aefa863fdde569d06edfa02833f..cf4e1a210006658ad2cca74f11e2bac7f5784672 100644 (file)
@@ -579,6 +579,7 @@ enum vmx_l1d_flush_state {
        VMENTER_L1D_FLUSH_NEVER,
        VMENTER_L1D_FLUSH_COND,
        VMENTER_L1D_FLUSH_ALWAYS,
+       VMENTER_L1D_FLUSH_EPT_DISABLED,
 };
 
 extern enum vmx_l1d_flush_state l1tf_vmx_mitigation;
index 511e6d63d9dd4b2c5f7cffff6137a721c1f7404e..b75828cf7715bf4d6145f5dbef7ad1c0365116ce 100644 (file)
@@ -676,10 +676,11 @@ static void __init l1tf_select_mitigation(void)
 
 #if IS_ENABLED(CONFIG_KVM_INTEL)
 static const char *l1tf_vmx_states[] = {
-       [VMENTER_L1D_FLUSH_AUTO]        = "auto",
-       [VMENTER_L1D_FLUSH_NEVER]       = "vulnerable",
-       [VMENTER_L1D_FLUSH_COND]        = "conditional cache flushes",
-       [VMENTER_L1D_FLUSH_ALWAYS]      = "cache flushes",
+       [VMENTER_L1D_FLUSH_AUTO]                = "auto",
+       [VMENTER_L1D_FLUSH_NEVER]               = "vulnerable",
+       [VMENTER_L1D_FLUSH_COND]                = "conditional cache flushes",
+       [VMENTER_L1D_FLUSH_ALWAYS]              = "cache flushes",
+       [VMENTER_L1D_FLUSH_EPT_DISABLED]        = "EPT disabled",
 };
 
 static ssize_t l1tf_show_state(char *buf)
index db62bf3adc0d3eded857d782286c56e7336559a0..b7265378d2144f790a27a69bfbd27493e27360b8 100644 (file)
@@ -13023,6 +13023,11 @@ static int __init vmx_setup_l1d_flush(void)
        if (!boot_cpu_has_bug(X86_BUG_L1TF))
                return 0;
 
+       if (!enable_ept) {
+               l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_EPT_DISABLED;
+               return 0;
+       }
+
        l1tf_vmx_mitigation = vmentry_l1d_flush;
 
        if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER)
@@ -13049,6 +13054,41 @@ static void vmx_cleanup_l1d_flush(void)
        l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO;
 }
 
+static void vmx_exit(void)
+{
+#ifdef CONFIG_KEXEC_CORE
+       RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL);
+       synchronize_rcu();
+#endif
+
+       kvm_exit();
+
+#if IS_ENABLED(CONFIG_HYPERV)
+       if (static_branch_unlikely(&enable_evmcs)) {
+               int cpu;
+               struct hv_vp_assist_page *vp_ap;
+               /*
+                * Reset everything to support using non-enlightened VMCS
+                * access later (e.g. when we reload the module with
+                * enlightened_vmcs=0)
+                */
+               for_each_online_cpu(cpu) {
+                       vp_ap = hv_get_vp_assist_page(cpu);
+
+                       if (!vp_ap)
+                               continue;
+
+                       vp_ap->current_nested_vmcs = 0;
+                       vp_ap->enlighten_vmentry = 0;
+               }
+
+               static_branch_disable(&enable_evmcs);
+       }
+#endif
+       vmx_cleanup_l1d_flush();
+}
+module_exit(vmx_exit);
+
 static int __init vmx_init(void)
 {
        int r;
@@ -13082,14 +13122,17 @@ static int __init vmx_init(void)
        }
 #endif
 
-       r = vmx_setup_l1d_flush();
+       r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx),
+                    __alignof__(struct vcpu_vmx), THIS_MODULE);
        if (r)
                return r;
 
-       r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx),
-                    __alignof__(struct vcpu_vmx), THIS_MODULE);
+       /*
+        * Must be called after kvm_init() so enable_ept is properly set up
+        */
+       r = vmx_setup_l1d_flush();
        if (r) {
-               vmx_cleanup_l1d_flush();
+               vmx_exit();
                return r;
        }
 
@@ -13100,40 +13143,4 @@ static int __init vmx_init(void)
 
        return 0;
 }
-
-static void __exit vmx_exit(void)
-{
-#ifdef CONFIG_KEXEC_CORE
-       RCU_INIT_POINTER(crash_vmclear_loaded_vmcss, NULL);
-       synchronize_rcu();
-#endif
-
-       kvm_exit();
-
-#if IS_ENABLED(CONFIG_HYPERV)
-       if (static_branch_unlikely(&enable_evmcs)) {
-               int cpu;
-               struct hv_vp_assist_page *vp_ap;
-               /*
-                * Reset everything to support using non-enlightened VMCS
-                * access later (e.g. when we reload the module with
-                * enlightened_vmcs=0)
-                */
-               for_each_online_cpu(cpu) {
-                       vp_ap = hv_get_vp_assist_page(cpu);
-
-                       if (!vp_ap)
-                               continue;
-
-                       vp_ap->current_nested_vmcs = 0;
-                       vp_ap->enlighten_vmentry = 0;
-               }
-
-               static_branch_disable(&enable_evmcs);
-       }
-#endif
-       vmx_cleanup_l1d_flush();
-}
-
-module_init(vmx_init)
-module_exit(vmx_exit)
+module_init(vmx_init);