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