1 /* $NetBSD: csan.h,v 1.5 2024/12/04 20:27:39 alnsn Exp $ */ 2 3 /* 4 * Copyright (c) 2019-2020 Maxime Villard, m00nbsd.net 5 * All rights reserved. 6 * 7 * This code is part of the KCSAN subsystem of the NetBSD kernel. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/ksyms.h> 32 #include <uvm/uvm.h> 33 #include <amd64/pmap.h> 34 #include <x86/cpufunc.h> 35 36 #include <machine/pmap_private.h> 37 38 static inline bool 39 kcsan_md_unsupported(vaddr_t addr) 40 { 41 return (addr >= (vaddr_t)PTE_BASE && 42 addr < ((vaddr_t)PTE_BASE + NBPD_L4)); 43 } 44 45 static inline bool 46 kcsan_md_is_avail(void) 47 { 48 return true; 49 } 50 51 static inline void 52 kcsan_md_disable_intrs(uint64_t *state) 53 { 54 *state = x86_read_psl(); 55 x86_disable_intr(); 56 } 57 58 static inline void 59 kcsan_md_enable_intrs(uint64_t *state) 60 { 61 x86_write_psl(*state); 62 } 63 64 static inline void 65 kcsan_md_delay(uint64_t us) 66 { 67 DELAY(us); 68 } 69 70 static inline bool 71 __md_unwind_end(const char *name) 72 { 73 if (!strcmp(name, "syscall") || 74 !strcmp(name, "alltraps") || 75 !strcmp(name, "handle_syscall") || 76 !strncmp(name, "Xtrap", 5) || 77 !strncmp(name, "Xintr", 5) || 78 !strncmp(name, "Xhandle", 7) || 79 !strncmp(name, "Xresume", 7) || 80 !strncmp(name, "Xstray", 6) || 81 !strncmp(name, "Xhold", 5) || 82 !strncmp(name, "Xrecurse", 8) || 83 !strcmp(name, "Xdoreti") || 84 !strncmp(name, "Xsoft", 5)) { 85 return true; 86 } 87 88 return false; 89 } 90 91 static void 92 kcsan_md_unwind(void) 93 { 94 uint64_t *rbp, rip; 95 const char *mod; 96 const char *sym; 97 size_t nsym; 98 int error; 99 100 rbp = (uint64_t *)__builtin_frame_address(0); 101 nsym = 0; 102 103 while (1) { 104 /* 8(%rbp) contains the saved %rip. */ 105 rip = *(rbp + 1); 106 107 if (rip < KERNBASE) { 108 break; 109 } 110 error = ksyms_getname(&mod, &sym, (vaddr_t)rip, KSYMS_PROC); 111 if (error) { 112 break; 113 } 114 printf("#%zu %p in %s <%s>\n", nsym, (void *)rip, sym, mod); 115 if (__md_unwind_end(sym)) { 116 break; 117 } 118 119 rbp = (uint64_t *)*(rbp); 120 if (rbp == 0) { 121 break; 122 } 123 nsym++; 124 125 if (nsym >= 15) { 126 break; 127 } 128 } 129 } 130