xref: /netbsd-src/sys/arch/x86/x86/spectre.c (revision 76646d9e03c9615328f50b26f06c9b57e12e065b)
1 /*	$NetBSD: spectre.c,v 1.36 2021/10/07 12:52:27 msaitoh Exp $	*/
2 
3 /*
4  * Copyright (c) 2018-2019 NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Maxime Villard.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 /*
33  * Mitigations for the SpectreV2, SpectreV4, MDS and TAA CPU flaws.
34  */
35 
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: spectre.c,v 1.36 2021/10/07 12:52:27 msaitoh Exp $");
38 
39 #include "opt_spectre.h"
40 
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/cpu.h>
44 #include <sys/sysctl.h>
45 #include <sys/xcall.h>
46 
47 #include <machine/cpufunc.h>
48 #include <machine/cpuvar.h>
49 #include <machine/specialreg.h>
50 #include <machine/frameasm.h>
51 
52 #include <x86/cputypes.h>
53 
54 enum v2_mitigation {
55 	V2_MITIGATION_NONE,
56 	V2_MITIGATION_AMD_DIS_IND,
57 	V2_MITIGATION_INTEL_IBRS,
58 	V2_MITIGATION_INTEL_ENHANCED_IBRS
59 };
60 
61 enum v4_mitigation {
62 	V4_MITIGATION_NONE,
63 	V4_MITIGATION_INTEL_SSBD,
64 	V4_MITIGATION_INTEL_SSB_NO,
65 	V4_MITIGATION_AMD_SSB_NO,
66 	V4_MITIGATION_AMD_NONARCH_F15H,
67 	V4_MITIGATION_AMD_NONARCH_F16H,
68 	V4_MITIGATION_AMD_NONARCH_F17H
69 };
70 
71 static enum v2_mitigation v2_mitigation_method = V2_MITIGATION_NONE;
72 static enum v4_mitigation v4_mitigation_method = V4_MITIGATION_NONE;
73 
74 static bool v2_mitigation_enabled __read_mostly = false;
75 static bool v4_mitigation_enabled __read_mostly = false;
76 
77 static char v2_mitigation_name[64] = "(none)";
78 static char v4_mitigation_name[64] = "(none)";
79 
80 /* --------------------------------------------------------------------- */
81 
82 static void
v2_set_name(void)83 v2_set_name(void)
84 {
85 	char name[64] = "";
86 	size_t nmitig = 0;
87 
88 #if defined(SPECTRE_V2_GCC_MITIGATION)
89 	strlcat(name, "[GCC retpoline]", sizeof(name));
90 	nmitig++;
91 #endif
92 
93 	if (!v2_mitigation_enabled) {
94 		if (nmitig == 0)
95 			strlcat(name, "(none)", sizeof(name));
96 	} else {
97 		if (nmitig)
98 			strlcat(name, " + ", sizeof(name));
99 		switch (v2_mitigation_method) {
100 		case V2_MITIGATION_AMD_DIS_IND:
101 			strlcat(name, "[AMD DIS_IND]", sizeof(name));
102 			break;
103 		case V2_MITIGATION_INTEL_IBRS:
104 			strlcat(name, "[Intel IBRS]", sizeof(name));
105 			break;
106 		case V2_MITIGATION_INTEL_ENHANCED_IBRS:
107 			strlcat(name, "[Intel Enhanced IBRS]", sizeof(name));
108 			break;
109 		default:
110 			panic("%s: impossible", __func__);
111 		}
112 	}
113 
114 	strlcpy(v2_mitigation_name, name,
115 	    sizeof(v2_mitigation_name));
116 }
117 
118 static void
v2_detect_method(void)119 v2_detect_method(void)
120 {
121 	struct cpu_info *ci = curcpu();
122 	u_int descs[4];
123 	uint64_t msr;
124 
125 	if (cpu_vendor == CPUVENDOR_INTEL) {
126 		if (cpuid_level >= 7) {
127 			x86_cpuid(7, descs);
128 
129 			if (descs[3] & CPUID_SEF_IBRS) {
130 				if (descs[3] & CPUID_SEF_ARCH_CAP) {
131 					msr = rdmsr(MSR_IA32_ARCH_CAPABILITIES);
132 					if (msr & IA32_ARCH_IBRS_ALL) {
133 						v2_mitigation_method =
134 						    V2_MITIGATION_INTEL_ENHANCED_IBRS;
135 						return;
136 					}
137 				}
138 #ifdef __x86_64__
139 				v2_mitigation_method = V2_MITIGATION_INTEL_IBRS;
140 				return;
141 #endif
142 			}
143 		}
144 		v2_mitigation_method = V2_MITIGATION_NONE;
145 	} else if (cpu_vendor == CPUVENDOR_AMD) {
146 		/*
147 		 * The AMD Family 10h manual documents the IC_CFG.DIS_IND bit.
148 		 * This bit disables the Indirect Branch Predictor.
149 		 *
150 		 * Families 12h and 16h are believed to have this bit too, but
151 		 * their manuals don't document it.
152 		 */
153 		switch (CPUID_TO_FAMILY(ci->ci_signature)) {
154 		case 0x10:
155 			v2_mitigation_method = V2_MITIGATION_AMD_DIS_IND;
156 			break;
157 		default:
158 			v2_mitigation_method = V2_MITIGATION_NONE;
159 			break;
160 		}
161 	} else {
162 		v2_mitigation_method = V2_MITIGATION_NONE;
163 	}
164 }
165 
166 /* -------------------------------------------------------------------------- */
167 
168 static volatile unsigned long ibrs_cpu_barrier1 __cacheline_aligned;
169 static volatile unsigned long ibrs_cpu_barrier2 __cacheline_aligned;
170 
171 #ifdef __x86_64__
172 /* IBRS_ENTER. */
173 extern uint8_t noibrs_enter, noibrs_enter_end;
174 extern uint8_t ibrs_enter, ibrs_enter_end;
175 static const struct x86_hotpatch_source hp_noibrs_enter_source = {
176 	.saddr = &noibrs_enter,
177 	.eaddr = &noibrs_enter_end
178 };
179 static const struct x86_hotpatch_source hp_ibrs_enter_source = {
180 	.saddr = &ibrs_enter,
181 	.eaddr = &ibrs_enter_end
182 };
183 static const struct x86_hotpatch_descriptor hp_ibrs_enter_desc = {
184 	.name = HP_NAME_IBRS_ENTER,
185 	.nsrc = 2,
186 	.srcs = { &hp_noibrs_enter_source, &hp_ibrs_enter_source }
187 };
188 __link_set_add_rodata(x86_hotpatch_descriptors, hp_ibrs_enter_desc);
189 
190 /* IBRS_LEAVE. */
191 extern uint8_t noibrs_leave, noibrs_leave_end;
192 extern uint8_t ibrs_leave, ibrs_leave_end;
193 static const struct x86_hotpatch_source hp_noibrs_leave_source = {
194 	.saddr = &noibrs_leave,
195 	.eaddr = &noibrs_leave_end
196 };
197 static const struct x86_hotpatch_source hp_ibrs_leave_source = {
198 	.saddr = &ibrs_leave,
199 	.eaddr = &ibrs_leave_end
200 };
201 static const struct x86_hotpatch_descriptor hp_ibrs_leave_desc = {
202 	.name = HP_NAME_IBRS_LEAVE,
203 	.nsrc = 2,
204 	.srcs = { &hp_noibrs_leave_source, &hp_ibrs_leave_source }
205 };
206 __link_set_add_rodata(x86_hotpatch_descriptors, hp_ibrs_leave_desc);
207 
208 static void
ibrs_disable_hotpatch(void)209 ibrs_disable_hotpatch(void)
210 {
211 	x86_hotpatch(HP_NAME_IBRS_ENTER, /* noibrs */ 0);
212 	x86_hotpatch(HP_NAME_IBRS_LEAVE, /* noibrs */ 0);
213 }
214 
215 static void
ibrs_enable_hotpatch(void)216 ibrs_enable_hotpatch(void)
217 {
218 	x86_hotpatch(HP_NAME_IBRS_ENTER, /* ibrs */ 1);
219 	x86_hotpatch(HP_NAME_IBRS_LEAVE, /* ibrs */ 1);
220 }
221 #else
222 /* IBRS not supported on i386 */
223 static void
ibrs_disable_hotpatch(void)224 ibrs_disable_hotpatch(void)
225 {
226 	panic("%s: impossible", __func__);
227 }
228 static void
ibrs_enable_hotpatch(void)229 ibrs_enable_hotpatch(void)
230 {
231 	panic("%s: impossible", __func__);
232 }
233 #endif
234 
235 /* -------------------------------------------------------------------------- */
236 
237 static void
mitigation_v2_apply_cpu(struct cpu_info * ci,bool enabled)238 mitigation_v2_apply_cpu(struct cpu_info *ci, bool enabled)
239 {
240 	uint64_t msr;
241 
242 	switch (v2_mitigation_method) {
243 	case V2_MITIGATION_NONE:
244 		panic("impossible");
245 	case V2_MITIGATION_INTEL_IBRS:
246 		/* cpu0 is the one that does the hotpatch job */
247 		if (ci == &cpu_info_primary) {
248 			if (enabled) {
249 				ibrs_enable_hotpatch();
250 			} else {
251 				ibrs_disable_hotpatch();
252 			}
253 		}
254 		if (!enabled) {
255 			wrmsr(MSR_IA32_SPEC_CTRL, 0);
256 		}
257 		break;
258 	case V2_MITIGATION_INTEL_ENHANCED_IBRS:
259 		msr = rdmsr(MSR_IA32_SPEC_CTRL);
260 		if (enabled) {
261 			msr |= IA32_SPEC_CTRL_IBRS;
262 		} else {
263 			msr &= ~IA32_SPEC_CTRL_IBRS;
264 		}
265 		wrmsr(MSR_IA32_SPEC_CTRL, msr);
266 		break;
267 	case V2_MITIGATION_AMD_DIS_IND:
268 		msr = rdmsr(MSR_IC_CFG);
269 		if (enabled) {
270 			msr |= IC_CFG_DIS_IND;
271 		} else {
272 			msr &= ~IC_CFG_DIS_IND;
273 		}
274 		wrmsr(MSR_IC_CFG, msr);
275 		break;
276 	}
277 }
278 
279 /*
280  * Note: IBRS requires hotpatching, so we need barriers.
281  */
282 static void
mitigation_v2_change_cpu(void * arg1,void * arg2)283 mitigation_v2_change_cpu(void *arg1, void *arg2)
284 {
285 	struct cpu_info *ci = curcpu();
286 	bool enabled = arg1 != NULL;
287 	u_long psl = 0;
288 
289 	/* Rendez-vous 1 (IBRS only). */
290 	if (v2_mitigation_method == V2_MITIGATION_INTEL_IBRS) {
291 		psl = x86_read_psl();
292 		x86_disable_intr();
293 
294 		atomic_dec_ulong(&ibrs_cpu_barrier1);
295 		while (atomic_cas_ulong(&ibrs_cpu_barrier1, 0, 0) != 0) {
296 			x86_pause();
297 		}
298 	}
299 
300 	mitigation_v2_apply_cpu(ci, enabled);
301 
302 	/* Rendez-vous 2 (IBRS only). */
303 	if (v2_mitigation_method == V2_MITIGATION_INTEL_IBRS) {
304 		atomic_dec_ulong(&ibrs_cpu_barrier2);
305 		while (atomic_cas_ulong(&ibrs_cpu_barrier2, 0, 0) != 0) {
306 			x86_pause();
307 		}
308 
309 		/* Write back and invalidate cache, flush pipelines. */
310 		wbinvd();
311 		x86_flush();
312 
313 		x86_write_psl(psl);
314 	}
315 }
316 
317 static int
mitigation_v2_change(bool enabled)318 mitigation_v2_change(bool enabled)
319 {
320 	uint64_t xc;
321 
322 	v2_detect_method();
323 
324 	switch (v2_mitigation_method) {
325 	case V2_MITIGATION_NONE:
326 		printf("[!] No mitigation available\n");
327 		return EOPNOTSUPP;
328 	case V2_MITIGATION_AMD_DIS_IND:
329 	case V2_MITIGATION_INTEL_IBRS:
330 	case V2_MITIGATION_INTEL_ENHANCED_IBRS:
331 		/* Initialize the barriers */
332 		ibrs_cpu_barrier1 = ncpu;
333 		ibrs_cpu_barrier2 = ncpu;
334 
335 		printf("[+] %s SpectreV2 Mitigation...",
336 		    enabled ? "Enabling" : "Disabling");
337 		xc = xc_broadcast(XC_HIGHPRI, mitigation_v2_change_cpu,
338 		    (void *)enabled, NULL);
339 		xc_wait(xc);
340 		printf(" done!\n");
341 		v2_mitigation_enabled = enabled;
342 		v2_set_name();
343 		return 0;
344 	default:
345 		panic("impossible");
346 	}
347 }
348 
349 static int
sysctl_machdep_spectreV2_mitigated(SYSCTLFN_ARGS)350 sysctl_machdep_spectreV2_mitigated(SYSCTLFN_ARGS)
351 {
352 	struct sysctlnode node;
353 	int error;
354 	bool val;
355 
356 	val = *(bool *)rnode->sysctl_data;
357 
358 	node = *rnode;
359 	node.sysctl_data = &val;
360 
361 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
362 	if (error != 0 || newp == NULL)
363 		return error;
364 
365 	if (val == v2_mitigation_enabled)
366 		return 0;
367 	return mitigation_v2_change(val);
368 }
369 
370 /* -------------------------------------------------------------------------- */
371 
372 static void
v4_set_name(void)373 v4_set_name(void)
374 {
375 	char name[64] = "";
376 
377 	if (!v4_mitigation_enabled) {
378 		strlcat(name, "(none)", sizeof(name));
379 	} else {
380 		switch (v4_mitigation_method) {
381 		case V4_MITIGATION_NONE:
382 			panic("%s: impossible", __func__);
383 		case V4_MITIGATION_INTEL_SSBD:
384 			strlcat(name, "[Intel SSBD]", sizeof(name));
385 			break;
386 		case V4_MITIGATION_INTEL_SSB_NO:
387 			strlcat(name, "[Intel SSB_NO]", sizeof(name));
388 			break;
389 		case V4_MITIGATION_AMD_SSB_NO:
390 			strlcat(name, "[AMD SSB_NO]", sizeof(name));
391 			break;
392 		case V4_MITIGATION_AMD_NONARCH_F15H:
393 		case V4_MITIGATION_AMD_NONARCH_F16H:
394 		case V4_MITIGATION_AMD_NONARCH_F17H:
395 			strlcat(name, "[AMD NONARCH]", sizeof(name));
396 			break;
397 		}
398 	}
399 
400 	strlcpy(v4_mitigation_name, name,
401 	    sizeof(v4_mitigation_name));
402 }
403 
404 static void
v4_detect_method(void)405 v4_detect_method(void)
406 {
407 	struct cpu_info *ci = curcpu();
408 	u_int descs[4];
409 	uint64_t msr;
410 
411 	if (cpu_vendor == CPUVENDOR_INTEL) {
412 		if (cpu_info_primary.ci_feat_val[7] & CPUID_SEF_ARCH_CAP) {
413 			msr = rdmsr(MSR_IA32_ARCH_CAPABILITIES);
414 			if (msr & IA32_ARCH_SSB_NO) {
415 				/* Not vulnerable to SpectreV4. */
416 				v4_mitigation_method = V4_MITIGATION_INTEL_SSB_NO;
417 				return;
418 			}
419 		}
420 		if (cpuid_level >= 7) {
421 			x86_cpuid(7, descs);
422 			if (descs[3] & CPUID_SEF_SSBD) {
423 				/* descs[3] = %edx */
424 				v4_mitigation_method = V4_MITIGATION_INTEL_SSBD;
425 				return;
426 			}
427 		}
428 	} else if (cpu_vendor == CPUVENDOR_AMD) {
429 		switch (CPUID_TO_FAMILY(ci->ci_signature)) {
430 		case 0x15:
431 			v4_mitigation_method = V4_MITIGATION_AMD_NONARCH_F15H;
432 			return;
433 		case 0x16:
434 			v4_mitigation_method = V4_MITIGATION_AMD_NONARCH_F16H;
435 			return;
436 		case 0x17:
437 			v4_mitigation_method = V4_MITIGATION_AMD_NONARCH_F17H;
438 			return;
439 		default:
440 			if (cpu_info_primary.ci_max_ext_cpuid < 0x80000008) {
441 				break;
442 			}
443 			x86_cpuid(0x80000008, descs);
444 			if (descs[1] & CPUID_CAPEX_SSB_NO) {
445 				/* Not vulnerable to SpectreV4. */
446 				v4_mitigation_method = V4_MITIGATION_AMD_SSB_NO;
447 				return;
448 			}
449 
450 			break;
451 		}
452 	}
453 
454 	v4_mitigation_method = V4_MITIGATION_NONE;
455 }
456 
457 static void
mitigation_v4_apply_cpu(bool enabled)458 mitigation_v4_apply_cpu(bool enabled)
459 {
460 	uint64_t msr, msrval = 0, msrbit = 0;
461 
462 	switch (v4_mitigation_method) {
463 	case V4_MITIGATION_NONE:
464 	case V4_MITIGATION_INTEL_SSB_NO:
465 	case V4_MITIGATION_AMD_SSB_NO:
466 		panic("impossible");
467 	case V4_MITIGATION_INTEL_SSBD:
468 		msrval = MSR_IA32_SPEC_CTRL;
469 		msrbit = IA32_SPEC_CTRL_SSBD;
470 		break;
471 	case V4_MITIGATION_AMD_NONARCH_F15H:
472 		msrval = MSR_LS_CFG;
473 		msrbit = LS_CFG_DIS_SSB_F15H;
474 		break;
475 	case V4_MITIGATION_AMD_NONARCH_F16H:
476 		msrval = MSR_LS_CFG;
477 		msrbit = LS_CFG_DIS_SSB_F16H;
478 		break;
479 	case V4_MITIGATION_AMD_NONARCH_F17H:
480 		msrval = MSR_LS_CFG;
481 		msrbit = LS_CFG_DIS_SSB_F17H;
482 		break;
483 	}
484 
485 	msr = rdmsr(msrval);
486 	if (enabled) {
487 		msr |= msrbit;
488 	} else {
489 		msr &= ~msrbit;
490 	}
491 	wrmsr(msrval, msr);
492 }
493 
494 static void
mitigation_v4_change_cpu(void * arg1,void * arg2)495 mitigation_v4_change_cpu(void *arg1, void *arg2)
496 {
497 	bool enabled = arg1 != NULL;
498 
499 	mitigation_v4_apply_cpu(enabled);
500 }
501 
502 static int
mitigation_v4_change(bool enabled)503 mitigation_v4_change(bool enabled)
504 {
505 	uint64_t xc;
506 
507 	v4_detect_method();
508 
509 	switch (v4_mitigation_method) {
510 	case V4_MITIGATION_NONE:
511 		printf("[!] No mitigation available\n");
512 		return EOPNOTSUPP;
513 	case V4_MITIGATION_INTEL_SSBD:
514 	case V4_MITIGATION_AMD_NONARCH_F15H:
515 	case V4_MITIGATION_AMD_NONARCH_F16H:
516 	case V4_MITIGATION_AMD_NONARCH_F17H:
517 		printf("[+] %s SpectreV4 Mitigation...",
518 		    enabled ? "Enabling" : "Disabling");
519 		xc = xc_broadcast(0, mitigation_v4_change_cpu,
520 		    (void *)enabled, NULL);
521 		xc_wait(xc);
522 		printf(" done!\n");
523 		v4_mitigation_enabled = enabled;
524 		v4_set_name();
525 		return 0;
526 	case V4_MITIGATION_INTEL_SSB_NO:
527 	case V4_MITIGATION_AMD_SSB_NO:
528 		printf("[+] The CPU is not affected by SpectreV4\n");
529 		return 0;
530 	default:
531 		panic("impossible");
532 	}
533 }
534 
535 static int
sysctl_machdep_spectreV4_mitigated(SYSCTLFN_ARGS)536 sysctl_machdep_spectreV4_mitigated(SYSCTLFN_ARGS)
537 {
538 	struct sysctlnode node;
539 	int error;
540 	bool val;
541 
542 	val = *(bool *)rnode->sysctl_data;
543 
544 	node = *rnode;
545 	node.sysctl_data = &val;
546 
547 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
548 	if (error != 0 || newp == NULL)
549 		return error;
550 
551 	if (val == v4_mitigation_enabled)
552 		return 0;
553 	return mitigation_v4_change(val);
554 }
555 
556 /* -------------------------------------------------------------------------- */
557 
558 enum mds_mitigation {
559 	MDS_MITIGATION_NONE,
560 	MDS_MITIGATION_VERW,
561 	MDS_MITIGATION_MDS_NO
562 };
563 
564 static char mds_mitigation_name[64] = "(none)";
565 
566 static enum mds_mitigation mds_mitigation_method = MDS_MITIGATION_NONE;
567 static bool mds_mitigation_enabled __read_mostly = false;
568 
569 static volatile unsigned long mds_cpu_barrier1 __cacheline_aligned;
570 static volatile unsigned long mds_cpu_barrier2 __cacheline_aligned;
571 
572 #ifdef __x86_64__
573 /* MDS_LEAVE. */
574 extern uint8_t nomds_leave, nomds_leave_end;
575 extern uint8_t mds_leave, mds_leave_end;
576 static const struct x86_hotpatch_source hp_nomds_leave_source = {
577 	.saddr = &nomds_leave,
578 	.eaddr = &nomds_leave_end
579 };
580 static const struct x86_hotpatch_source hp_mds_leave_source = {
581 	.saddr = &mds_leave,
582 	.eaddr = &mds_leave_end
583 };
584 static const struct x86_hotpatch_descriptor hp_mds_leave_desc = {
585 	.name = HP_NAME_MDS_LEAVE,
586 	.nsrc = 2,
587 	.srcs = { &hp_nomds_leave_source, &hp_mds_leave_source }
588 };
589 __link_set_add_rodata(x86_hotpatch_descriptors, hp_mds_leave_desc);
590 
591 static void
mds_disable_hotpatch(void)592 mds_disable_hotpatch(void)
593 {
594 	x86_hotpatch(HP_NAME_MDS_LEAVE, /* nomds */ 0);
595 }
596 
597 static void
mds_enable_hotpatch(void)598 mds_enable_hotpatch(void)
599 {
600 	x86_hotpatch(HP_NAME_MDS_LEAVE, /* mds */ 1);
601 }
602 #else
603 /* MDS not supported on i386 */
604 static void
mds_disable_hotpatch(void)605 mds_disable_hotpatch(void)
606 {
607 	panic("%s: impossible", __func__);
608 }
609 static void
mds_enable_hotpatch(void)610 mds_enable_hotpatch(void)
611 {
612 	panic("%s: impossible", __func__);
613 }
614 #endif
615 
616 static void
mitigation_mds_apply_cpu(struct cpu_info * ci,bool enabled)617 mitigation_mds_apply_cpu(struct cpu_info *ci, bool enabled)
618 {
619 	switch (mds_mitigation_method) {
620 	case MDS_MITIGATION_NONE:
621 	case MDS_MITIGATION_MDS_NO:
622 		panic("impossible");
623 	case MDS_MITIGATION_VERW:
624 		/* cpu0 is the one that does the hotpatch job */
625 		if (ci == &cpu_info_primary) {
626 			if (enabled) {
627 				mds_enable_hotpatch();
628 			} else {
629 				mds_disable_hotpatch();
630 			}
631 		}
632 		break;
633 	}
634 }
635 
636 static void
mitigation_mds_change_cpu(void * arg1,void * arg2)637 mitigation_mds_change_cpu(void *arg1, void *arg2)
638 {
639 	struct cpu_info *ci = curcpu();
640 	bool enabled = arg1 != NULL;
641 	u_long psl = 0;
642 
643 	/* Rendez-vous 1. */
644 	psl = x86_read_psl();
645 	x86_disable_intr();
646 
647 	atomic_dec_ulong(&mds_cpu_barrier1);
648 	while (atomic_cas_ulong(&mds_cpu_barrier1, 0, 0) != 0) {
649 		x86_pause();
650 	}
651 
652 	mitigation_mds_apply_cpu(ci, enabled);
653 
654 	/* Rendez-vous 2. */
655 	atomic_dec_ulong(&mds_cpu_barrier2);
656 	while (atomic_cas_ulong(&mds_cpu_barrier2, 0, 0) != 0) {
657 		x86_pause();
658 	}
659 
660 	/* Write back and invalidate cache, flush pipelines. */
661 	wbinvd();
662 	x86_flush();
663 
664 	x86_write_psl(psl);
665 }
666 
667 static void
mds_detect_method(void)668 mds_detect_method(void)
669 {
670 	u_int descs[4];
671 	uint64_t msr;
672 
673 	if (cpu_vendor != CPUVENDOR_INTEL) {
674 		mds_mitigation_method = MDS_MITIGATION_MDS_NO;
675 		return;
676 	}
677 
678 	if (cpuid_level < 7) {
679 		return;
680 	}
681 
682 	x86_cpuid(0x7, descs);
683 	if (descs[3] & CPUID_SEF_ARCH_CAP) {
684 		msr = rdmsr(MSR_IA32_ARCH_CAPABILITIES);
685 		if (msr & IA32_ARCH_MDS_NO) {
686 			mds_mitigation_method = MDS_MITIGATION_MDS_NO;
687 			return;
688 		}
689 	}
690 
691 #ifdef __x86_64__
692 	if (descs[3] & CPUID_SEF_MD_CLEAR) {
693 		mds_mitigation_method = MDS_MITIGATION_VERW;
694 	}
695 #endif
696 }
697 
698 static void
mds_set_name(void)699 mds_set_name(void)
700 {
701 	char name[64] = "";
702 
703 	if (!mds_mitigation_enabled) {
704 		strlcat(name, "(none)", sizeof(name));
705 	} else {
706 		switch (mds_mitigation_method) {
707 		case MDS_MITIGATION_NONE:
708 			panic("%s: impossible", __func__);
709 		case MDS_MITIGATION_MDS_NO:
710 			strlcat(name, "[MDS_NO]", sizeof(name));
711 			break;
712 		case MDS_MITIGATION_VERW:
713 			strlcat(name, "[VERW]", sizeof(name));
714 			break;
715 		}
716 	}
717 
718 	strlcpy(mds_mitigation_name, name,
719 	    sizeof(mds_mitigation_name));
720 }
721 
722 static int
mitigation_mds_change(bool enabled)723 mitigation_mds_change(bool enabled)
724 {
725 	uint64_t xc;
726 
727 	mds_detect_method();
728 
729 	switch (mds_mitigation_method) {
730 	case MDS_MITIGATION_NONE:
731 		printf("[!] No mitigation available\n");
732 		return EOPNOTSUPP;
733 	case MDS_MITIGATION_VERW:
734 		/* Initialize the barriers */
735 		mds_cpu_barrier1 = ncpu;
736 		mds_cpu_barrier2 = ncpu;
737 
738 		printf("[+] %s MDS Mitigation...",
739 		    enabled ? "Enabling" : "Disabling");
740 		xc = xc_broadcast(XC_HIGHPRI, mitigation_mds_change_cpu,
741 		    (void *)enabled, NULL);
742 		xc_wait(xc);
743 		printf(" done!\n");
744 		mds_mitigation_enabled = enabled;
745 		mds_set_name();
746 		return 0;
747 	case MDS_MITIGATION_MDS_NO:
748 		printf("[+] The CPU is not affected by MDS\n");
749 		return 0;
750 	default:
751 		panic("impossible");
752 	}
753 }
754 
755 static int
sysctl_machdep_mds_mitigated(SYSCTLFN_ARGS)756 sysctl_machdep_mds_mitigated(SYSCTLFN_ARGS)
757 {
758 	struct sysctlnode node;
759 	int error;
760 	bool val;
761 
762 	val = *(bool *)rnode->sysctl_data;
763 
764 	node = *rnode;
765 	node.sysctl_data = &val;
766 
767 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
768 	if (error != 0 || newp == NULL)
769 		return error;
770 
771 	if (val == mds_mitigation_enabled)
772 		return 0;
773 	return mitigation_mds_change(val);
774 }
775 
776 /* -------------------------------------------------------------------------- */
777 
778 enum taa_mitigation {
779 	TAA_MITIGATION_NONE,
780 	TAA_MITIGATION_TAA_NO,
781 	TAA_MITIGATION_MDS,
782 	TAA_MITIGATION_RTM_DISABLE
783 };
784 
785 static char taa_mitigation_name[64] = "(none)";
786 
787 static enum taa_mitigation taa_mitigation_method = TAA_MITIGATION_NONE;
788 static bool taa_mitigation_enabled __read_mostly = false;
789 static bool *taa_mitigation_enabled_ptr = &taa_mitigation_enabled;
790 
791 static void
mitigation_taa_apply_cpu(struct cpu_info * ci,bool enabled)792 mitigation_taa_apply_cpu(struct cpu_info *ci, bool enabled)
793 {
794 	uint64_t msr;
795 
796 	switch (taa_mitigation_method) {
797 	case TAA_MITIGATION_NONE:
798 	case TAA_MITIGATION_TAA_NO:
799 	case TAA_MITIGATION_MDS:
800 		panic("impossible");
801 	case TAA_MITIGATION_RTM_DISABLE:
802 		msr = rdmsr(MSR_IA32_TSX_CTRL);
803 		if (enabled) {
804 			msr |= IA32_TSX_CTRL_RTM_DISABLE;
805 		} else {
806 			msr &= ~IA32_TSX_CTRL_RTM_DISABLE;
807 		}
808 		wrmsr(MSR_IA32_TSX_CTRL, msr);
809 		break;
810 	}
811 }
812 
813 static void
mitigation_taa_change_cpu(void * arg1,void * arg2)814 mitigation_taa_change_cpu(void *arg1, void *arg2)
815 {
816 	struct cpu_info *ci = curcpu();
817 	bool enabled = arg1 != NULL;
818 
819 	mitigation_taa_apply_cpu(ci, enabled);
820 }
821 
822 static void
taa_detect_method(void)823 taa_detect_method(void)
824 {
825 	u_int descs[4];
826 	uint64_t msr;
827 
828 	taa_mitigation_enabled_ptr = &taa_mitigation_enabled;
829 
830 	if (cpu_vendor != CPUVENDOR_INTEL) {
831 		taa_mitigation_method = TAA_MITIGATION_TAA_NO;
832 		return;
833 	}
834 	if (!(cpu_feature[5] & CPUID_SEF_RTM)) {
835 		taa_mitigation_method = TAA_MITIGATION_TAA_NO;
836 		return;
837 	}
838 
839 	/*
840 	 * If the CPU doesn't have MDS_NO set, then the TAA mitigation is based
841 	 * on the MDS mitigation.
842 	 */
843 	if (cpuid_level < 7) {
844 		taa_mitigation_method = TAA_MITIGATION_MDS;
845 		taa_mitigation_enabled_ptr = &mds_mitigation_enabled;
846 		return;
847 	}
848 	x86_cpuid(0x7, descs);
849 	if (!(descs[3] & CPUID_SEF_ARCH_CAP)) {
850 		taa_mitigation_method = TAA_MITIGATION_MDS;
851 		taa_mitigation_enabled_ptr = &mds_mitigation_enabled;
852 		return;
853 	}
854 	msr = rdmsr(MSR_IA32_ARCH_CAPABILITIES);
855 	if (!(msr & IA32_ARCH_MDS_NO)) {
856 		taa_mitigation_method = TAA_MITIGATION_MDS;
857 		taa_mitigation_enabled_ptr = &mds_mitigation_enabled;
858 		return;
859 	}
860 
861 	/*
862 	 * Otherwise, we need the TAA-specific mitigation.
863 	 */
864 	if (msr & IA32_ARCH_TAA_NO) {
865 		taa_mitigation_method = TAA_MITIGATION_TAA_NO;
866 		return;
867 	}
868 	if (msr & IA32_ARCH_TSX_CTRL) {
869 		taa_mitigation_method = TAA_MITIGATION_RTM_DISABLE;
870 		return;
871 	}
872 }
873 
874 static void
taa_set_name(void)875 taa_set_name(void)
876 {
877 	char name[64] = "";
878 
879 	switch (taa_mitigation_method) {
880 	case TAA_MITIGATION_NONE:
881 		strlcpy(name, "(none)", sizeof(name));
882 		break;
883 	case TAA_MITIGATION_TAA_NO:
884 		strlcpy(name, "[TAA_NO]", sizeof(name));
885 		break;
886 	case TAA_MITIGATION_MDS:
887 		strlcpy(name, "[MDS]", sizeof(name));
888 		break;
889 	case TAA_MITIGATION_RTM_DISABLE:
890 		if (!taa_mitigation_enabled) {
891 			strlcpy(name, "(none)", sizeof(name));
892 		} else {
893 			strlcpy(name, "[RTM_DISABLE]", sizeof(name));
894 		}
895 		break;
896 	}
897 
898 	strlcpy(taa_mitigation_name, name, sizeof(taa_mitigation_name));
899 }
900 
901 static int
mitigation_taa_change(bool enabled)902 mitigation_taa_change(bool enabled)
903 {
904 	uint64_t xc;
905 
906 	taa_detect_method();
907 
908 	switch (taa_mitigation_method) {
909 	case TAA_MITIGATION_NONE:
910 		printf("[!] No mitigation available\n");
911 		return EOPNOTSUPP;
912 	case TAA_MITIGATION_TAA_NO:
913 		printf("[+] The CPU is not affected by TAA\n");
914 		return 0;
915 	case TAA_MITIGATION_MDS:
916 		printf("[!] Mitigation based on MDS, use machdep.mds\n");
917 		taa_set_name();
918 		return EINVAL;
919 	case TAA_MITIGATION_RTM_DISABLE:
920 		printf("[+] %s TAA Mitigation...",
921 		    enabled ? "Enabling" : "Disabling");
922 		xc = xc_broadcast(XC_HIGHPRI, mitigation_taa_change_cpu,
923 		    (void *)enabled, NULL);
924 		xc_wait(xc);
925 		printf(" done!\n");
926 		taa_mitigation_enabled = enabled;
927 		taa_set_name();
928 		return 0;
929 	default:
930 		panic("impossible");
931 	}
932 }
933 
934 static int
sysctl_machdep_taa_mitigated(SYSCTLFN_ARGS)935 sysctl_machdep_taa_mitigated(SYSCTLFN_ARGS)
936 {
937 	struct sysctlnode node;
938 	int error;
939 	bool val;
940 
941 	val = *(bool *)rnode->sysctl_data;
942 
943 	node = *rnode;
944 	node.sysctl_data = &val;
945 
946 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
947 	if (error != 0 || newp == NULL)
948 		return error;
949 
950 	if (val == *taa_mitigation_enabled_ptr)
951 		return 0;
952 	return mitigation_taa_change(val);
953 }
954 
955 /* -------------------------------------------------------------------------- */
956 
957 void speculation_barrier(struct lwp *, struct lwp *);
958 
959 void
speculation_barrier(struct lwp * oldlwp,struct lwp * newlwp)960 speculation_barrier(struct lwp *oldlwp, struct lwp *newlwp)
961 {
962 	/*
963 	 * Speculation barriers are applicable only to Spectre V2.
964 	 */
965 	if (!v2_mitigation_enabled)
966 		return;
967 
968 	/*
969 	 * From kernel thread to kernel thread, no need for a barrier.
970 	 */
971 	if ((oldlwp->l_flag & LW_SYSTEM) && (newlwp->l_flag & LW_SYSTEM))
972 		return;
973 
974 	switch (v2_mitigation_method) {
975 	case V2_MITIGATION_INTEL_IBRS:
976 		wrmsr(MSR_IA32_PRED_CMD, IA32_PRED_CMD_IBPB);
977 		break;
978 	default:
979 		/* nothing */
980 		break;
981 	}
982 }
983 
984 /*
985  * cpu0 is the one that detects the method and sets the global 'enabled'
986  * variable for each mitigation.
987  */
988 void
cpu_speculation_init(struct cpu_info * ci)989 cpu_speculation_init(struct cpu_info *ci)
990 {
991 	/*
992 	 * Spectre V2.
993 	 */
994 	if (ci == &cpu_info_primary) {
995 		v2_detect_method();
996 		v2_mitigation_enabled =
997 		    (v2_mitigation_method != V2_MITIGATION_NONE);
998 		v2_set_name();
999 	}
1000 	if (v2_mitigation_method != V2_MITIGATION_NONE) {
1001 		mitigation_v2_apply_cpu(ci, true);
1002 	}
1003 
1004 	/*
1005 	 * Spectre V4.
1006 	 *
1007 	 * Disabled by default, as recommended by AMD, but can be enabled
1008 	 * dynamically. We only detect if the CPU is not vulnerable, to
1009 	 * mark it as 'mitigated' in the sysctl.
1010 	 */
1011 #if 0
1012 	if (ci == &cpu_info_primary) {
1013 		v4_detect_method();
1014 		v4_mitigation_enabled =
1015 		    (v4_mitigation_method != V4_MITIGATION_NONE);
1016 		v4_set_name();
1017 	}
1018 	if (v4_mitigation_method != V4_MITIGATION_NONE &&
1019 	    v4_mitigation_method != V4_MITIGATION_INTEL_SSB_NO &&
1020 	    v4_mitigation_method != V4_MITIGATION_AMD_SSB_NO) {
1021 		mitigation_v4_apply_cpu(ci, true);
1022 	}
1023 #else
1024 	if (ci == &cpu_info_primary) {
1025 		v4_detect_method();
1026 		if (v4_mitigation_method == V4_MITIGATION_INTEL_SSB_NO ||
1027 		    v4_mitigation_method == V4_MITIGATION_AMD_SSB_NO) {
1028 			v4_mitigation_enabled = true;
1029 			v4_set_name();
1030 		}
1031 	}
1032 #endif
1033 
1034 	/*
1035 	 * Microarchitectural Data Sampling.
1036 	 */
1037 	if (ci == &cpu_info_primary) {
1038 		mds_detect_method();
1039 		mds_mitigation_enabled =
1040 		    (mds_mitigation_method != MDS_MITIGATION_NONE);
1041 		mds_set_name();
1042 	}
1043 	if (mds_mitigation_method != MDS_MITIGATION_NONE &&
1044 	    mds_mitigation_method != MDS_MITIGATION_MDS_NO) {
1045 		mitigation_mds_apply_cpu(ci, true);
1046 	}
1047 
1048 	/*
1049 	 * TSX Asynchronous Abort.
1050 	 */
1051 	if (ci == &cpu_info_primary) {
1052 		taa_detect_method();
1053 		taa_mitigation_enabled =
1054 		    (taa_mitigation_method == TAA_MITIGATION_RTM_DISABLE) ||
1055 		    (taa_mitigation_method == TAA_MITIGATION_TAA_NO);
1056 		taa_set_name();
1057 	}
1058 	if (taa_mitigation_method == TAA_MITIGATION_RTM_DISABLE) {
1059 		mitigation_taa_apply_cpu(ci, true);
1060 	}
1061 }
1062 
1063 void sysctl_speculation_init(struct sysctllog **);
1064 
1065 void
sysctl_speculation_init(struct sysctllog ** clog)1066 sysctl_speculation_init(struct sysctllog **clog)
1067 {
1068 	const struct sysctlnode *spec_rnode;
1069 
1070 	/* SpectreV1 */
1071 	spec_rnode = NULL;
1072 	sysctl_createv(clog, 0, NULL, &spec_rnode,
1073 		       CTLFLAG_PERMANENT,
1074 		       CTLTYPE_NODE, "spectre_v1", NULL,
1075 		       NULL, 0, NULL, 0,
1076 		       CTL_MACHDEP, CTL_CREATE);
1077 	sysctl_createv(clog, 0, &spec_rnode, &spec_rnode,
1078 		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
1079 		       CTLTYPE_BOOL, "mitigated",
1080 		       SYSCTL_DESCR("Whether Spectre Variant 1 is mitigated"),
1081 		       NULL, 0 /* mitigated=0 */, NULL, 0,
1082 		       CTL_CREATE, CTL_EOL);
1083 
1084 	/* SpectreV2 */
1085 	spec_rnode = NULL;
1086 	sysctl_createv(clog, 0, NULL, &spec_rnode,
1087 		       CTLFLAG_PERMANENT,
1088 		       CTLTYPE_NODE, "spectre_v2", NULL,
1089 		       NULL, 0, NULL, 0,
1090 		       CTL_MACHDEP, CTL_CREATE);
1091 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1092 		       CTLFLAG_READWRITE,
1093 		       CTLTYPE_BOOL, "hwmitigated",
1094 		       SYSCTL_DESCR("Whether Spectre Variant 2 is HW-mitigated"),
1095 		       sysctl_machdep_spectreV2_mitigated, 0,
1096 		       &v2_mitigation_enabled, 0,
1097 		       CTL_CREATE, CTL_EOL);
1098 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1099 		       CTLFLAG_PERMANENT | CTLFLAG_IMMEDIATE,
1100 		       CTLTYPE_BOOL, "swmitigated",
1101 		       SYSCTL_DESCR("Whether Spectre Variant 2 is SW-mitigated"),
1102 #if defined(SPECTRE_V2_GCC_MITIGATION)
1103 		       NULL, 1,
1104 #else
1105 		       NULL, 0,
1106 #endif
1107 		       NULL, 0,
1108 		       CTL_CREATE, CTL_EOL);
1109 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1110 		       CTLFLAG_PERMANENT,
1111 		       CTLTYPE_STRING, "method",
1112 		       SYSCTL_DESCR("Mitigation method in use"),
1113 		       NULL, 0,
1114 		       v2_mitigation_name, 0,
1115 		       CTL_CREATE, CTL_EOL);
1116 
1117 	/* SpectreV4 */
1118 	spec_rnode = NULL;
1119 	sysctl_createv(clog, 0, NULL, &spec_rnode,
1120 		       CTLFLAG_PERMANENT,
1121 		       CTLTYPE_NODE, "spectre_v4", NULL,
1122 		       NULL, 0, NULL, 0,
1123 		       CTL_MACHDEP, CTL_CREATE);
1124 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1125 		       CTLFLAG_READWRITE,
1126 		       CTLTYPE_BOOL, "mitigated",
1127 		       SYSCTL_DESCR("Whether Spectre Variant 4 is mitigated"),
1128 		       sysctl_machdep_spectreV4_mitigated, 0,
1129 		       &v4_mitigation_enabled, 0,
1130 		       CTL_CREATE, CTL_EOL);
1131 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1132 		       CTLFLAG_PERMANENT,
1133 		       CTLTYPE_STRING, "method",
1134 		       SYSCTL_DESCR("Mitigation method in use"),
1135 		       NULL, 0,
1136 		       v4_mitigation_name, 0,
1137 		       CTL_CREATE, CTL_EOL);
1138 
1139 	/* Microarchitectural Data Sampling */
1140 	spec_rnode = NULL;
1141 	sysctl_createv(clog, 0, NULL, &spec_rnode,
1142 		       CTLFLAG_PERMANENT,
1143 		       CTLTYPE_NODE, "mds", NULL,
1144 		       NULL, 0, NULL, 0,
1145 		       CTL_MACHDEP, CTL_CREATE);
1146 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1147 		       CTLFLAG_READWRITE,
1148 		       CTLTYPE_BOOL, "mitigated",
1149 		       SYSCTL_DESCR("Whether MDS is mitigated"),
1150 		       sysctl_machdep_mds_mitigated, 0,
1151 		       &mds_mitigation_enabled, 0,
1152 		       CTL_CREATE, CTL_EOL);
1153 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1154 		       CTLFLAG_PERMANENT,
1155 		       CTLTYPE_STRING, "method",
1156 		       SYSCTL_DESCR("Mitigation method in use"),
1157 		       NULL, 0,
1158 		       mds_mitigation_name, 0,
1159 		       CTL_CREATE, CTL_EOL);
1160 
1161 	/* TSX Asynchronous Abort */
1162 	spec_rnode = NULL;
1163 	sysctl_createv(clog, 0, NULL, &spec_rnode,
1164 		       CTLFLAG_PERMANENT,
1165 		       CTLTYPE_NODE, "taa", NULL,
1166 		       NULL, 0, NULL, 0,
1167 		       CTL_MACHDEP, CTL_CREATE);
1168 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1169 		       CTLFLAG_READWRITE,
1170 		       CTLTYPE_BOOL, "mitigated",
1171 		       SYSCTL_DESCR("Whether TAA is mitigated"),
1172 		       sysctl_machdep_taa_mitigated, 0,
1173 		       taa_mitigation_enabled_ptr, 0,
1174 		       CTL_CREATE, CTL_EOL);
1175 	sysctl_createv(clog, 0, &spec_rnode, NULL,
1176 		       CTLFLAG_PERMANENT,
1177 		       CTLTYPE_STRING, "method",
1178 		       SYSCTL_DESCR("Mitigation method in use"),
1179 		       NULL, 0,
1180 		       taa_mitigation_name, 0,
1181 		       CTL_CREATE, CTL_EOL);
1182 }
1183