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