xref: /freebsd/sys/kern/subr_msan.c (revision a422084abbda10edc0b591021536a7c9c6d0c8b4)
1*a422084aSMark Johnston /*	$NetBSD: subr_msan.c,v 1.14 2020/09/09 16:29:59 maxv Exp $	*/
2*a422084aSMark Johnston 
3*a422084aSMark Johnston /*
4*a422084aSMark Johnston  * Copyright (c) 2019-2020 Maxime Villard, m00nbsd.net
5*a422084aSMark Johnston  * All rights reserved.
6*a422084aSMark Johnston  * Copyright (c) 2021 The FreeBSD Foundation
7*a422084aSMark Johnston  *
8*a422084aSMark Johnston  * Portions of this software were developed by Mark Johnston under sponsorship
9*a422084aSMark Johnston  * from the FreeBSD Foundation.
10*a422084aSMark Johnston  *
11*a422084aSMark Johnston  * This code is part of the KMSAN subsystem of the NetBSD kernel.
12*a422084aSMark Johnston  *
13*a422084aSMark Johnston  * Redistribution and use in source and binary forms, with or without
14*a422084aSMark Johnston  * modification, are permitted provided that the following conditions
15*a422084aSMark Johnston  * are met:
16*a422084aSMark Johnston  * 1. Redistributions of source code must retain the above copyright
17*a422084aSMark Johnston  *    notice, this list of conditions and the following disclaimer.
18*a422084aSMark Johnston  * 2. Redistributions in binary form must reproduce the above copyright
19*a422084aSMark Johnston  *    notice, this list of conditions and the following disclaimer in the
20*a422084aSMark Johnston  *    documentation and/or other materials provided with the distribution.
21*a422084aSMark Johnston  *
22*a422084aSMark Johnston  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23*a422084aSMark Johnston  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24*a422084aSMark Johnston  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25*a422084aSMark Johnston  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26*a422084aSMark Johnston  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*a422084aSMark Johnston  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*a422084aSMark Johnston  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*a422084aSMark Johnston  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*a422084aSMark Johnston  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*a422084aSMark Johnston  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*a422084aSMark Johnston  * SUCH DAMAGE.
33*a422084aSMark Johnston  */
34*a422084aSMark Johnston 
35*a422084aSMark Johnston #define	SAN_RUNTIME
36*a422084aSMark Johnston 
37*a422084aSMark Johnston #include <sys/cdefs.h>
38*a422084aSMark Johnston __FBSDID("$FreeBSD$");
39*a422084aSMark Johnston #if 0
40*a422084aSMark Johnston __KERNEL_RCSID(0, "$NetBSD: subr_msan.c,v 1.14 2020/09/09 16:29:59 maxv Exp $");
41*a422084aSMark Johnston #endif
42*a422084aSMark Johnston 
43*a422084aSMark Johnston #include <sys/param.h>
44*a422084aSMark Johnston #include <sys/systm.h>
45*a422084aSMark Johnston #include <sys/bio.h>
46*a422084aSMark Johnston #include <sys/buf.h>
47*a422084aSMark Johnston #include <sys/conf.h>
48*a422084aSMark Johnston #include <sys/kdb.h>
49*a422084aSMark Johnston #include <sys/kernel.h>
50*a422084aSMark Johnston #include <sys/linker.h>
51*a422084aSMark Johnston #include <sys/malloc.h>
52*a422084aSMark Johnston #include <sys/mbuf.h>
53*a422084aSMark Johnston #include <sys/memdesc.h>
54*a422084aSMark Johnston #include <sys/msan.h>
55*a422084aSMark Johnston #include <sys/proc.h>
56*a422084aSMark Johnston #include <sys/stack.h>
57*a422084aSMark Johnston #include <sys/sysctl.h>
58*a422084aSMark Johnston #include <sys/uio.h>
59*a422084aSMark Johnston 
60*a422084aSMark Johnston #include <cam/cam.h>
61*a422084aSMark Johnston #include <cam/cam_ccb.h>
62*a422084aSMark Johnston 
63*a422084aSMark Johnston #include <vm/vm.h>
64*a422084aSMark Johnston #include <vm/pmap.h>
65*a422084aSMark Johnston 
66*a422084aSMark Johnston #include <machine/msan.h>
67*a422084aSMark Johnston #include <machine/stdarg.h>
68*a422084aSMark Johnston 
69*a422084aSMark Johnston void kmsan_init_arg(size_t);
70*a422084aSMark Johnston void kmsan_init_ret(size_t);
71*a422084aSMark Johnston 
72*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
73*a422084aSMark Johnston 
74*a422084aSMark Johnston /*
75*a422084aSMark Johnston  * Part of the compiler ABI.
76*a422084aSMark Johnston  */
77*a422084aSMark Johnston 
78*a422084aSMark Johnston typedef struct {
79*a422084aSMark Johnston 	uint8_t *shad;
80*a422084aSMark Johnston 	msan_orig_t *orig;
81*a422084aSMark Johnston } msan_meta_t;
82*a422084aSMark Johnston 
83*a422084aSMark Johnston #define MSAN_PARAM_SIZE		800
84*a422084aSMark Johnston #define MSAN_RETVAL_SIZE	800
85*a422084aSMark Johnston typedef struct {
86*a422084aSMark Johnston 	uint8_t param_shadow[MSAN_PARAM_SIZE];
87*a422084aSMark Johnston 	uint8_t retval_shadow[MSAN_RETVAL_SIZE];
88*a422084aSMark Johnston 	uint8_t va_arg_shadow[MSAN_PARAM_SIZE];
89*a422084aSMark Johnston 	uint8_t va_arg_origin[MSAN_PARAM_SIZE];
90*a422084aSMark Johnston 	uint64_t va_arg_overflow_size;
91*a422084aSMark Johnston 	msan_orig_t param_origin[MSAN_PARAM_SIZE / sizeof(msan_orig_t)];
92*a422084aSMark Johnston 	msan_orig_t retval_origin;
93*a422084aSMark Johnston } msan_tls_t;
94*a422084aSMark Johnston 
95*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
96*a422084aSMark Johnston 
97*a422084aSMark Johnston #define MSAN_NCONTEXT	4
98*a422084aSMark Johnston #define MSAN_ORIG_MASK	(~0x3)
99*a422084aSMark Johnston 
100*a422084aSMark Johnston typedef struct kmsan_td {
101*a422084aSMark Johnston 	size_t ctx;
102*a422084aSMark Johnston 	msan_tls_t tls[MSAN_NCONTEXT];
103*a422084aSMark Johnston } msan_td_t;
104*a422084aSMark Johnston 
105*a422084aSMark Johnston static msan_tls_t dummy_tls;
106*a422084aSMark Johnston 
107*a422084aSMark Johnston /*
108*a422084aSMark Johnston  * Use separate dummy regions for loads and stores: stores may mark the region
109*a422084aSMark Johnston  * as uninitialized, and that can trigger false positives.
110*a422084aSMark Johnston  */
111*a422084aSMark Johnston static uint8_t msan_dummy_shad[PAGE_SIZE] __aligned(PAGE_SIZE);
112*a422084aSMark Johnston static uint8_t msan_dummy_write_shad[PAGE_SIZE] __aligned(PAGE_SIZE);
113*a422084aSMark Johnston static uint8_t msan_dummy_orig[PAGE_SIZE] __aligned(PAGE_SIZE);
114*a422084aSMark Johnston static msan_td_t msan_thread0;
115*a422084aSMark Johnston static bool kmsan_enabled __read_mostly;
116*a422084aSMark Johnston 
117*a422084aSMark Johnston static bool kmsan_reporting = false;
118*a422084aSMark Johnston 
119*a422084aSMark Johnston /*
120*a422084aSMark Johnston  * Avoid clobbering any thread-local state before we panic.
121*a422084aSMark Johnston  */
122*a422084aSMark Johnston #define	kmsan_panic(f, ...) do {			\
123*a422084aSMark Johnston 	kmsan_enabled = false;				\
124*a422084aSMark Johnston 	panic(f, __VA_ARGS__);				\
125*a422084aSMark Johnston } while (0)
126*a422084aSMark Johnston 
127*a422084aSMark Johnston #define	REPORT(f, ...) do {				\
128*a422084aSMark Johnston 	if (panic_on_violation) {			\
129*a422084aSMark Johnston 		kmsan_panic(f, __VA_ARGS__);		\
130*a422084aSMark Johnston 	} else {					\
131*a422084aSMark Johnston 		struct stack st;			\
132*a422084aSMark Johnston 							\
133*a422084aSMark Johnston 		stack_save(&st);			\
134*a422084aSMark Johnston 		printf(f "\n", __VA_ARGS__);		\
135*a422084aSMark Johnston 		stack_print_ddb(&st);			\
136*a422084aSMark Johnston 	}						\
137*a422084aSMark Johnston } while (0)
138*a422084aSMark Johnston 
139*a422084aSMark Johnston FEATURE(kmsan, "Kernel memory sanitizer");
140*a422084aSMark Johnston 
141*a422084aSMark Johnston static SYSCTL_NODE(_debug, OID_AUTO, kmsan, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
142*a422084aSMark Johnston     "KMSAN options");
143*a422084aSMark Johnston 
144*a422084aSMark Johnston static bool panic_on_violation = 1;
145*a422084aSMark Johnston SYSCTL_BOOL(_debug_kmsan, OID_AUTO, panic_on_violation, CTLFLAG_RWTUN,
146*a422084aSMark Johnston     &panic_on_violation, 0,
147*a422084aSMark Johnston     "Panic if an invalid access is detected");
148*a422084aSMark Johnston 
149*a422084aSMark Johnston static MALLOC_DEFINE(M_KMSAN, "kmsan", "Kernel memory sanitizer");
150*a422084aSMark Johnston 
151*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
152*a422084aSMark Johnston 
153*a422084aSMark Johnston static inline const char *
154*a422084aSMark Johnston kmsan_orig_name(int type)
155*a422084aSMark Johnston {
156*a422084aSMark Johnston 	switch (type) {
157*a422084aSMark Johnston 	case KMSAN_TYPE_STACK:
158*a422084aSMark Johnston 		return ("stack");
159*a422084aSMark Johnston 	case KMSAN_TYPE_KMEM:
160*a422084aSMark Johnston 		return ("kmem");
161*a422084aSMark Johnston 	case KMSAN_TYPE_MALLOC:
162*a422084aSMark Johnston 		return ("malloc");
163*a422084aSMark Johnston 	case KMSAN_TYPE_UMA:
164*a422084aSMark Johnston 		return ("UMA");
165*a422084aSMark Johnston 	default:
166*a422084aSMark Johnston 		return ("unknown");
167*a422084aSMark Johnston 	}
168*a422084aSMark Johnston }
169*a422084aSMark Johnston 
170*a422084aSMark Johnston static void
171*a422084aSMark Johnston kmsan_report_hook(const void *addr, size_t size, size_t off, const char *hook)
172*a422084aSMark Johnston {
173*a422084aSMark Johnston 	msan_orig_t *orig;
174*a422084aSMark Johnston 	const char *typename;
175*a422084aSMark Johnston 	char *var, *fn;
176*a422084aSMark Johnston 	uintptr_t ptr;
177*a422084aSMark Johnston 	long foff;
178*a422084aSMark Johnston 	char buf[128];
179*a422084aSMark Johnston 	int type;
180*a422084aSMark Johnston 
181*a422084aSMark Johnston 	if (__predict_false(panicstr != NULL || kdb_active || kmsan_reporting))
182*a422084aSMark Johnston 		return;
183*a422084aSMark Johnston 
184*a422084aSMark Johnston 	kmsan_reporting = true;
185*a422084aSMark Johnston 	__compiler_membar();
186*a422084aSMark Johnston 
187*a422084aSMark Johnston 	orig = (msan_orig_t *)kmsan_md_addr_to_orig((vm_offset_t)addr);
188*a422084aSMark Johnston 	orig = (msan_orig_t *)((uintptr_t)orig & MSAN_ORIG_MASK);
189*a422084aSMark Johnston 
190*a422084aSMark Johnston 	if (*orig == 0) {
191*a422084aSMark Johnston 		REPORT("MSan: Uninitialized memory in %s, offset %zu",
192*a422084aSMark Johnston 		    hook, off);
193*a422084aSMark Johnston 		goto out;
194*a422084aSMark Johnston 	}
195*a422084aSMark Johnston 
196*a422084aSMark Johnston 	kmsan_md_orig_decode(*orig, &type, &ptr);
197*a422084aSMark Johnston 	typename = kmsan_orig_name(type);
198*a422084aSMark Johnston 
199*a422084aSMark Johnston 	if (linker_ddb_search_symbol_name((caddr_t)ptr, buf,
200*a422084aSMark Johnston 	    sizeof(buf), &foff) == 0) {
201*a422084aSMark Johnston 		REPORT("MSan: Uninitialized %s memory in %s, "
202*a422084aSMark Johnston 		    "offset %zu/%zu, addr %p, from %s+%#lx",
203*a422084aSMark Johnston 		    typename, hook, off, size, addr, buf, foff);
204*a422084aSMark Johnston 	} else if (__builtin_memcmp((void *)ptr, "----", 4) == 0) {
205*a422084aSMark Johnston 		/*
206*a422084aSMark Johnston 		 * The format of the string is: "----var@function". Parse it to
207*a422084aSMark Johnston 		 * display a nice warning.
208*a422084aSMark Johnston 		 */
209*a422084aSMark Johnston 		var = (char *)ptr + 4;
210*a422084aSMark Johnston 		strlcpy(buf, var, sizeof(buf));
211*a422084aSMark Johnston 		var = buf;
212*a422084aSMark Johnston 		fn = strchr(buf, '@');
213*a422084aSMark Johnston 		*fn++ = '\0';
214*a422084aSMark Johnston 		REPORT("MSan: Uninitialized %s memory in %s, offset %zu, "
215*a422084aSMark Johnston 		    "variable '%s' from %s", typename, hook, off, var, fn);
216*a422084aSMark Johnston 	} else {
217*a422084aSMark Johnston 		REPORT("MSan: Uninitialized %s memory in %s, "
218*a422084aSMark Johnston 		    "offset %zu/%zu, addr %p, PC %p",
219*a422084aSMark Johnston 		    typename, hook, off, size, addr, (void *)ptr);
220*a422084aSMark Johnston 	}
221*a422084aSMark Johnston 
222*a422084aSMark Johnston out:
223*a422084aSMark Johnston 	__compiler_membar();
224*a422084aSMark Johnston 	kmsan_reporting = false;
225*a422084aSMark Johnston }
226*a422084aSMark Johnston 
227*a422084aSMark Johnston static void
228*a422084aSMark Johnston kmsan_report_inline(msan_orig_t orig, unsigned long pc)
229*a422084aSMark Johnston {
230*a422084aSMark Johnston 	const char *typename;
231*a422084aSMark Johnston 	char *var, *fn;
232*a422084aSMark Johnston 	uintptr_t ptr;
233*a422084aSMark Johnston 	char buf[128];
234*a422084aSMark Johnston 	long foff;
235*a422084aSMark Johnston 	int type;
236*a422084aSMark Johnston 
237*a422084aSMark Johnston 	if (__predict_false(panicstr != NULL || kdb_active || kmsan_reporting))
238*a422084aSMark Johnston 		return;
239*a422084aSMark Johnston 
240*a422084aSMark Johnston 	kmsan_reporting = true;
241*a422084aSMark Johnston 	__compiler_membar();
242*a422084aSMark Johnston 
243*a422084aSMark Johnston 	if (orig == 0) {
244*a422084aSMark Johnston 		REPORT("MSan: uninitialized variable in %p", (void *)pc);
245*a422084aSMark Johnston 		goto out;
246*a422084aSMark Johnston 	}
247*a422084aSMark Johnston 
248*a422084aSMark Johnston 	kmsan_md_orig_decode(orig, &type, &ptr);
249*a422084aSMark Johnston 	typename = kmsan_orig_name(type);
250*a422084aSMark Johnston 
251*a422084aSMark Johnston 	if (linker_ddb_search_symbol_name((caddr_t)ptr, buf,
252*a422084aSMark Johnston 	    sizeof(buf), &foff) == 0) {
253*a422084aSMark Johnston 		REPORT("MSan: Uninitialized %s memory from %s+%#lx",
254*a422084aSMark Johnston 		    typename, buf, foff);
255*a422084aSMark Johnston 	} else if (__builtin_memcmp((void *)ptr, "----", 4) == 0) {
256*a422084aSMark Johnston 		/*
257*a422084aSMark Johnston 		 * The format of the string is: "----var@function". Parse it to
258*a422084aSMark Johnston 		 * display a nice warning.
259*a422084aSMark Johnston 		 */
260*a422084aSMark Johnston 		var = (char *)ptr + 4;
261*a422084aSMark Johnston 		strlcpy(buf, var, sizeof(buf));
262*a422084aSMark Johnston 		var = buf;
263*a422084aSMark Johnston 		fn = strchr(buf, '@');
264*a422084aSMark Johnston 		*fn++ = '\0';
265*a422084aSMark Johnston 		REPORT("MSan: Uninitialized variable '%s' from %s", var, fn);
266*a422084aSMark Johnston 	} else {
267*a422084aSMark Johnston 		REPORT("MSan: Uninitialized %s memory, origin %x",
268*a422084aSMark Johnston 		    typename, orig);
269*a422084aSMark Johnston 	}
270*a422084aSMark Johnston 
271*a422084aSMark Johnston out:
272*a422084aSMark Johnston 	__compiler_membar();
273*a422084aSMark Johnston 	kmsan_reporting = false;
274*a422084aSMark Johnston }
275*a422084aSMark Johnston 
276*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
277*a422084aSMark Johnston 
278*a422084aSMark Johnston static inline msan_meta_t
279*a422084aSMark Johnston kmsan_meta_get(const void *addr, size_t size, const bool write)
280*a422084aSMark Johnston {
281*a422084aSMark Johnston 	msan_meta_t ret;
282*a422084aSMark Johnston 
283*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled)) {
284*a422084aSMark Johnston 		ret.shad = write ? msan_dummy_write_shad : msan_dummy_shad;
285*a422084aSMark Johnston 		ret.orig = (msan_orig_t *)msan_dummy_orig;
286*a422084aSMark Johnston 	} else if (__predict_false(kmsan_md_unsupported((vm_offset_t)addr))) {
287*a422084aSMark Johnston 		ret.shad = write ? msan_dummy_write_shad : msan_dummy_shad;
288*a422084aSMark Johnston 		ret.orig = (msan_orig_t *)msan_dummy_orig;
289*a422084aSMark Johnston 	} else {
290*a422084aSMark Johnston 		ret.shad = (void *)kmsan_md_addr_to_shad((vm_offset_t)addr);
291*a422084aSMark Johnston 		ret.orig =
292*a422084aSMark Johnston 		    (msan_orig_t *)kmsan_md_addr_to_orig((vm_offset_t)addr);
293*a422084aSMark Johnston 		ret.orig = (msan_orig_t *)((uintptr_t)ret.orig &
294*a422084aSMark Johnston 		    MSAN_ORIG_MASK);
295*a422084aSMark Johnston 	}
296*a422084aSMark Johnston 
297*a422084aSMark Johnston 	return (ret);
298*a422084aSMark Johnston }
299*a422084aSMark Johnston 
300*a422084aSMark Johnston static inline void
301*a422084aSMark Johnston kmsan_origin_fill(const void *addr, msan_orig_t o, size_t size)
302*a422084aSMark Johnston {
303*a422084aSMark Johnston 	msan_orig_t *orig;
304*a422084aSMark Johnston 	size_t i;
305*a422084aSMark Johnston 
306*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
307*a422084aSMark Johnston 		return;
308*a422084aSMark Johnston 	if (__predict_false(kmsan_md_unsupported((vm_offset_t)addr)))
309*a422084aSMark Johnston 		return;
310*a422084aSMark Johnston 
311*a422084aSMark Johnston 	orig = (msan_orig_t *)kmsan_md_addr_to_orig((vm_offset_t)addr);
312*a422084aSMark Johnston 	size += ((uintptr_t)orig & (sizeof(*orig) - 1));
313*a422084aSMark Johnston 	orig = (msan_orig_t *)((uintptr_t)orig & MSAN_ORIG_MASK);
314*a422084aSMark Johnston 
315*a422084aSMark Johnston 	for (i = 0; i < size; i += 4) {
316*a422084aSMark Johnston 		orig[i / 4] = o;
317*a422084aSMark Johnston 	}
318*a422084aSMark Johnston }
319*a422084aSMark Johnston 
320*a422084aSMark Johnston static inline void
321*a422084aSMark Johnston kmsan_shadow_fill(uintptr_t addr, uint8_t c, size_t size)
322*a422084aSMark Johnston {
323*a422084aSMark Johnston 	uint8_t *shad;
324*a422084aSMark Johnston 
325*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
326*a422084aSMark Johnston 		return;
327*a422084aSMark Johnston 	if (__predict_false(kmsan_md_unsupported(addr)))
328*a422084aSMark Johnston 		return;
329*a422084aSMark Johnston 
330*a422084aSMark Johnston 	shad = (uint8_t *)kmsan_md_addr_to_shad(addr);
331*a422084aSMark Johnston 	__builtin_memset(shad, c, size);
332*a422084aSMark Johnston }
333*a422084aSMark Johnston 
334*a422084aSMark Johnston static inline void
335*a422084aSMark Johnston kmsan_meta_copy(void *dst, const void *src, size_t size)
336*a422084aSMark Johnston {
337*a422084aSMark Johnston 	uint8_t *orig_src, *orig_dst;
338*a422084aSMark Johnston 	uint8_t *shad_src, *shad_dst;
339*a422084aSMark Johnston 	msan_orig_t *_src, *_dst;
340*a422084aSMark Johnston 	size_t i;
341*a422084aSMark Johnston 
342*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
343*a422084aSMark Johnston 		return;
344*a422084aSMark Johnston 	if (__predict_false(kmsan_md_unsupported((vm_offset_t)dst)))
345*a422084aSMark Johnston 		return;
346*a422084aSMark Johnston 	if (__predict_false(kmsan_md_unsupported((vm_offset_t)src))) {
347*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)dst, KMSAN_STATE_INITED, size);
348*a422084aSMark Johnston 		return;
349*a422084aSMark Johnston 	}
350*a422084aSMark Johnston 
351*a422084aSMark Johnston 	shad_src = (uint8_t *)kmsan_md_addr_to_shad((vm_offset_t)src);
352*a422084aSMark Johnston 	shad_dst = (uint8_t *)kmsan_md_addr_to_shad((vm_offset_t)dst);
353*a422084aSMark Johnston 	__builtin_memmove(shad_dst, shad_src, size);
354*a422084aSMark Johnston 
355*a422084aSMark Johnston 	orig_src = (uint8_t *)kmsan_md_addr_to_orig((vm_offset_t)src);
356*a422084aSMark Johnston 	orig_dst = (uint8_t *)kmsan_md_addr_to_orig((vm_offset_t)dst);
357*a422084aSMark Johnston 	for (i = 0; i < size; i++) {
358*a422084aSMark Johnston 		_src = (msan_orig_t *)((uintptr_t)orig_src & MSAN_ORIG_MASK);
359*a422084aSMark Johnston 		_dst = (msan_orig_t *)((uintptr_t)orig_dst & MSAN_ORIG_MASK);
360*a422084aSMark Johnston 		*_dst = *_src;
361*a422084aSMark Johnston 		orig_src++;
362*a422084aSMark Johnston 		orig_dst++;
363*a422084aSMark Johnston 	}
364*a422084aSMark Johnston }
365*a422084aSMark Johnston 
366*a422084aSMark Johnston static inline void
367*a422084aSMark Johnston kmsan_shadow_check(uintptr_t addr, size_t size, const char *hook)
368*a422084aSMark Johnston {
369*a422084aSMark Johnston 	uint8_t *shad;
370*a422084aSMark Johnston 	size_t i;
371*a422084aSMark Johnston 
372*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
373*a422084aSMark Johnston 		return;
374*a422084aSMark Johnston 	if (__predict_false(kmsan_md_unsupported(addr)))
375*a422084aSMark Johnston 		return;
376*a422084aSMark Johnston 
377*a422084aSMark Johnston 	shad = (uint8_t *)kmsan_md_addr_to_shad(addr);
378*a422084aSMark Johnston 	for (i = 0; i < size; i++) {
379*a422084aSMark Johnston 		if (__predict_true(shad[i] == 0))
380*a422084aSMark Johnston 			continue;
381*a422084aSMark Johnston 		kmsan_report_hook((const char *)addr + i, size, i, hook);
382*a422084aSMark Johnston 		break;
383*a422084aSMark Johnston 	}
384*a422084aSMark Johnston }
385*a422084aSMark Johnston 
386*a422084aSMark Johnston void
387*a422084aSMark Johnston kmsan_init_arg(size_t n)
388*a422084aSMark Johnston {
389*a422084aSMark Johnston 	msan_td_t *mtd;
390*a422084aSMark Johnston 	uint8_t *arg;
391*a422084aSMark Johnston 
392*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
393*a422084aSMark Johnston 		return;
394*a422084aSMark Johnston 	if (__predict_false(curthread == NULL))
395*a422084aSMark Johnston 		return;
396*a422084aSMark Johnston 	mtd = curthread->td_kmsan;
397*a422084aSMark Johnston 	arg = mtd->tls[mtd->ctx].param_shadow;
398*a422084aSMark Johnston 	__builtin_memset(arg, 0, n);
399*a422084aSMark Johnston }
400*a422084aSMark Johnston 
401*a422084aSMark Johnston void
402*a422084aSMark Johnston kmsan_init_ret(size_t n)
403*a422084aSMark Johnston {
404*a422084aSMark Johnston 	msan_td_t *mtd;
405*a422084aSMark Johnston 	uint8_t *arg;
406*a422084aSMark Johnston 
407*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
408*a422084aSMark Johnston 		return;
409*a422084aSMark Johnston 	if (__predict_false(curthread == NULL))
410*a422084aSMark Johnston 		return;
411*a422084aSMark Johnston 	mtd = curthread->td_kmsan;
412*a422084aSMark Johnston 	arg = mtd->tls[mtd->ctx].retval_shadow;
413*a422084aSMark Johnston 	__builtin_memset(arg, 0, n);
414*a422084aSMark Johnston }
415*a422084aSMark Johnston 
416*a422084aSMark Johnston static void
417*a422084aSMark Johnston kmsan_check_arg(size_t size, const char *hook)
418*a422084aSMark Johnston {
419*a422084aSMark Johnston 	msan_td_t *mtd;
420*a422084aSMark Johnston 	uint8_t *arg;
421*a422084aSMark Johnston 	size_t i;
422*a422084aSMark Johnston 
423*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
424*a422084aSMark Johnston 		return;
425*a422084aSMark Johnston 	if (__predict_false(curthread == NULL))
426*a422084aSMark Johnston 		return;
427*a422084aSMark Johnston 	mtd = curthread->td_kmsan;
428*a422084aSMark Johnston 	arg = mtd->tls[mtd->ctx].param_shadow;
429*a422084aSMark Johnston 
430*a422084aSMark Johnston 	for (i = 0; i < size; i++) {
431*a422084aSMark Johnston 		if (__predict_true(arg[i] == 0))
432*a422084aSMark Johnston 			continue;
433*a422084aSMark Johnston 		kmsan_report_hook((const char *)arg + i, size, i, hook);
434*a422084aSMark Johnston 		break;
435*a422084aSMark Johnston 	}
436*a422084aSMark Johnston }
437*a422084aSMark Johnston 
438*a422084aSMark Johnston void
439*a422084aSMark Johnston kmsan_thread_alloc(struct thread *td)
440*a422084aSMark Johnston {
441*a422084aSMark Johnston 	msan_td_t *mtd;
442*a422084aSMark Johnston 
443*a422084aSMark Johnston 	if (!kmsan_enabled)
444*a422084aSMark Johnston 		return;
445*a422084aSMark Johnston 
446*a422084aSMark Johnston 	mtd = td->td_kmsan;
447*a422084aSMark Johnston 	if (mtd == NULL) {
448*a422084aSMark Johnston 		/* We might be recycling a thread. */
449*a422084aSMark Johnston 		kmsan_init_arg(sizeof(size_t) + sizeof(struct malloc_type *) +
450*a422084aSMark Johnston 		    sizeof(int));
451*a422084aSMark Johnston 		mtd = malloc(sizeof(*mtd), M_KMSAN, M_WAITOK);
452*a422084aSMark Johnston 	}
453*a422084aSMark Johnston 	kmsan_memset(mtd, 0, sizeof(*mtd));
454*a422084aSMark Johnston 	mtd->ctx = 0;
455*a422084aSMark Johnston 
456*a422084aSMark Johnston 	if (td->td_kstack != 0)
457*a422084aSMark Johnston 		kmsan_mark((void *)td->td_kstack, ptoa(td->td_kstack_pages),
458*a422084aSMark Johnston 		    KMSAN_STATE_UNINIT);
459*a422084aSMark Johnston 
460*a422084aSMark Johnston 	td->td_kmsan = mtd;
461*a422084aSMark Johnston }
462*a422084aSMark Johnston 
463*a422084aSMark Johnston void
464*a422084aSMark Johnston kmsan_thread_free(struct thread *td)
465*a422084aSMark Johnston {
466*a422084aSMark Johnston 	msan_td_t *mtd;
467*a422084aSMark Johnston 
468*a422084aSMark Johnston 	if (!kmsan_enabled)
469*a422084aSMark Johnston 		return;
470*a422084aSMark Johnston 	if (__predict_false(td == curthread))
471*a422084aSMark Johnston 		kmsan_panic("%s: freeing KMSAN TLS for curthread", __func__);
472*a422084aSMark Johnston 
473*a422084aSMark Johnston 	mtd = td->td_kmsan;
474*a422084aSMark Johnston 	kmsan_init_arg(sizeof(void *) + sizeof(struct malloc_type *));
475*a422084aSMark Johnston 	free(mtd, M_KMSAN);
476*a422084aSMark Johnston 	td->td_kmsan = NULL;
477*a422084aSMark Johnston }
478*a422084aSMark Johnston 
479*a422084aSMark Johnston void kmsan_intr_enter(void);
480*a422084aSMark Johnston void kmsan_intr_leave(void);
481*a422084aSMark Johnston 
482*a422084aSMark Johnston void
483*a422084aSMark Johnston kmsan_intr_enter(void)
484*a422084aSMark Johnston {
485*a422084aSMark Johnston 	msan_td_t *mtd;
486*a422084aSMark Johnston 
487*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
488*a422084aSMark Johnston 		return;
489*a422084aSMark Johnston 
490*a422084aSMark Johnston 	mtd = curthread->td_kmsan;
491*a422084aSMark Johnston 	mtd->ctx++;
492*a422084aSMark Johnston 	if (__predict_false(mtd->ctx >= MSAN_NCONTEXT))
493*a422084aSMark Johnston 		kmsan_panic("%s: mtd->ctx = %zu", __func__, mtd->ctx);
494*a422084aSMark Johnston }
495*a422084aSMark Johnston 
496*a422084aSMark Johnston void
497*a422084aSMark Johnston kmsan_intr_leave(void)
498*a422084aSMark Johnston {
499*a422084aSMark Johnston 	msan_td_t *mtd;
500*a422084aSMark Johnston 
501*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
502*a422084aSMark Johnston 		return;
503*a422084aSMark Johnston 
504*a422084aSMark Johnston 	mtd = curthread->td_kmsan;
505*a422084aSMark Johnston 	if (__predict_false(mtd->ctx == 0))
506*a422084aSMark Johnston 		kmsan_panic("%s: mtd->ctx = %zu", __func__, mtd->ctx);
507*a422084aSMark Johnston 	mtd->ctx--;
508*a422084aSMark Johnston }
509*a422084aSMark Johnston 
510*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
511*a422084aSMark Johnston 
512*a422084aSMark Johnston void
513*a422084aSMark Johnston kmsan_shadow_map(vm_offset_t addr, size_t size)
514*a422084aSMark Johnston {
515*a422084aSMark Johnston 	size_t npages, i;
516*a422084aSMark Johnston 	vm_offset_t va;
517*a422084aSMark Johnston 
518*a422084aSMark Johnston 	MPASS(addr % PAGE_SIZE == 0);
519*a422084aSMark Johnston 	MPASS(size % PAGE_SIZE == 0);
520*a422084aSMark Johnston 
521*a422084aSMark Johnston 	if (!kmsan_enabled)
522*a422084aSMark Johnston 		return;
523*a422084aSMark Johnston 
524*a422084aSMark Johnston 	npages = atop(size);
525*a422084aSMark Johnston 
526*a422084aSMark Johnston 	va = kmsan_md_addr_to_shad(addr);
527*a422084aSMark Johnston 	for (i = 0; i < npages; i++) {
528*a422084aSMark Johnston 		pmap_kmsan_enter(va + ptoa(i));
529*a422084aSMark Johnston 	}
530*a422084aSMark Johnston 
531*a422084aSMark Johnston 	va = kmsan_md_addr_to_orig(addr);
532*a422084aSMark Johnston 	for (i = 0; i < npages; i++) {
533*a422084aSMark Johnston 		pmap_kmsan_enter(va + ptoa(i));
534*a422084aSMark Johnston 	}
535*a422084aSMark Johnston }
536*a422084aSMark Johnston 
537*a422084aSMark Johnston void
538*a422084aSMark Johnston kmsan_orig(const void *addr, size_t size, int type, uintptr_t pc)
539*a422084aSMark Johnston {
540*a422084aSMark Johnston 	msan_orig_t orig;
541*a422084aSMark Johnston 
542*a422084aSMark Johnston 	orig = kmsan_md_orig_encode(type, pc);
543*a422084aSMark Johnston 	kmsan_origin_fill(addr, orig, size);
544*a422084aSMark Johnston }
545*a422084aSMark Johnston 
546*a422084aSMark Johnston void
547*a422084aSMark Johnston kmsan_mark(const void *addr, size_t size, uint8_t c)
548*a422084aSMark Johnston {
549*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)addr, c, size);
550*a422084aSMark Johnston }
551*a422084aSMark Johnston 
552*a422084aSMark Johnston static void
553*a422084aSMark Johnston kmsan_mark_bio(const struct bio *bp, uint8_t c)
554*a422084aSMark Johnston {
555*a422084aSMark Johnston 	kmsan_mark(bp->bio_data, bp->bio_length, c);
556*a422084aSMark Johnston }
557*a422084aSMark Johnston 
558*a422084aSMark Johnston static void
559*a422084aSMark Johnston kmsan_mark_ccb(const union ccb *ccb, uint8_t c)
560*a422084aSMark Johnston {
561*a422084aSMark Johnston 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_IN)
562*a422084aSMark Johnston 		return;
563*a422084aSMark Johnston 	if ((ccb->ccb_h.flags & CAM_DATA_MASK) != CAM_DATA_VADDR)
564*a422084aSMark Johnston 		return;
565*a422084aSMark Johnston 
566*a422084aSMark Johnston 	switch (ccb->ccb_h.func_code) {
567*a422084aSMark Johnston 	case XPT_SCSI_IO: {
568*a422084aSMark Johnston 		const struct ccb_scsiio *scsiio;
569*a422084aSMark Johnston 
570*a422084aSMark Johnston 		scsiio = &ccb->ctio;
571*a422084aSMark Johnston 		kmsan_mark(scsiio->data_ptr, scsiio->dxfer_len, c);
572*a422084aSMark Johnston 		break;
573*a422084aSMark Johnston 	}
574*a422084aSMark Johnston 	case XPT_ATA_IO: {
575*a422084aSMark Johnston 		const struct ccb_ataio *ataio;
576*a422084aSMark Johnston 
577*a422084aSMark Johnston 		ataio = &ccb->ataio;
578*a422084aSMark Johnston 		kmsan_mark(ataio->data_ptr, ataio->dxfer_len, c);
579*a422084aSMark Johnston 		break;
580*a422084aSMark Johnston 	}
581*a422084aSMark Johnston 	case XPT_NVME_IO: {
582*a422084aSMark Johnston 		const struct ccb_nvmeio *nvmeio;
583*a422084aSMark Johnston 
584*a422084aSMark Johnston 		nvmeio = &ccb->nvmeio;
585*a422084aSMark Johnston 		kmsan_mark(nvmeio->data_ptr, nvmeio->dxfer_len, c);
586*a422084aSMark Johnston 		break;
587*a422084aSMark Johnston 	}
588*a422084aSMark Johnston 	default:
589*a422084aSMark Johnston 		kmsan_panic("%s: unhandled CCB type %d", __func__,
590*a422084aSMark Johnston 		    ccb->ccb_h.func_code);
591*a422084aSMark Johnston 	}
592*a422084aSMark Johnston }
593*a422084aSMark Johnston 
594*a422084aSMark Johnston static void
595*a422084aSMark Johnston kmsan_mark_mbuf(const struct mbuf *m, uint8_t c)
596*a422084aSMark Johnston {
597*a422084aSMark Johnston 	do {
598*a422084aSMark Johnston 		if ((m->m_flags & M_EXTPG) == 0)
599*a422084aSMark Johnston 			kmsan_mark(m->m_data, m->m_len, c);
600*a422084aSMark Johnston 		m = m->m_next;
601*a422084aSMark Johnston 	} while (m != NULL);
602*a422084aSMark Johnston }
603*a422084aSMark Johnston 
604*a422084aSMark Johnston void
605*a422084aSMark Johnston kmsan_check(const void *p, size_t sz, const char *descr)
606*a422084aSMark Johnston {
607*a422084aSMark Johnston 	kmsan_shadow_check((uintptr_t)p, sz, descr);
608*a422084aSMark Johnston }
609*a422084aSMark Johnston 
610*a422084aSMark Johnston void
611*a422084aSMark Johnston kmsan_check_bio(const struct bio *bp, const char *descr)
612*a422084aSMark Johnston {
613*a422084aSMark Johnston 	kmsan_shadow_check((uintptr_t)bp->bio_data, bp->bio_length, descr);
614*a422084aSMark Johnston }
615*a422084aSMark Johnston 
616*a422084aSMark Johnston void
617*a422084aSMark Johnston kmsan_check_ccb(const union ccb *ccb, const char *descr)
618*a422084aSMark Johnston {
619*a422084aSMark Johnston 	if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_OUT)
620*a422084aSMark Johnston 		return;
621*a422084aSMark Johnston 	switch (ccb->ccb_h.func_code) {
622*a422084aSMark Johnston 	case XPT_SCSI_IO: {
623*a422084aSMark Johnston 		const struct ccb_scsiio *scsiio;
624*a422084aSMark Johnston 
625*a422084aSMark Johnston 		scsiio = &ccb->ctio;
626*a422084aSMark Johnston 		kmsan_check(scsiio->data_ptr, scsiio->dxfer_len, descr);
627*a422084aSMark Johnston 		break;
628*a422084aSMark Johnston 	}
629*a422084aSMark Johnston 	case XPT_ATA_IO: {
630*a422084aSMark Johnston 		const struct ccb_ataio *ataio;
631*a422084aSMark Johnston 
632*a422084aSMark Johnston 		ataio = &ccb->ataio;
633*a422084aSMark Johnston 		kmsan_check(ataio->data_ptr, ataio->dxfer_len, descr);
634*a422084aSMark Johnston 		break;
635*a422084aSMark Johnston 	}
636*a422084aSMark Johnston 	case XPT_NVME_IO: {
637*a422084aSMark Johnston 		const struct ccb_nvmeio *nvmeio;
638*a422084aSMark Johnston 
639*a422084aSMark Johnston 		nvmeio = &ccb->nvmeio;
640*a422084aSMark Johnston 		kmsan_check(nvmeio->data_ptr, nvmeio->dxfer_len, descr);
641*a422084aSMark Johnston 		break;
642*a422084aSMark Johnston 	}
643*a422084aSMark Johnston 	default:
644*a422084aSMark Johnston 		kmsan_panic("%s: unhandled CCB type %d", __func__,
645*a422084aSMark Johnston 		    ccb->ccb_h.func_code);
646*a422084aSMark Johnston 	}
647*a422084aSMark Johnston }
648*a422084aSMark Johnston 
649*a422084aSMark Johnston void
650*a422084aSMark Johnston kmsan_check_mbuf(const struct mbuf *m, const char *descr)
651*a422084aSMark Johnston {
652*a422084aSMark Johnston 	do {
653*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)mtod(m, void *), m->m_len, descr);
654*a422084aSMark Johnston 	} while ((m = m->m_next) != NULL);
655*a422084aSMark Johnston }
656*a422084aSMark Johnston 
657*a422084aSMark Johnston void
658*a422084aSMark Johnston kmsan_init(void)
659*a422084aSMark Johnston {
660*a422084aSMark Johnston 	int disabled;
661*a422084aSMark Johnston 
662*a422084aSMark Johnston 	disabled = 0;
663*a422084aSMark Johnston 	TUNABLE_INT_FETCH("debug.kmsan.disabled", &disabled);
664*a422084aSMark Johnston 	if (disabled)
665*a422084aSMark Johnston 		return;
666*a422084aSMark Johnston 
667*a422084aSMark Johnston 	/* Initialize the TLS for curthread. */
668*a422084aSMark Johnston 	msan_thread0.ctx = 0;
669*a422084aSMark Johnston 	thread0.td_kmsan = &msan_thread0;
670*a422084aSMark Johnston 
671*a422084aSMark Johnston 	/* Now officially enabled. */
672*a422084aSMark Johnston 	kmsan_enabled = true;
673*a422084aSMark Johnston }
674*a422084aSMark Johnston 
675*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
676*a422084aSMark Johnston 
677*a422084aSMark Johnston msan_meta_t __msan_metadata_ptr_for_load_n(void *, size_t);
678*a422084aSMark Johnston msan_meta_t __msan_metadata_ptr_for_store_n(void *, size_t);
679*a422084aSMark Johnston 
680*a422084aSMark Johnston msan_meta_t
681*a422084aSMark Johnston __msan_metadata_ptr_for_load_n(void *addr, size_t size)
682*a422084aSMark Johnston {
683*a422084aSMark Johnston 	return (kmsan_meta_get(addr, size, false));
684*a422084aSMark Johnston }
685*a422084aSMark Johnston 
686*a422084aSMark Johnston msan_meta_t
687*a422084aSMark Johnston __msan_metadata_ptr_for_store_n(void *addr, size_t size)
688*a422084aSMark Johnston {
689*a422084aSMark Johnston 	return (kmsan_meta_get(addr, size, true));
690*a422084aSMark Johnston }
691*a422084aSMark Johnston 
692*a422084aSMark Johnston #define MSAN_META_FUNC(size)						\
693*a422084aSMark Johnston 	msan_meta_t __msan_metadata_ptr_for_load_##size(void *);	\
694*a422084aSMark Johnston 	msan_meta_t __msan_metadata_ptr_for_load_##size(void *addr)	\
695*a422084aSMark Johnston 	{								\
696*a422084aSMark Johnston 		return (kmsan_meta_get(addr, size, false));		\
697*a422084aSMark Johnston 	}								\
698*a422084aSMark Johnston 	msan_meta_t __msan_metadata_ptr_for_store_##size(void *);	\
699*a422084aSMark Johnston 	msan_meta_t __msan_metadata_ptr_for_store_##size(void *addr)	\
700*a422084aSMark Johnston 	{								\
701*a422084aSMark Johnston 		return (kmsan_meta_get(addr, size, true));		\
702*a422084aSMark Johnston 	}
703*a422084aSMark Johnston 
704*a422084aSMark Johnston MSAN_META_FUNC(1)
705*a422084aSMark Johnston MSAN_META_FUNC(2)
706*a422084aSMark Johnston MSAN_META_FUNC(4)
707*a422084aSMark Johnston MSAN_META_FUNC(8)
708*a422084aSMark Johnston 
709*a422084aSMark Johnston void __msan_instrument_asm_store(const void *, size_t);
710*a422084aSMark Johnston msan_orig_t __msan_chain_origin(msan_orig_t);
711*a422084aSMark Johnston void __msan_poison(const void *, size_t);
712*a422084aSMark Johnston void __msan_unpoison(const void *, size_t);
713*a422084aSMark Johnston void __msan_poison_alloca(const void *, uint64_t, const char *);
714*a422084aSMark Johnston void __msan_unpoison_alloca(const void *, uint64_t);
715*a422084aSMark Johnston void __msan_warning(msan_orig_t);
716*a422084aSMark Johnston msan_tls_t *__msan_get_context_state(void);
717*a422084aSMark Johnston 
718*a422084aSMark Johnston void
719*a422084aSMark Johnston __msan_instrument_asm_store(const void *addr, size_t size)
720*a422084aSMark Johnston {
721*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_INITED, size);
722*a422084aSMark Johnston }
723*a422084aSMark Johnston 
724*a422084aSMark Johnston msan_orig_t
725*a422084aSMark Johnston __msan_chain_origin(msan_orig_t origin)
726*a422084aSMark Johnston {
727*a422084aSMark Johnston 	return (origin);
728*a422084aSMark Johnston }
729*a422084aSMark Johnston 
730*a422084aSMark Johnston void
731*a422084aSMark Johnston __msan_poison(const void *addr, size_t size)
732*a422084aSMark Johnston {
733*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_UNINIT, size);
734*a422084aSMark Johnston }
735*a422084aSMark Johnston 
736*a422084aSMark Johnston void
737*a422084aSMark Johnston __msan_unpoison(const void *addr, size_t size)
738*a422084aSMark Johnston {
739*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_INITED, size);
740*a422084aSMark Johnston }
741*a422084aSMark Johnston 
742*a422084aSMark Johnston void
743*a422084aSMark Johnston __msan_poison_alloca(const void *addr, uint64_t size, const char *descr)
744*a422084aSMark Johnston {
745*a422084aSMark Johnston 	msan_orig_t orig;
746*a422084aSMark Johnston 
747*a422084aSMark Johnston 	orig = kmsan_md_orig_encode(KMSAN_TYPE_STACK, (uintptr_t)descr);
748*a422084aSMark Johnston 	kmsan_origin_fill(addr, orig, size);
749*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_UNINIT, size);
750*a422084aSMark Johnston }
751*a422084aSMark Johnston 
752*a422084aSMark Johnston void
753*a422084aSMark Johnston __msan_unpoison_alloca(const void *addr, uint64_t size)
754*a422084aSMark Johnston {
755*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)addr, KMSAN_STATE_INITED, size);
756*a422084aSMark Johnston }
757*a422084aSMark Johnston 
758*a422084aSMark Johnston void
759*a422084aSMark Johnston __msan_warning(msan_orig_t origin)
760*a422084aSMark Johnston {
761*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled))
762*a422084aSMark Johnston 		return;
763*a422084aSMark Johnston 	kmsan_report_inline(origin, KMSAN_RET_ADDR);
764*a422084aSMark Johnston }
765*a422084aSMark Johnston 
766*a422084aSMark Johnston msan_tls_t *
767*a422084aSMark Johnston __msan_get_context_state(void)
768*a422084aSMark Johnston {
769*a422084aSMark Johnston 	msan_td_t *mtd;
770*a422084aSMark Johnston 
771*a422084aSMark Johnston 	/*
772*a422084aSMark Johnston 	 * When APs are started, they execute some C code before curthread is
773*a422084aSMark Johnston 	 * set.  We have to handle that here.
774*a422084aSMark Johnston 	 */
775*a422084aSMark Johnston 	if (__predict_false(!kmsan_enabled || curthread == NULL))
776*a422084aSMark Johnston 		return (&dummy_tls);
777*a422084aSMark Johnston 	mtd = curthread->td_kmsan;
778*a422084aSMark Johnston 	return (&mtd->tls[mtd->ctx]);
779*a422084aSMark Johnston }
780*a422084aSMark Johnston 
781*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
782*a422084aSMark Johnston 
783*a422084aSMark Johnston /*
784*a422084aSMark Johnston  * Function hooks. Mostly ASM functions which need KMSAN wrappers to handle
785*a422084aSMark Johnston  * initialized areas properly.
786*a422084aSMark Johnston  */
787*a422084aSMark Johnston 
788*a422084aSMark Johnston void *
789*a422084aSMark Johnston kmsan_memcpy(void *dst, const void *src, size_t len)
790*a422084aSMark Johnston {
791*a422084aSMark Johnston 	/* No kmsan_check_arg, because inlined. */
792*a422084aSMark Johnston 	kmsan_init_ret(sizeof(void *));
793*a422084aSMark Johnston 	if (__predict_true(len != 0)) {
794*a422084aSMark Johnston 		kmsan_meta_copy(dst, src, len);
795*a422084aSMark Johnston 	}
796*a422084aSMark Johnston 	return (__builtin_memcpy(dst, src, len));
797*a422084aSMark Johnston }
798*a422084aSMark Johnston 
799*a422084aSMark Johnston int
800*a422084aSMark Johnston kmsan_memcmp(const void *b1, const void *b2, size_t len)
801*a422084aSMark Johnston {
802*a422084aSMark Johnston 	const uint8_t *_b1 = b1, *_b2 = b2;
803*a422084aSMark Johnston 	size_t i;
804*a422084aSMark Johnston 
805*a422084aSMark Johnston 	kmsan_check_arg(sizeof(b1) + sizeof(b2) + sizeof(len),
806*a422084aSMark Johnston 	    "memcmp():args");
807*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
808*a422084aSMark Johnston 
809*a422084aSMark Johnston 	for (i = 0; i < len; i++) {
810*a422084aSMark Johnston 		if (*_b1 != *_b2) {
811*a422084aSMark Johnston 			kmsan_shadow_check((uintptr_t)b1, i + 1,
812*a422084aSMark Johnston 			    "memcmp():arg1");
813*a422084aSMark Johnston 			kmsan_shadow_check((uintptr_t)b2, i + 1,
814*a422084aSMark Johnston 			    "memcmp():arg2");
815*a422084aSMark Johnston 			return (*_b1 - *_b2);
816*a422084aSMark Johnston 		}
817*a422084aSMark Johnston 		_b1++, _b2++;
818*a422084aSMark Johnston 	}
819*a422084aSMark Johnston 
820*a422084aSMark Johnston 	return (0);
821*a422084aSMark Johnston }
822*a422084aSMark Johnston 
823*a422084aSMark Johnston void *
824*a422084aSMark Johnston kmsan_memset(void *dst, int c, size_t len)
825*a422084aSMark Johnston {
826*a422084aSMark Johnston 	/* No kmsan_check_arg, because inlined. */
827*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)dst, KMSAN_STATE_INITED, len);
828*a422084aSMark Johnston 	kmsan_init_ret(sizeof(void *));
829*a422084aSMark Johnston 	return (__builtin_memset(dst, c, len));
830*a422084aSMark Johnston }
831*a422084aSMark Johnston 
832*a422084aSMark Johnston void *
833*a422084aSMark Johnston kmsan_memmove(void *dst, const void *src, size_t len)
834*a422084aSMark Johnston {
835*a422084aSMark Johnston 	/* No kmsan_check_arg, because inlined. */
836*a422084aSMark Johnston 	if (__predict_true(len != 0)) {
837*a422084aSMark Johnston 		kmsan_meta_copy(dst, src, len);
838*a422084aSMark Johnston 	}
839*a422084aSMark Johnston 	kmsan_init_ret(sizeof(void *));
840*a422084aSMark Johnston 	return (__builtin_memmove(dst, src, len));
841*a422084aSMark Johnston }
842*a422084aSMark Johnston 
843*a422084aSMark Johnston __strong_reference(kmsan_memcpy, __msan_memcpy);
844*a422084aSMark Johnston __strong_reference(kmsan_memset, __msan_memset);
845*a422084aSMark Johnston __strong_reference(kmsan_memmove, __msan_memmove);
846*a422084aSMark Johnston 
847*a422084aSMark Johnston char *
848*a422084aSMark Johnston kmsan_strcpy(char *dst, const char *src)
849*a422084aSMark Johnston {
850*a422084aSMark Johnston 	const char *_src = src;
851*a422084aSMark Johnston 	char *_dst = dst;
852*a422084aSMark Johnston 	size_t len = 0;
853*a422084aSMark Johnston 
854*a422084aSMark Johnston 	kmsan_check_arg(sizeof(dst) + sizeof(src), "strcpy():args");
855*a422084aSMark Johnston 
856*a422084aSMark Johnston 	while (1) {
857*a422084aSMark Johnston 		len++;
858*a422084aSMark Johnston 		*dst = *src;
859*a422084aSMark Johnston 		if (*src == '\0')
860*a422084aSMark Johnston 			break;
861*a422084aSMark Johnston 		src++, dst++;
862*a422084aSMark Johnston 	}
863*a422084aSMark Johnston 
864*a422084aSMark Johnston 	kmsan_shadow_check((uintptr_t)_src, len, "strcpy():arg2");
865*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)_dst, KMSAN_STATE_INITED, len);
866*a422084aSMark Johnston 	kmsan_init_ret(sizeof(char *));
867*a422084aSMark Johnston 	return (_dst);
868*a422084aSMark Johnston }
869*a422084aSMark Johnston 
870*a422084aSMark Johnston int
871*a422084aSMark Johnston kmsan_strcmp(const char *s1, const char *s2)
872*a422084aSMark Johnston {
873*a422084aSMark Johnston 	const char *_s1 = s1, *_s2 = s2;
874*a422084aSMark Johnston 	size_t len = 0;
875*a422084aSMark Johnston 
876*a422084aSMark Johnston 	kmsan_check_arg(sizeof(s1) + sizeof(s2), "strcmp():args");
877*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
878*a422084aSMark Johnston 
879*a422084aSMark Johnston 	while (1) {
880*a422084aSMark Johnston 		len++;
881*a422084aSMark Johnston 		if (*s1 != *s2)
882*a422084aSMark Johnston 			break;
883*a422084aSMark Johnston 		if (*s1 == '\0') {
884*a422084aSMark Johnston 			kmsan_shadow_check((uintptr_t)_s1, len, "strcmp():arg1");
885*a422084aSMark Johnston 			kmsan_shadow_check((uintptr_t)_s2, len, "strcmp():arg2");
886*a422084aSMark Johnston 			return (0);
887*a422084aSMark Johnston 		}
888*a422084aSMark Johnston 		s1++, s2++;
889*a422084aSMark Johnston 	}
890*a422084aSMark Johnston 
891*a422084aSMark Johnston 	kmsan_shadow_check((uintptr_t)_s1, len, "strcmp():arg1");
892*a422084aSMark Johnston 	kmsan_shadow_check((uintptr_t)_s2, len, "strcmp():arg2");
893*a422084aSMark Johnston 
894*a422084aSMark Johnston 	return (*(const unsigned char *)s1 - *(const unsigned char *)s2);
895*a422084aSMark Johnston }
896*a422084aSMark Johnston 
897*a422084aSMark Johnston size_t
898*a422084aSMark Johnston kmsan_strlen(const char *str)
899*a422084aSMark Johnston {
900*a422084aSMark Johnston 	const char *s;
901*a422084aSMark Johnston 
902*a422084aSMark Johnston 	kmsan_check_arg(sizeof(str), "strlen():args");
903*a422084aSMark Johnston 
904*a422084aSMark Johnston 	s = str;
905*a422084aSMark Johnston 	while (1) {
906*a422084aSMark Johnston 		if (*s == '\0')
907*a422084aSMark Johnston 			break;
908*a422084aSMark Johnston 		s++;
909*a422084aSMark Johnston 	}
910*a422084aSMark Johnston 
911*a422084aSMark Johnston 	kmsan_shadow_check((uintptr_t)str, (size_t)(s - str) + 1, "strlen():arg1");
912*a422084aSMark Johnston 	kmsan_init_ret(sizeof(size_t));
913*a422084aSMark Johnston 	return (s - str);
914*a422084aSMark Johnston }
915*a422084aSMark Johnston 
916*a422084aSMark Johnston int	kmsan_copyin(const void *, void *, size_t);
917*a422084aSMark Johnston int	kmsan_copyout(const void *, void *, size_t);
918*a422084aSMark Johnston int	kmsan_copyinstr(const void *, void *, size_t, size_t *);
919*a422084aSMark Johnston 
920*a422084aSMark Johnston int
921*a422084aSMark Johnston kmsan_copyin(const void *uaddr, void *kaddr, size_t len)
922*a422084aSMark Johnston {
923*a422084aSMark Johnston 	int ret;
924*a422084aSMark Johnston 
925*a422084aSMark Johnston 	kmsan_check_arg(sizeof(uaddr) + sizeof(kaddr) + sizeof(len),
926*a422084aSMark Johnston 	    "copyin():args");
927*a422084aSMark Johnston 	ret = copyin(uaddr, kaddr, len);
928*a422084aSMark Johnston 	if (ret == 0)
929*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)kaddr, KMSAN_STATE_INITED, len);
930*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
931*a422084aSMark Johnston 	return (ret);
932*a422084aSMark Johnston }
933*a422084aSMark Johnston 
934*a422084aSMark Johnston int
935*a422084aSMark Johnston kmsan_copyout(const void *kaddr, void *uaddr, size_t len)
936*a422084aSMark Johnston {
937*a422084aSMark Johnston 	kmsan_check_arg(sizeof(kaddr) + sizeof(uaddr) + sizeof(len),
938*a422084aSMark Johnston 	    "copyout():args");
939*a422084aSMark Johnston 	kmsan_shadow_check((uintptr_t)kaddr, len, "copyout():arg1");
940*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
941*a422084aSMark Johnston 	return (copyout(kaddr, uaddr, len));
942*a422084aSMark Johnston }
943*a422084aSMark Johnston 
944*a422084aSMark Johnston int
945*a422084aSMark Johnston kmsan_copyinstr(const void *uaddr, void *kaddr, size_t len, size_t *done)
946*a422084aSMark Johnston {
947*a422084aSMark Johnston 	size_t _done;
948*a422084aSMark Johnston 	int ret;
949*a422084aSMark Johnston 
950*a422084aSMark Johnston 	kmsan_check_arg(sizeof(uaddr) + sizeof(kaddr) +
951*a422084aSMark Johnston 	    sizeof(len) + sizeof(done), "copyinstr():args");
952*a422084aSMark Johnston 	ret = copyinstr(uaddr, kaddr, len, &_done);
953*a422084aSMark Johnston 	if (ret == 0)
954*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)kaddr, KMSAN_STATE_INITED, _done);
955*a422084aSMark Johnston 	if (done != NULL) {
956*a422084aSMark Johnston 		*done = _done;
957*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)done, KMSAN_STATE_INITED, sizeof(size_t));
958*a422084aSMark Johnston 	}
959*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
960*a422084aSMark Johnston 	return (ret);
961*a422084aSMark Johnston }
962*a422084aSMark Johnston 
963*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
964*a422084aSMark Johnston 
965*a422084aSMark Johnston int
966*a422084aSMark Johnston kmsan_fubyte(volatile const void *base)
967*a422084aSMark Johnston {
968*a422084aSMark Johnston 	int ret;
969*a422084aSMark Johnston 
970*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base), "fubyte(): args");
971*a422084aSMark Johnston 	ret = fubyte(base);
972*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
973*a422084aSMark Johnston 	return (ret);
974*a422084aSMark Johnston }
975*a422084aSMark Johnston 
976*a422084aSMark Johnston int
977*a422084aSMark Johnston kmsan_fuword16(volatile const void *base)
978*a422084aSMark Johnston {
979*a422084aSMark Johnston 	int ret;
980*a422084aSMark Johnston 
981*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base), "fuword16(): args");
982*a422084aSMark Johnston 	ret = fuword16(base);
983*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
984*a422084aSMark Johnston 	return (ret);
985*a422084aSMark Johnston }
986*a422084aSMark Johnston 
987*a422084aSMark Johnston int
988*a422084aSMark Johnston kmsan_fueword(volatile const void *base, long *val)
989*a422084aSMark Johnston {
990*a422084aSMark Johnston 	int ret;
991*a422084aSMark Johnston 
992*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(val), "fueword(): args");
993*a422084aSMark Johnston 	ret = fueword(base, val);
994*a422084aSMark Johnston 	if (ret == 0)
995*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)val, KMSAN_STATE_INITED,
996*a422084aSMark Johnston 		    sizeof(*val));
997*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
998*a422084aSMark Johnston 	return (ret);
999*a422084aSMark Johnston }
1000*a422084aSMark Johnston 
1001*a422084aSMark Johnston int
1002*a422084aSMark Johnston kmsan_fueword32(volatile const void *base, int32_t *val)
1003*a422084aSMark Johnston {
1004*a422084aSMark Johnston 	int ret;
1005*a422084aSMark Johnston 
1006*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(val), "fueword32(): args");
1007*a422084aSMark Johnston 	ret = fueword32(base, val);
1008*a422084aSMark Johnston 	if (ret == 0)
1009*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)val, KMSAN_STATE_INITED,
1010*a422084aSMark Johnston 		    sizeof(*val));
1011*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1012*a422084aSMark Johnston 	return (ret);
1013*a422084aSMark Johnston }
1014*a422084aSMark Johnston 
1015*a422084aSMark Johnston int
1016*a422084aSMark Johnston kmsan_fueword64(volatile const void *base, int64_t *val)
1017*a422084aSMark Johnston {
1018*a422084aSMark Johnston 	int ret;
1019*a422084aSMark Johnston 
1020*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(val), "fueword64(): args");
1021*a422084aSMark Johnston 	ret = fueword64(base, val);
1022*a422084aSMark Johnston 	if (ret == 0)
1023*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)val, KMSAN_STATE_INITED,
1024*a422084aSMark Johnston 		    sizeof(*val));
1025*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1026*a422084aSMark Johnston 	return (ret);
1027*a422084aSMark Johnston }
1028*a422084aSMark Johnston 
1029*a422084aSMark Johnston int
1030*a422084aSMark Johnston kmsan_subyte(volatile void *base, int byte)
1031*a422084aSMark Johnston {
1032*a422084aSMark Johnston 	int ret;
1033*a422084aSMark Johnston 
1034*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(byte), "subyte():args");
1035*a422084aSMark Johnston 	ret = subyte(base, byte);
1036*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1037*a422084aSMark Johnston 	return (ret);
1038*a422084aSMark Johnston }
1039*a422084aSMark Johnston 
1040*a422084aSMark Johnston int
1041*a422084aSMark Johnston kmsan_suword(volatile void *base, long word)
1042*a422084aSMark Johnston {
1043*a422084aSMark Johnston 	int ret;
1044*a422084aSMark Johnston 
1045*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(word), "suword():args");
1046*a422084aSMark Johnston 	ret = suword(base, word);
1047*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1048*a422084aSMark Johnston 	return (ret);
1049*a422084aSMark Johnston }
1050*a422084aSMark Johnston 
1051*a422084aSMark Johnston int
1052*a422084aSMark Johnston kmsan_suword16(volatile void *base, int word)
1053*a422084aSMark Johnston {
1054*a422084aSMark Johnston 	int ret;
1055*a422084aSMark Johnston 
1056*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(word), "suword16():args");
1057*a422084aSMark Johnston 	ret = suword16(base, word);
1058*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1059*a422084aSMark Johnston 	return (ret);
1060*a422084aSMark Johnston }
1061*a422084aSMark Johnston 
1062*a422084aSMark Johnston int
1063*a422084aSMark Johnston kmsan_suword32(volatile void *base, int32_t word)
1064*a422084aSMark Johnston {
1065*a422084aSMark Johnston 	int ret;
1066*a422084aSMark Johnston 
1067*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(word), "suword32():args");
1068*a422084aSMark Johnston 	ret = suword32(base, word);
1069*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1070*a422084aSMark Johnston 	return (ret);
1071*a422084aSMark Johnston }
1072*a422084aSMark Johnston 
1073*a422084aSMark Johnston int
1074*a422084aSMark Johnston kmsan_suword64(volatile void *base, int64_t word)
1075*a422084aSMark Johnston {
1076*a422084aSMark Johnston 	int ret;
1077*a422084aSMark Johnston 
1078*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(word), "suword64():args");
1079*a422084aSMark Johnston 	ret = suword64(base, word);
1080*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1081*a422084aSMark Johnston 	return (ret);
1082*a422084aSMark Johnston }
1083*a422084aSMark Johnston 
1084*a422084aSMark Johnston int
1085*a422084aSMark Johnston kmsan_casueword32(volatile uint32_t *base, uint32_t oldval, uint32_t *oldvalp,
1086*a422084aSMark Johnston     uint32_t newval)
1087*a422084aSMark Johnston {
1088*a422084aSMark Johnston 	int ret;
1089*a422084aSMark Johnston 
1090*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(oldval) + sizeof(oldvalp) +
1091*a422084aSMark Johnston 	    sizeof(newval), "casueword32(): args");
1092*a422084aSMark Johnston 	ret = casueword32(base, oldval, oldvalp, newval);
1093*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)oldvalp, KMSAN_STATE_INITED,
1094*a422084aSMark Johnston 	    sizeof(*oldvalp));
1095*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1096*a422084aSMark Johnston 	return (ret);
1097*a422084aSMark Johnston }
1098*a422084aSMark Johnston 
1099*a422084aSMark Johnston int
1100*a422084aSMark Johnston kmsan_casueword(volatile u_long *base, u_long oldval, u_long *oldvalp,
1101*a422084aSMark Johnston     u_long newval)
1102*a422084aSMark Johnston {
1103*a422084aSMark Johnston 	int ret;
1104*a422084aSMark Johnston 
1105*a422084aSMark Johnston 	kmsan_check_arg(sizeof(base) + sizeof(oldval) + sizeof(oldvalp) +
1106*a422084aSMark Johnston 	    sizeof(newval), "casueword32(): args");
1107*a422084aSMark Johnston 	ret = casueword(base, oldval, oldvalp, newval);
1108*a422084aSMark Johnston 	kmsan_shadow_fill((uintptr_t)oldvalp, KMSAN_STATE_INITED,
1109*a422084aSMark Johnston 	    sizeof(*oldvalp));
1110*a422084aSMark Johnston 	kmsan_init_ret(sizeof(int));
1111*a422084aSMark Johnston 	return (ret);
1112*a422084aSMark Johnston }
1113*a422084aSMark Johnston 
1114*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
1115*a422084aSMark Johnston 
1116*a422084aSMark Johnston #include <machine/atomic.h>
1117*a422084aSMark Johnston #include <sys/atomic_san.h>
1118*a422084aSMark Johnston 
1119*a422084aSMark Johnston #define _MSAN_ATOMIC_FUNC_ADD(name, type)				\
1120*a422084aSMark Johnston 	void kmsan_atomic_add_##name(volatile type *ptr, type val)	\
1121*a422084aSMark Johnston 	{								\
1122*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(val),		\
1123*a422084aSMark Johnston 		    "atomic_add_" #name "():args");			\
1124*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1125*a422084aSMark Johnston 		    "atomic_add_" #name "():ptr");			\
1126*a422084aSMark Johnston 		atomic_add_##name(ptr, val);				\
1127*a422084aSMark Johnston 	}
1128*a422084aSMark Johnston 
1129*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_ADD(name, type)				\
1130*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_ADD(name, type)				\
1131*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_ADD(acq_##name, type)				\
1132*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_ADD(rel_##name, type)
1133*a422084aSMark Johnston 
1134*a422084aSMark Johnston #define _MSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
1135*a422084aSMark Johnston 	void kmsan_atomic_subtract_##name(volatile type *ptr, type val)	\
1136*a422084aSMark Johnston 	{								\
1137*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(val),		\
1138*a422084aSMark Johnston 		    "atomic_subtract_" #name "():args");		\
1139*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1140*a422084aSMark Johnston 		    "atomic_subtract_" #name "():ptr");			\
1141*a422084aSMark Johnston 		atomic_subtract_##name(ptr, val);			\
1142*a422084aSMark Johnston 	}
1143*a422084aSMark Johnston 
1144*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
1145*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_SUBTRACT(name, type)				\
1146*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_SUBTRACT(acq_##name, type)			\
1147*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_SUBTRACT(rel_##name, type)
1148*a422084aSMark Johnston 
1149*a422084aSMark Johnston #define _MSAN_ATOMIC_FUNC_SET(name, type)				\
1150*a422084aSMark Johnston 	void kmsan_atomic_set_##name(volatile type *ptr, type val)	\
1151*a422084aSMark Johnston 	{								\
1152*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(val),		\
1153*a422084aSMark Johnston 		    "atomic_set_" #name "():args");			\
1154*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1155*a422084aSMark Johnston 		    "atomic_set_" #name "():ptr");			\
1156*a422084aSMark Johnston 		atomic_set_##name(ptr, val);				\
1157*a422084aSMark Johnston 	}
1158*a422084aSMark Johnston 
1159*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_SET(name, type)				\
1160*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_SET(name, type)				\
1161*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_SET(acq_##name, type)				\
1162*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_SET(rel_##name, type)
1163*a422084aSMark Johnston 
1164*a422084aSMark Johnston #define _MSAN_ATOMIC_FUNC_CLEAR(name, type)				\
1165*a422084aSMark Johnston 	void kmsan_atomic_clear_##name(volatile type *ptr, type val)	\
1166*a422084aSMark Johnston 	{								\
1167*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(val),		\
1168*a422084aSMark Johnston 		    "atomic_clear_" #name "():args");			\
1169*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1170*a422084aSMark Johnston 		    "atomic_clear_" #name "():ptr");			\
1171*a422084aSMark Johnston 		atomic_clear_##name(ptr, val);				\
1172*a422084aSMark Johnston 	}
1173*a422084aSMark Johnston 
1174*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_CLEAR(name, type)				\
1175*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_CLEAR(name, type)				\
1176*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_CLEAR(acq_##name, type)			\
1177*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_CLEAR(rel_##name, type)
1178*a422084aSMark Johnston 
1179*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_FETCHADD(name, type)				\
1180*a422084aSMark Johnston 	type kmsan_atomic_fetchadd_##name(volatile type *ptr, type val)	\
1181*a422084aSMark Johnston 	{								\
1182*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(val),		\
1183*a422084aSMark Johnston 		    "atomic_fetchadd_" #name "():args");		\
1184*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1185*a422084aSMark Johnston 		    "atomic_fetchadd_" #name "():ptr");			\
1186*a422084aSMark Johnston 		kmsan_init_ret(sizeof(type));				\
1187*a422084aSMark Johnston 		return (atomic_fetchadd_##name(ptr, val));		\
1188*a422084aSMark Johnston 	}
1189*a422084aSMark Johnston 
1190*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_READANDCLEAR(name, type)			\
1191*a422084aSMark Johnston 	type kmsan_atomic_readandclear_##name(volatile type *ptr)	\
1192*a422084aSMark Johnston 	{								\
1193*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr),				\
1194*a422084aSMark Johnston 		    "atomic_readandclear_" #name "():args");		\
1195*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1196*a422084aSMark Johnston 		    "atomic_readandclear_" #name "():ptr");		\
1197*a422084aSMark Johnston 		kmsan_init_ret(sizeof(type));				\
1198*a422084aSMark Johnston 		return (atomic_readandclear_##name(ptr));		\
1199*a422084aSMark Johnston 	}
1200*a422084aSMark Johnston 
1201*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_TESTANDCLEAR(name, type)			\
1202*a422084aSMark Johnston 	int kmsan_atomic_testandclear_##name(volatile type *ptr, u_int v) \
1203*a422084aSMark Johnston 	{								\
1204*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(v),		\
1205*a422084aSMark Johnston 		    "atomic_testandclear_" #name "():args");		\
1206*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1207*a422084aSMark Johnston 		    "atomic_testandclear_" #name "():ptr");		\
1208*a422084aSMark Johnston 		kmsan_init_ret(sizeof(int));				\
1209*a422084aSMark Johnston 		return (atomic_testandclear_##name(ptr, v));		\
1210*a422084aSMark Johnston 	}
1211*a422084aSMark Johnston 
1212*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_TESTANDSET(name, type)				\
1213*a422084aSMark Johnston 	int kmsan_atomic_testandset_##name(volatile type *ptr, u_int v) \
1214*a422084aSMark Johnston 	{								\
1215*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(v),		\
1216*a422084aSMark Johnston 		    "atomic_testandset_" #name "():args");		\
1217*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1218*a422084aSMark Johnston 		    "atomic_testandset_" #name "():ptr");		\
1219*a422084aSMark Johnston 		kmsan_init_ret(sizeof(int));				\
1220*a422084aSMark Johnston 		return (atomic_testandset_##name(ptr, v));		\
1221*a422084aSMark Johnston 	}
1222*a422084aSMark Johnston 
1223*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_SWAP(name, type)				\
1224*a422084aSMark Johnston 	type kmsan_atomic_swap_##name(volatile type *ptr, type val)	\
1225*a422084aSMark Johnston 	{								\
1226*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(val),		\
1227*a422084aSMark Johnston 		    "atomic_swap_" #name "():args");			\
1228*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1229*a422084aSMark Johnston 		    "atomic_swap_" #name "():ptr");			\
1230*a422084aSMark Johnston 		kmsan_init_ret(sizeof(type));				\
1231*a422084aSMark Johnston 		return (atomic_swap_##name(ptr, val));			\
1232*a422084aSMark Johnston 	}
1233*a422084aSMark Johnston 
1234*a422084aSMark Johnston #define _MSAN_ATOMIC_FUNC_CMPSET(name, type)				\
1235*a422084aSMark Johnston 	int kmsan_atomic_cmpset_##name(volatile type *ptr, type oval,	\
1236*a422084aSMark Johnston 	    type nval)							\
1237*a422084aSMark Johnston 	{								\
1238*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(oval) +		\
1239*a422084aSMark Johnston 		    sizeof(nval), "atomic_cmpset_" #name "():args");	\
1240*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1241*a422084aSMark Johnston 		    "atomic_cmpset_" #name "():ptr");			\
1242*a422084aSMark Johnston 		kmsan_init_ret(sizeof(int));				\
1243*a422084aSMark Johnston 		return (atomic_cmpset_##name(ptr, oval, nval));		\
1244*a422084aSMark Johnston 	}
1245*a422084aSMark Johnston 
1246*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_CMPSET(name, type)				\
1247*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_CMPSET(name, type)				\
1248*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_CMPSET(acq_##name, type)			\
1249*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_CMPSET(rel_##name, type)
1250*a422084aSMark Johnston 
1251*a422084aSMark Johnston #define _MSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
1252*a422084aSMark Johnston 	int kmsan_atomic_fcmpset_##name(volatile type *ptr, type *oval,	\
1253*a422084aSMark Johnston 	    type nval)							\
1254*a422084aSMark Johnston 	{								\
1255*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(oval) +		\
1256*a422084aSMark Johnston 		    sizeof(nval), "atomic_fcmpset_" #name "():args");	\
1257*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1258*a422084aSMark Johnston 		    "atomic_fcmpset_" #name "():ptr");			\
1259*a422084aSMark Johnston 		kmsan_init_ret(sizeof(int));				\
1260*a422084aSMark Johnston 		return (atomic_fcmpset_##name(ptr, oval, nval));	\
1261*a422084aSMark Johnston 	}
1262*a422084aSMark Johnston 
1263*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
1264*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_FCMPSET(name, type)				\
1265*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_FCMPSET(acq_##name, type)			\
1266*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_FCMPSET(rel_##name, type)
1267*a422084aSMark Johnston 
1268*a422084aSMark Johnston #define MSAN_ATOMIC_FUNC_THREAD_FENCE(name)				\
1269*a422084aSMark Johnston 	void kmsan_atomic_thread_fence_##name(void)			\
1270*a422084aSMark Johnston 	{								\
1271*a422084aSMark Johnston 		atomic_thread_fence_##name();				\
1272*a422084aSMark Johnston 	}
1273*a422084aSMark Johnston 
1274*a422084aSMark Johnston #define	_MSAN_ATOMIC_FUNC_LOAD(name, type)				\
1275*a422084aSMark Johnston 	type kmsan_atomic_load_##name(volatile type *ptr)		\
1276*a422084aSMark Johnston 	{								\
1277*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr),				\
1278*a422084aSMark Johnston 		    "atomic_load_" #name "():args");			\
1279*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)ptr, sizeof(type),	\
1280*a422084aSMark Johnston 		    "atomic_load_" #name "():ptr");			\
1281*a422084aSMark Johnston 		kmsan_init_ret(sizeof(type));				\
1282*a422084aSMark Johnston 		return (atomic_load_##name(ptr));			\
1283*a422084aSMark Johnston 	}
1284*a422084aSMark Johnston 
1285*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_LOAD(name, type)				\
1286*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_LOAD(name, type)				\
1287*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_LOAD(acq_##name, type)
1288*a422084aSMark Johnston 
1289*a422084aSMark Johnston #define	_MSAN_ATOMIC_FUNC_STORE(name, type)				\
1290*a422084aSMark Johnston 	void kmsan_atomic_store_##name(volatile type *ptr, type val)	\
1291*a422084aSMark Johnston 	{								\
1292*a422084aSMark Johnston 		kmsan_check_arg(sizeof(ptr) + sizeof(val),		\
1293*a422084aSMark Johnston 		    "atomic_store_" #name "():args");			\
1294*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)ptr, KMSAN_STATE_INITED,	\
1295*a422084aSMark Johnston 		    sizeof(type));					\
1296*a422084aSMark Johnston 		atomic_store_##name(ptr, val);				\
1297*a422084aSMark Johnston 	}
1298*a422084aSMark Johnston 
1299*a422084aSMark Johnston #define	MSAN_ATOMIC_FUNC_STORE(name, type)				\
1300*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_STORE(name, type)				\
1301*a422084aSMark Johnston 	_MSAN_ATOMIC_FUNC_STORE(rel_##name, type)
1302*a422084aSMark Johnston 
1303*a422084aSMark Johnston MSAN_ATOMIC_FUNC_ADD(8, uint8_t);
1304*a422084aSMark Johnston MSAN_ATOMIC_FUNC_ADD(16, uint16_t);
1305*a422084aSMark Johnston MSAN_ATOMIC_FUNC_ADD(32, uint32_t);
1306*a422084aSMark Johnston MSAN_ATOMIC_FUNC_ADD(64, uint64_t);
1307*a422084aSMark Johnston MSAN_ATOMIC_FUNC_ADD(int, u_int);
1308*a422084aSMark Johnston MSAN_ATOMIC_FUNC_ADD(long, u_long);
1309*a422084aSMark Johnston MSAN_ATOMIC_FUNC_ADD(ptr, uintptr_t);
1310*a422084aSMark Johnston 
1311*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SUBTRACT(8, uint8_t);
1312*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SUBTRACT(16, uint16_t);
1313*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SUBTRACT(32, uint32_t);
1314*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SUBTRACT(64, uint64_t);
1315*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SUBTRACT(int, u_int);
1316*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SUBTRACT(long, u_long);
1317*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SUBTRACT(ptr, uintptr_t);
1318*a422084aSMark Johnston 
1319*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SET(8, uint8_t);
1320*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SET(16, uint16_t);
1321*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SET(32, uint32_t);
1322*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SET(64, uint64_t);
1323*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SET(int, u_int);
1324*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SET(long, u_long);
1325*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SET(ptr, uintptr_t);
1326*a422084aSMark Johnston 
1327*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CLEAR(8, uint8_t);
1328*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CLEAR(16, uint16_t);
1329*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CLEAR(32, uint32_t);
1330*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CLEAR(64, uint64_t);
1331*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CLEAR(int, u_int);
1332*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CLEAR(long, u_long);
1333*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CLEAR(ptr, uintptr_t);
1334*a422084aSMark Johnston 
1335*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FETCHADD(32, uint32_t);
1336*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FETCHADD(64, uint64_t);
1337*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FETCHADD(int, u_int);
1338*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FETCHADD(long, u_long);
1339*a422084aSMark Johnston 
1340*a422084aSMark Johnston MSAN_ATOMIC_FUNC_READANDCLEAR(32, uint32_t);
1341*a422084aSMark Johnston MSAN_ATOMIC_FUNC_READANDCLEAR(64, uint64_t);
1342*a422084aSMark Johnston MSAN_ATOMIC_FUNC_READANDCLEAR(int, u_int);
1343*a422084aSMark Johnston MSAN_ATOMIC_FUNC_READANDCLEAR(long, u_long);
1344*a422084aSMark Johnston MSAN_ATOMIC_FUNC_READANDCLEAR(ptr, uintptr_t);
1345*a422084aSMark Johnston 
1346*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDCLEAR(32, uint32_t);
1347*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDCLEAR(64, uint64_t);
1348*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDCLEAR(int, u_int);
1349*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDCLEAR(long, u_long);
1350*a422084aSMark Johnston 
1351*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDSET(32, uint32_t);
1352*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDSET(64, uint64_t);
1353*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDSET(int, u_int);
1354*a422084aSMark Johnston MSAN_ATOMIC_FUNC_TESTANDSET(long, u_long);
1355*a422084aSMark Johnston 
1356*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SWAP(32, uint32_t);
1357*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SWAP(64, uint64_t);
1358*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SWAP(int, u_int);
1359*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SWAP(long, u_long);
1360*a422084aSMark Johnston MSAN_ATOMIC_FUNC_SWAP(ptr, uintptr_t);
1361*a422084aSMark Johnston 
1362*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CMPSET(8, uint8_t);
1363*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CMPSET(16, uint16_t);
1364*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CMPSET(32, uint32_t);
1365*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CMPSET(64, uint64_t);
1366*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CMPSET(int, u_int);
1367*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CMPSET(long, u_long);
1368*a422084aSMark Johnston MSAN_ATOMIC_FUNC_CMPSET(ptr, uintptr_t);
1369*a422084aSMark Johnston 
1370*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FCMPSET(8, uint8_t);
1371*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FCMPSET(16, uint16_t);
1372*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FCMPSET(32, uint32_t);
1373*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FCMPSET(64, uint64_t);
1374*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FCMPSET(int, u_int);
1375*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FCMPSET(long, u_long);
1376*a422084aSMark Johnston MSAN_ATOMIC_FUNC_FCMPSET(ptr, uintptr_t);
1377*a422084aSMark Johnston 
1378*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(8, uint8_t);
1379*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(16, uint16_t);
1380*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(32, uint32_t);
1381*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(64, uint64_t);
1382*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(char, u_char);
1383*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(short, u_short);
1384*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(int, u_int);
1385*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(long, u_long);
1386*a422084aSMark Johnston MSAN_ATOMIC_FUNC_LOAD(ptr, uintptr_t);
1387*a422084aSMark Johnston 
1388*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(8, uint8_t);
1389*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(16, uint16_t);
1390*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(32, uint32_t);
1391*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(64, uint64_t);
1392*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(char, u_char);
1393*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(short, u_short);
1394*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(int, u_int);
1395*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(long, u_long);
1396*a422084aSMark Johnston MSAN_ATOMIC_FUNC_STORE(ptr, uintptr_t);
1397*a422084aSMark Johnston 
1398*a422084aSMark Johnston MSAN_ATOMIC_FUNC_THREAD_FENCE(acq);
1399*a422084aSMark Johnston MSAN_ATOMIC_FUNC_THREAD_FENCE(rel);
1400*a422084aSMark Johnston MSAN_ATOMIC_FUNC_THREAD_FENCE(acq_rel);
1401*a422084aSMark Johnston MSAN_ATOMIC_FUNC_THREAD_FENCE(seq_cst);
1402*a422084aSMark Johnston 
1403*a422084aSMark Johnston void
1404*a422084aSMark Johnston kmsan_atomic_interrupt_fence(void)
1405*a422084aSMark Johnston {
1406*a422084aSMark Johnston 	atomic_interrupt_fence();
1407*a422084aSMark Johnston }
1408*a422084aSMark Johnston 
1409*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
1410*a422084aSMark Johnston 
1411*a422084aSMark Johnston #include <sys/bus.h>
1412*a422084aSMark Johnston #include <machine/bus.h>
1413*a422084aSMark Johnston #include <sys/bus_san.h>
1414*a422084aSMark Johnston 
1415*a422084aSMark Johnston int
1416*a422084aSMark Johnston kmsan_bus_space_map(bus_space_tag_t tag, bus_addr_t hnd, bus_size_t size,
1417*a422084aSMark Johnston     int flags, bus_space_handle_t *handlep)
1418*a422084aSMark Johnston {
1419*a422084aSMark Johnston 	return (bus_space_map(tag, hnd, size, flags, handlep));
1420*a422084aSMark Johnston }
1421*a422084aSMark Johnston 
1422*a422084aSMark Johnston void
1423*a422084aSMark Johnston kmsan_bus_space_unmap(bus_space_tag_t tag, bus_space_handle_t hnd,
1424*a422084aSMark Johnston     bus_size_t size)
1425*a422084aSMark Johnston {
1426*a422084aSMark Johnston 	bus_space_unmap(tag, hnd, size);
1427*a422084aSMark Johnston }
1428*a422084aSMark Johnston 
1429*a422084aSMark Johnston int
1430*a422084aSMark Johnston kmsan_bus_space_subregion(bus_space_tag_t tag, bus_space_handle_t hnd,
1431*a422084aSMark Johnston     bus_size_t offset, bus_size_t size, bus_space_handle_t *handlep)
1432*a422084aSMark Johnston {
1433*a422084aSMark Johnston 	return (bus_space_subregion(tag, hnd, offset, size, handlep));
1434*a422084aSMark Johnston }
1435*a422084aSMark Johnston 
1436*a422084aSMark Johnston void
1437*a422084aSMark Johnston kmsan_bus_space_free(bus_space_tag_t tag, bus_space_handle_t hnd,
1438*a422084aSMark Johnston     bus_size_t size)
1439*a422084aSMark Johnston {
1440*a422084aSMark Johnston 	bus_space_free(tag, hnd, size);
1441*a422084aSMark Johnston }
1442*a422084aSMark Johnston 
1443*a422084aSMark Johnston void
1444*a422084aSMark Johnston kmsan_bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t hnd,
1445*a422084aSMark Johnston     bus_size_t offset, bus_size_t size, int flags)
1446*a422084aSMark Johnston {
1447*a422084aSMark Johnston 	bus_space_barrier(tag, hnd, offset, size, flags);
1448*a422084aSMark Johnston }
1449*a422084aSMark Johnston 
1450*a422084aSMark Johnston /* XXXMJ x86-specific */
1451*a422084aSMark Johnston #define MSAN_BUS_READ_FUNC(func, width, type)				\
1452*a422084aSMark Johnston 	type kmsan_bus_space_read##func##_##width(bus_space_tag_t tag,	\
1453*a422084aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t offset)			\
1454*a422084aSMark Johnston 	{								\
1455*a422084aSMark Johnston 		type ret;						\
1456*a422084aSMark Johnston 		if ((tag) != X86_BUS_SPACE_IO)				\
1457*a422084aSMark Johnston 			kmsan_shadow_fill((uintptr_t)(hnd + offset),	\
1458*a422084aSMark Johnston 			    KMSAN_STATE_INITED, (width));		\
1459*a422084aSMark Johnston 		ret = bus_space_read##func##_##width(tag, hnd, offset);	\
1460*a422084aSMark Johnston 		kmsan_init_ret(sizeof(type));				\
1461*a422084aSMark Johnston 		return (ret);						\
1462*a422084aSMark Johnston 	}								\
1463*a422084aSMark Johnston 
1464*a422084aSMark Johnston #define MSAN_BUS_READ_PTR_FUNC(func, width, type)			\
1465*a422084aSMark Johnston 	void kmsan_bus_space_read_##func##_##width(bus_space_tag_t tag,	\
1466*a422084aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t size, type *buf,		\
1467*a422084aSMark Johnston 	    bus_size_t count)						\
1468*a422084aSMark Johnston 	{								\
1469*a422084aSMark Johnston 		kmsan_shadow_fill((uintptr_t)buf, KMSAN_STATE_INITED,	\
1470*a422084aSMark Johnston 		    (width) * count);					\
1471*a422084aSMark Johnston 		bus_space_read_##func##_##width(tag, hnd, size, buf, 	\
1472*a422084aSMark Johnston 		    count);						\
1473*a422084aSMark Johnston 	}
1474*a422084aSMark Johnston 
1475*a422084aSMark Johnston MSAN_BUS_READ_FUNC(, 1, uint8_t)
1476*a422084aSMark Johnston MSAN_BUS_READ_FUNC(_stream, 1, uint8_t)
1477*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(multi, 1, uint8_t)
1478*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(multi_stream, 1, uint8_t)
1479*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(region, 1, uint8_t)
1480*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(region_stream, 1, uint8_t)
1481*a422084aSMark Johnston 
1482*a422084aSMark Johnston MSAN_BUS_READ_FUNC(, 2, uint16_t)
1483*a422084aSMark Johnston MSAN_BUS_READ_FUNC(_stream, 2, uint16_t)
1484*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(multi, 2, uint16_t)
1485*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(multi_stream, 2, uint16_t)
1486*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(region, 2, uint16_t)
1487*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(region_stream, 2, uint16_t)
1488*a422084aSMark Johnston 
1489*a422084aSMark Johnston MSAN_BUS_READ_FUNC(, 4, uint32_t)
1490*a422084aSMark Johnston MSAN_BUS_READ_FUNC(_stream, 4, uint32_t)
1491*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(multi, 4, uint32_t)
1492*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(multi_stream, 4, uint32_t)
1493*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(region, 4, uint32_t)
1494*a422084aSMark Johnston MSAN_BUS_READ_PTR_FUNC(region_stream, 4, uint32_t)
1495*a422084aSMark Johnston 
1496*a422084aSMark Johnston MSAN_BUS_READ_FUNC(, 8, uint64_t)
1497*a422084aSMark Johnston 
1498*a422084aSMark Johnston #define	MSAN_BUS_WRITE_FUNC(func, width, type)				\
1499*a422084aSMark Johnston 	void kmsan_bus_space_write##func##_##width(bus_space_tag_t tag,	\
1500*a422084aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t offset, type value)	\
1501*a422084aSMark Johnston 	{								\
1502*a422084aSMark Johnston 		bus_space_write##func##_##width(tag, hnd, offset, value);\
1503*a422084aSMark Johnston 	}								\
1504*a422084aSMark Johnston 
1505*a422084aSMark Johnston #define	MSAN_BUS_WRITE_PTR_FUNC(func, width, type)			\
1506*a422084aSMark Johnston 	void kmsan_bus_space_write_##func##_##width(bus_space_tag_t tag,\
1507*a422084aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t size, const type *buf,	\
1508*a422084aSMark Johnston 	    bus_size_t count)						\
1509*a422084aSMark Johnston 	{								\
1510*a422084aSMark Johnston 		kmsan_shadow_check((uintptr_t)buf, sizeof(type) * count,\
1511*a422084aSMark Johnston 		    "bus_space_write()");				\
1512*a422084aSMark Johnston 		bus_space_write_##func##_##width(tag, hnd, size, buf, 	\
1513*a422084aSMark Johnston 		    count);						\
1514*a422084aSMark Johnston 	}
1515*a422084aSMark Johnston 
1516*a422084aSMark Johnston MSAN_BUS_WRITE_FUNC(, 1, uint8_t)
1517*a422084aSMark Johnston MSAN_BUS_WRITE_FUNC(_stream, 1, uint8_t)
1518*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(multi, 1, uint8_t)
1519*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(multi_stream, 1, uint8_t)
1520*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(region, 1, uint8_t)
1521*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(region_stream, 1, uint8_t)
1522*a422084aSMark Johnston 
1523*a422084aSMark Johnston MSAN_BUS_WRITE_FUNC(, 2, uint16_t)
1524*a422084aSMark Johnston MSAN_BUS_WRITE_FUNC(_stream, 2, uint16_t)
1525*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(multi, 2, uint16_t)
1526*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(multi_stream, 2, uint16_t)
1527*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(region, 2, uint16_t)
1528*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(region_stream, 2, uint16_t)
1529*a422084aSMark Johnston 
1530*a422084aSMark Johnston MSAN_BUS_WRITE_FUNC(, 4, uint32_t)
1531*a422084aSMark Johnston MSAN_BUS_WRITE_FUNC(_stream, 4, uint32_t)
1532*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(multi, 4, uint32_t)
1533*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(multi_stream, 4, uint32_t)
1534*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(region, 4, uint32_t)
1535*a422084aSMark Johnston MSAN_BUS_WRITE_PTR_FUNC(region_stream, 4, uint32_t)
1536*a422084aSMark Johnston 
1537*a422084aSMark Johnston MSAN_BUS_WRITE_FUNC(, 8, uint64_t)
1538*a422084aSMark Johnston 
1539*a422084aSMark Johnston #define	MSAN_BUS_SET_FUNC(func, width, type)				\
1540*a422084aSMark Johnston 	void kmsan_bus_space_set_##func##_##width(bus_space_tag_t tag,	\
1541*a422084aSMark Johnston 	    bus_space_handle_t hnd, bus_size_t offset, type value,	\
1542*a422084aSMark Johnston 	    bus_size_t count)						\
1543*a422084aSMark Johnston 	{								\
1544*a422084aSMark Johnston 		bus_space_set_##func##_##width(tag, hnd, offset, value,	\
1545*a422084aSMark Johnston 		    count);						\
1546*a422084aSMark Johnston 	}
1547*a422084aSMark Johnston 
1548*a422084aSMark Johnston MSAN_BUS_SET_FUNC(multi, 1, uint8_t)
1549*a422084aSMark Johnston MSAN_BUS_SET_FUNC(region, 1, uint8_t)
1550*a422084aSMark Johnston MSAN_BUS_SET_FUNC(multi_stream, 1, uint8_t)
1551*a422084aSMark Johnston MSAN_BUS_SET_FUNC(region_stream, 1, uint8_t)
1552*a422084aSMark Johnston 
1553*a422084aSMark Johnston MSAN_BUS_SET_FUNC(multi, 2, uint16_t)
1554*a422084aSMark Johnston MSAN_BUS_SET_FUNC(region, 2, uint16_t)
1555*a422084aSMark Johnston MSAN_BUS_SET_FUNC(multi_stream, 2, uint16_t)
1556*a422084aSMark Johnston MSAN_BUS_SET_FUNC(region_stream, 2, uint16_t)
1557*a422084aSMark Johnston 
1558*a422084aSMark Johnston MSAN_BUS_SET_FUNC(multi, 4, uint32_t)
1559*a422084aSMark Johnston MSAN_BUS_SET_FUNC(region, 4, uint32_t)
1560*a422084aSMark Johnston MSAN_BUS_SET_FUNC(multi_stream, 4, uint32_t)
1561*a422084aSMark Johnston MSAN_BUS_SET_FUNC(region_stream, 4, uint32_t)
1562*a422084aSMark Johnston 
1563*a422084aSMark Johnston /* -------------------------------------------------------------------------- */
1564*a422084aSMark Johnston 
1565*a422084aSMark Johnston void
1566*a422084aSMark Johnston kmsan_bus_dmamap_sync(struct memdesc *desc, bus_dmasync_op_t op)
1567*a422084aSMark Johnston {
1568*a422084aSMark Johnston 	/*
1569*a422084aSMark Johnston 	 * Some drivers, e.g., nvme, use the same code path for loading device
1570*a422084aSMark Johnston 	 * read and write requests, and will thus specify both flags.  In this
1571*a422084aSMark Johnston 	 * case we should not do any checking since it will generally lead to
1572*a422084aSMark Johnston 	 * false positives.
1573*a422084aSMark Johnston 	 */
1574*a422084aSMark Johnston 	if ((op & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) ==
1575*a422084aSMark Johnston 	    BUS_DMASYNC_PREWRITE) {
1576*a422084aSMark Johnston 		switch (desc->md_type) {
1577*a422084aSMark Johnston 		case MEMDESC_VADDR:
1578*a422084aSMark Johnston 			kmsan_check(desc->u.md_vaddr, desc->md_opaque,
1579*a422084aSMark Johnston 			    "dmasync");
1580*a422084aSMark Johnston 			break;
1581*a422084aSMark Johnston 		case MEMDESC_BIO:
1582*a422084aSMark Johnston 			kmsan_check_bio(desc->u.md_bio, "dmasync");
1583*a422084aSMark Johnston 			break;
1584*a422084aSMark Johnston 		case MEMDESC_MBUF:
1585*a422084aSMark Johnston 			kmsan_check_mbuf(desc->u.md_mbuf, "dmasync");
1586*a422084aSMark Johnston 			break;
1587*a422084aSMark Johnston 		case MEMDESC_CCB:
1588*a422084aSMark Johnston 			kmsan_check_ccb(desc->u.md_ccb, "dmasync");
1589*a422084aSMark Johnston 			break;
1590*a422084aSMark Johnston 		case 0:
1591*a422084aSMark Johnston 			break;
1592*a422084aSMark Johnston 		default:
1593*a422084aSMark Johnston 			kmsan_panic("%s: unhandled memdesc type %d", __func__,
1594*a422084aSMark Johnston 			    desc->md_type);
1595*a422084aSMark Johnston 		}
1596*a422084aSMark Johnston 	}
1597*a422084aSMark Johnston 	if ((op & BUS_DMASYNC_POSTREAD) != 0) {
1598*a422084aSMark Johnston 		switch (desc->md_type) {
1599*a422084aSMark Johnston 		case MEMDESC_VADDR:
1600*a422084aSMark Johnston 			kmsan_mark(desc->u.md_vaddr, desc->md_opaque,
1601*a422084aSMark Johnston 			    KMSAN_STATE_INITED);
1602*a422084aSMark Johnston 			break;
1603*a422084aSMark Johnston 		case MEMDESC_BIO:
1604*a422084aSMark Johnston 			kmsan_mark_bio(desc->u.md_bio, KMSAN_STATE_INITED);
1605*a422084aSMark Johnston 			break;
1606*a422084aSMark Johnston 		case MEMDESC_MBUF:
1607*a422084aSMark Johnston 			kmsan_mark_mbuf(desc->u.md_mbuf, KMSAN_STATE_INITED);
1608*a422084aSMark Johnston 			break;
1609*a422084aSMark Johnston 		case MEMDESC_CCB:
1610*a422084aSMark Johnston 			kmsan_mark_ccb(desc->u.md_ccb, KMSAN_STATE_INITED);
1611*a422084aSMark Johnston 			break;
1612*a422084aSMark Johnston 		case 0:
1613*a422084aSMark Johnston 			break;
1614*a422084aSMark Johnston 		default:
1615*a422084aSMark Johnston 			kmsan_panic("%s: unhandled memdesc type %d", __func__,
1616*a422084aSMark Johnston 			    desc->md_type);
1617*a422084aSMark Johnston 		}
1618*a422084aSMark Johnston 	}
1619*a422084aSMark Johnston }
1620