csan.h revision 1.5 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