Skip to content

Commit a399477

Browse files
konradwilkKAGA-KOKO
authored andcommitted
x86/KVM/VMX: Add module argument for L1TF mitigation
Add a mitigation mode parameter "vmentry_l1d_flush" for CVE-2018-3620, aka L1 terminal fault. The valid arguments are: - "always" L1D cache flush on every VMENTER. - "cond" Conditional L1D cache flush, explained below - "never" Disable the L1D cache flush mitigation "cond" is trying to avoid L1D cache flushes on VMENTER if the code executed between VMEXIT and VMENTER is considered safe, i.e. is not bringing any interesting information into L1D which might exploited. [ tglx: Split out from a larger patch ] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
1 parent 26acfb6 commit a399477

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1973,6 +1973,18 @@
19731973
(virtualized real and unpaged mode) on capable
19741974
Intel chips. Default is 1 (enabled)
19751975

1976+
kvm-intel.vmentry_l1d_flush=[KVM,Intel] Mitigation for L1 Terminal Fault
1977+
CVE-2018-3620.
1978+
1979+
Valid arguments: never, cond, always
1980+
1981+
always: L1D cache flush on every VMENTER.
1982+
cond: Flush L1D on VMENTER only when the code between
1983+
VMEXIT and VMENTER can leak host memory.
1984+
never: Disables the mitigation
1985+
1986+
Default is cond (do L1 cache flush in specific instances)
1987+
19761988
kvm-intel.vpid= [KVM,Intel] Disable Virtual Processor Identification
19771989
feature (tagged TLBs) on capable Intel chips.
19781990
Default is 1 (enabled)

arch/x86/kvm/vmx.c

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,54 @@ module_param(ple_window_max, uint, 0444);
191191

192192
extern const ulong vmx_return;
193193

194+
static DEFINE_STATIC_KEY_FALSE(vmx_l1d_should_flush);
195+
196+
/* These MUST be in sync with vmentry_l1d_param order. */
197+
enum vmx_l1d_flush_state {
198+
VMENTER_L1D_FLUSH_NEVER,
199+
VMENTER_L1D_FLUSH_COND,
200+
VMENTER_L1D_FLUSH_ALWAYS,
201+
};
202+
203+
static enum vmx_l1d_flush_state __read_mostly vmentry_l1d_flush = VMENTER_L1D_FLUSH_COND;
204+
205+
static const struct {
206+
const char *option;
207+
enum vmx_l1d_flush_state cmd;
208+
} vmentry_l1d_param[] = {
209+
{"never", VMENTER_L1D_FLUSH_NEVER},
210+
{"cond", VMENTER_L1D_FLUSH_COND},
211+
{"always", VMENTER_L1D_FLUSH_ALWAYS},
212+
};
213+
214+
static int vmentry_l1d_flush_set(const char *s, const struct kernel_param *kp)
215+
{
216+
unsigned int i;
217+
218+
if (!s)
219+
return -EINVAL;
220+
221+
for (i = 0; i < ARRAY_SIZE(vmentry_l1d_param); i++) {
222+
if (!strcmp(s, vmentry_l1d_param[i].option)) {
223+
vmentry_l1d_flush = vmentry_l1d_param[i].cmd;
224+
return 0;
225+
}
226+
}
227+
228+
return -EINVAL;
229+
}
230+
231+
static int vmentry_l1d_flush_get(char *s, const struct kernel_param *kp)
232+
{
233+
return sprintf(s, "%s\n", vmentry_l1d_param[vmentry_l1d_flush].option);
234+
}
235+
236+
static const struct kernel_param_ops vmentry_l1d_flush_ops = {
237+
.set = vmentry_l1d_flush_set,
238+
.get = vmentry_l1d_flush_get,
239+
};
240+
module_param_cb(vmentry_l1d_flush, &vmentry_l1d_flush_ops, &vmentry_l1d_flush, S_IRUGO);
241+
194242
struct kvm_vmx {
195243
struct kvm kvm;
196244

@@ -13062,6 +13110,15 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
1306213110
.enable_smi_window = enable_smi_window,
1306313111
};
1306413112

13113+
static void __init vmx_setup_l1d_flush(void)
13114+
{
13115+
if (vmentry_l1d_flush == VMENTER_L1D_FLUSH_NEVER ||
13116+
!boot_cpu_has_bug(X86_BUG_L1TF))
13117+
return;
13118+
13119+
static_branch_enable(&vmx_l1d_should_flush);
13120+
}
13121+
1306513122
static int __init vmx_init(void)
1306613123
{
1306713124
int r;
@@ -13095,6 +13152,8 @@ static int __init vmx_init(void)
1309513152
}
1309613153
#endif
1309713154

13155+
vmx_setup_l1d_flush();
13156+
1309813157
r = kvm_init(&vmx_x86_ops, sizeof(struct vcpu_vmx),
1309913158
__alignof__(struct vcpu_vmx), THIS_MODULE);
1310013159
if (r)

0 commit comments

Comments
 (0)