Skip to content

Commit 05bd639

Browse files
committed
KVM: VMX: Disable L1TF L1 data cache flush if CONFIG_CPU_MITIGATIONS=n
Disable support for flushing the L1 data cache to mitigate L1TF if CPU mitigations are disabled for the entire kernel. KVM's mitigation of L1TF is in no way special enough to justify ignoring CONFIG_CPU_MITIGATIONS=n. Deliberately use CPU_MITIGATIONS instead of the more precise MITIGATION_L1TF, as MITIGATION_L1TF only controls the default behavior, i.e. CONFIG_MITIGATION_L1TF=n doesn't completely disable L1TF mitigations in the kernel. Keep the vmentry_l1d_flush module param to avoid breaking existing setups, and leverage the .set path to alert the user to the fact that vmentry_l1d_flush will be ignored. Don't bother validating the incoming value; if an admin misconfigures vmentry_l1d_flush, the fact that the bad configuration won't be detected when running with CONFIG_CPU_MITIGATIONS=n is likely the least of their worries. Reviewed-by: Brendan Jackman <jackmanb@google.com> Link: https://patch.msgid.link/20251113233746.1703361-9-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 0abd961 commit 05bd639

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

arch/x86/include/asm/hardirq.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <linux/threads.h>
66

77
typedef struct {
8-
#if IS_ENABLED(CONFIG_KVM_INTEL)
8+
#if IS_ENABLED(CONFIG_CPU_MITIGATIONS) && IS_ENABLED(CONFIG_KVM_INTEL)
99
u8 kvm_cpu_l1tf_flush_l1d;
1010
#endif
1111
unsigned int __nmi_count; /* arch dependent */
@@ -68,7 +68,7 @@ extern u64 arch_irq_stat(void);
6868
DECLARE_PER_CPU_CACHE_HOT(u16, __softirq_pending);
6969
#define local_softirq_pending_ref __softirq_pending
7070

71-
#if IS_ENABLED(CONFIG_KVM_INTEL)
71+
#if IS_ENABLED(CONFIG_CPU_MITIGATIONS) && IS_ENABLED(CONFIG_KVM_INTEL)
7272
/*
7373
* This function is called from noinstr interrupt contexts
7474
* and must be inlined to not get instrumentation.

arch/x86/kvm/vmx/vmx.c

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ module_param(pt_mode, int, S_IRUGO);
203203

204204
struct x86_pmu_lbr __ro_after_init vmx_lbr_caps;
205205

206+
#ifdef CONFIG_CPU_MITIGATIONS
206207
static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
207208
static DEFINE_STATIC_KEY_FALSE(vmx_l1d_flush_cond);
208209
static DEFINE_MUTEX(vmx_l1d_flush_mutex);
@@ -225,7 +226,7 @@ static const struct {
225226
#define L1D_CACHE_ORDER 4
226227
static void *vmx_l1d_flush_pages;
227228

228-
static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
229+
static int __vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
229230
{
230231
struct page *page;
231232
unsigned int i;
@@ -302,6 +303,16 @@ static int vmx_setup_l1d_flush(enum vmx_l1d_flush_state l1tf)
302303
return 0;
303304
}
304305

306+
static int vmx_setup_l1d_flush(void)
307+
{
308+
/*
309+
* Hand the parameter mitigation value in which was stored in the pre
310+
* module init parser. If no parameter was given, it will contain
311+
* 'auto' which will be turned into the default 'cond' mitigation mode.
312+
*/
313+
return __vmx_setup_l1d_flush(vmentry_l1d_flush_param);
314+
}
315+
305316
static void vmx_cleanup_l1d_flush(void)
306317
{
307318
if (vmx_l1d_flush_pages) {
@@ -349,7 +360,7 @@ static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp)
349360
}
350361

351362
mutex_lock(&vmx_l1d_flush_mutex);
352-
ret = vmx_setup_l1d_flush(l1tf);
363+
ret = __vmx_setup_l1d_flush(l1tf);
353364
mutex_unlock(&vmx_l1d_flush_mutex);
354365
return ret;
355366
}
@@ -376,6 +387,9 @@ static noinstr void vmx_l1d_flush(struct kvm_vcpu *vcpu)
376387
{
377388
int size = PAGE_SIZE << L1D_CACHE_ORDER;
378389

390+
if (!static_branch_unlikely(&vmx_l1d_should_flush))
391+
return;
392+
379393
/*
380394
* This code is only executed when the flush mode is 'cond' or
381395
* 'always'
@@ -433,6 +447,31 @@ static noinstr void vmx_l1d_flush(struct kvm_vcpu *vcpu)
433447
: "eax", "ebx", "ecx", "edx");
434448
}
435449

450+
#else /* CONFIG_CPU_MITIGATIONS*/
451+
static int vmx_setup_l1d_flush(void)
452+
{
453+
l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_NEVER;
454+
return 0;
455+
}
456+
static void vmx_cleanup_l1d_flush(void)
457+
{
458+
l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO;
459+
}
460+
static __always_inline void vmx_l1d_flush(struct kvm_vcpu *vcpu)
461+
{
462+
463+
}
464+
static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp)
465+
{
466+
pr_warn_once("Kernel compiled without mitigations, ignoring vmentry_l1d_flush\n");
467+
return 0;
468+
}
469+
static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
470+
{
471+
return sysfs_emit(s, "never\n");
472+
}
473+
#endif
474+
436475
static const struct kernel_param_ops vmentry_l1d_flush_ops = {
437476
.set = vmentry_l1d_flush_set,
438477
.get = vmentry_l1d_flush_get,
@@ -7323,8 +7362,7 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
73237362

73247363
guest_state_enter_irqoff();
73257364

7326-
if (static_branch_unlikely(&vmx_l1d_should_flush))
7327-
vmx_l1d_flush(vcpu);
7365+
vmx_l1d_flush(vcpu);
73287366

73297367
vmx_disable_fb_clear(vmx);
73307368

@@ -8696,14 +8734,8 @@ int __init vmx_init(void)
86968734
if (r)
86978735
return r;
86988736

8699-
/*
8700-
* Must be called after common x86 init so enable_ept is properly set
8701-
* up. Hand the parameter mitigation value in which was stored in
8702-
* the pre module init parser. If no parameter was given, it will
8703-
* contain 'auto' which will be turned into the default 'cond'
8704-
* mitigation mode.
8705-
*/
8706-
r = vmx_setup_l1d_flush(vmentry_l1d_flush_param);
8737+
/* Must be called after common x86 init so enable_ept is setup. */
8738+
r = vmx_setup_l1d_flush();
87078739
if (r)
87088740
goto err_l1d_flush;
87098741

0 commit comments

Comments
 (0)