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