| From foo@baz Tue Aug 14 16:14:56 CEST 2018 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Fri, 13 Jul 2018 16:23:18 +0200 |
| Subject: x86/l1tf: Handle EPT disabled state proper |
| |
| From: Thomas Gleixner <tglx@linutronix.de> |
| |
| 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: David Woodhouse <dwmw@amazon.co.uk> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/include/asm/vmx.h | 1 + |
| arch/x86/kernel/cpu/bugs.c | 9 +++++---- |
| arch/x86/kvm/vmx.c | 44 ++++++++++++++++++++++++++------------------ |
| 3 files changed, 32 insertions(+), 22 deletions(-) |
| |
| --- a/arch/x86/include/asm/vmx.h |
| +++ b/arch/x86/include/asm/vmx.h |
| @@ -504,6 +504,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; |
| --- a/arch/x86/kernel/cpu/bugs.c |
| +++ b/arch/x86/kernel/cpu/bugs.c |
| @@ -675,10 +675,11 @@ static void __init l1tf_select_mitigatio |
| |
| #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) |
| --- a/arch/x86/kvm/vmx.c |
| +++ b/arch/x86/kvm/vmx.c |
| @@ -11659,6 +11659,11 @@ static int __init vmx_setup_l1d_flush(vo |
| 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) |
| @@ -11685,18 +11690,35 @@ 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(); |
| + |
| + vmx_cleanup_l1d_flush(); |
| +} |
| +module_exit(vmx_exit) |
| + |
| static int __init vmx_init(void) |
| { |
| int r; |
| |
| - 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; |
| } |
| |
| @@ -11707,18 +11729,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(); |
| - |
| - vmx_cleanup_l1d_flush(); |
| -} |
| - |
| module_init(vmx_init) |
| -module_exit(vmx_exit) |