1 /* $OpenBSD: dt_prov_static.c,v 1.22 2023/08/28 14:50:01 bluhm Exp $ */ 2 3 /* 4 * Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/systm.h> 21 #include <sys/param.h> 22 #include <sys/tracepoint.h> 23 24 #include <dev/dt/dtvar.h> 25 26 int dt_prov_static_alloc(struct dt_probe *, struct dt_softc *, 27 struct dt_pcb_list *, struct dtioc_req *); 28 int dt_prov_static_hook(struct dt_provider *, ...); 29 30 struct dt_provider dt_prov_static = { 31 .dtpv_name = "tracepoint", 32 .dtpv_alloc = dt_prov_static_alloc, 33 .dtpv_enter = dt_prov_static_hook, 34 .dtpv_dealloc = NULL, 35 }; 36 37 /* 38 * Scheduler 39 */ 40 DT_STATIC_PROBE2(sched, dequeue, "pid_t", "pid_t"); 41 DT_STATIC_PROBE2(sched, enqueue, "pid_t", "pid_t"); 42 DT_STATIC_PROBE3(sched, fork, "pid_t", "pid_t", "int"); 43 DT_STATIC_PROBE2(sched, off__cpu, "pid_t", "pid_t"); 44 DT_STATIC_PROBE0(sched, on__cpu); 45 DT_STATIC_PROBE0(sched, remain__cpu); 46 DT_STATIC_PROBE0(sched, sleep); 47 DT_STATIC_PROBE3(sched, steal, "pid_t", "pid_t", "int"); 48 DT_STATIC_PROBE2(sched, unsleep, "pid_t", "pid_t"); 49 DT_STATIC_PROBE3(sched, wakeup, "pid_t", "pid_t", "int"); 50 51 /* 52 * Raw syscalls 53 */ 54 DT_STATIC_PROBE1(raw_syscalls, sys_enter, "register_t"); 55 DT_STATIC_PROBE1(raw_syscalls, sys_exit, "register_t"); 56 57 /* 58 * UVM 59 */ 60 DT_STATIC_PROBE3(uvm, fault, "vaddr_t", "vm_fault_t", "vm_prot_t"); 61 DT_STATIC_PROBE3(uvm, map_insert, "vaddr_t", "vaddr_t", "vm_prot_t"); 62 DT_STATIC_PROBE3(uvm, map_remove, "vaddr_t", "vaddr_t", "vm_prot_t"); 63 DT_STATIC_PROBE4(uvm, malloc, "int", "void *", "size_t", "int"); 64 DT_STATIC_PROBE3(uvm, free, "int", "void *", "size_t"); 65 DT_STATIC_PROBE3(uvm, pool_get, "void *", "void *", "int"); 66 DT_STATIC_PROBE2(uvm, pool_put, "void *", "void *"); 67 68 /* 69 * VFS 70 */ 71 DT_STATIC_PROBE3(vfs, bufcache_rel, "long", "int", "int64_t"); 72 DT_STATIC_PROBE3(vfs, bufcache_take, "long", "int", "int64_t"); 73 DT_STATIC_PROBE4(vfs, cleaner, "long", "int", "long", "long"); 74 75 #ifdef __amd64__ 76 /* 77 * VMM 78 */ 79 DT_STATIC_PROBE2(vmm, guest_enter, "void *", "void *"); 80 DT_STATIC_PROBE3(vmm, guest_exit, "void *", "void *", "uint64_t"); 81 DT_STATIC_PROBE4(vmm, inout, "void *", "uint16_t", "uint8_t", "uint32_t"); 82 #endif /* __amd64__ */ 83 84 /* 85 * SMR 86 */ 87 DT_STATIC_PROBE3(smr, call, "void *", "void *", "int"); 88 DT_STATIC_PROBE2(smr, called, "void *", "void *"); 89 DT_STATIC_PROBE1(smr, barrier_enter, "int"); 90 DT_STATIC_PROBE1(smr, barrier_exit, "int"); 91 DT_STATIC_PROBE0(smr, wakeup); 92 DT_STATIC_PROBE2(smr, thread, "uint64_t", "uint64_t"); 93 94 /* 95 * reference counting, keep in sync with sys/refcnt.h 96 */ 97 DT_STATIC_PROBE0(refcnt, none); 98 DT_STATIC_PROBE3(refcnt, ethmulti, "void *", "int", "int"); 99 DT_STATIC_PROBE3(refcnt, ifaddr, "void *", "int", "int"); 100 DT_STATIC_PROBE3(refcnt, ifmaddr, "void *", "int", "int"); 101 DT_STATIC_PROBE3(refcnt, inpcb, "void *", "int", "int"); 102 DT_STATIC_PROBE3(refcnt, rtentry, "void *", "int", "int"); 103 DT_STATIC_PROBE3(refcnt, syncache, "void *", "int", "int"); 104 DT_STATIC_PROBE3(refcnt, tdb, "void *", "int", "int"); 105 106 /* 107 * List of all static probes 108 */ 109 struct dt_probe *const dtps_static[] = { 110 /* Scheduler */ 111 &_DT_STATIC_P(sched, dequeue), 112 &_DT_STATIC_P(sched, enqueue), 113 &_DT_STATIC_P(sched, fork), 114 &_DT_STATIC_P(sched, off__cpu), 115 &_DT_STATIC_P(sched, on__cpu), 116 &_DT_STATIC_P(sched, remain__cpu), 117 &_DT_STATIC_P(sched, sleep), 118 &_DT_STATIC_P(sched, steal), 119 &_DT_STATIC_P(sched, unsleep), 120 &_DT_STATIC_P(sched, wakeup), 121 /* Raw syscalls */ 122 &_DT_STATIC_P(raw_syscalls, sys_enter), 123 &_DT_STATIC_P(raw_syscalls, sys_exit), 124 /* UVM */ 125 &_DT_STATIC_P(uvm, fault), 126 &_DT_STATIC_P(uvm, map_insert), 127 &_DT_STATIC_P(uvm, map_remove), 128 &_DT_STATIC_P(uvm, malloc), 129 &_DT_STATIC_P(uvm, free), 130 &_DT_STATIC_P(uvm, pool_get), 131 &_DT_STATIC_P(uvm, pool_put), 132 /* VFS */ 133 &_DT_STATIC_P(vfs, bufcache_rel), 134 &_DT_STATIC_P(vfs, bufcache_take), 135 &_DT_STATIC_P(vfs, cleaner), 136 #ifdef __amd64__ 137 /* VMM */ 138 &_DT_STATIC_P(vmm, guest_enter), 139 &_DT_STATIC_P(vmm, guest_exit), 140 &_DT_STATIC_P(vmm, inout), 141 #endif /* __amd64__ */ 142 /* SMR */ 143 &_DT_STATIC_P(smr, call), 144 &_DT_STATIC_P(smr, called), 145 &_DT_STATIC_P(smr, barrier_enter), 146 &_DT_STATIC_P(smr, barrier_exit), 147 &_DT_STATIC_P(smr, wakeup), 148 &_DT_STATIC_P(smr, thread), 149 /* refcnt */ 150 &_DT_STATIC_P(refcnt, none), 151 &_DT_STATIC_P(refcnt, ethmulti), 152 &_DT_STATIC_P(refcnt, ifaddr), 153 &_DT_STATIC_P(refcnt, ifmaddr), 154 &_DT_STATIC_P(refcnt, inpcb), 155 &_DT_STATIC_P(refcnt, rtentry), 156 &_DT_STATIC_P(refcnt, syncache), 157 &_DT_STATIC_P(refcnt, tdb), 158 }; 159 160 struct dt_probe *const *dtps_index_refcnt; 161 162 int 163 dt_prov_static_init(void) 164 { 165 int i; 166 167 for (i = 0; i < nitems(dtps_static); i++) { 168 if (dtps_static[i] == &_DT_STATIC_P(refcnt, none)) 169 dtps_index_refcnt = &dtps_static[i]; 170 dt_dev_register_probe(dtps_static[i]); 171 } 172 173 return i; 174 } 175 176 int 177 dt_prov_static_alloc(struct dt_probe *dtp, struct dt_softc *sc, 178 struct dt_pcb_list *plist, struct dtioc_req *dtrq) 179 { 180 struct dt_pcb *dp; 181 182 KASSERT(dtioc_req_isvalid(dtrq)); 183 KASSERT(TAILQ_EMPTY(plist)); 184 185 dp = dt_pcb_alloc(dtp, sc); 186 if (dp == NULL) 187 return ENOMEM; 188 189 dp->dp_filter = dtrq->dtrq_filter; 190 dp->dp_evtflags = dtrq->dtrq_evtflags; 191 TAILQ_INSERT_HEAD(plist, dp, dp_snext); 192 193 return 0; 194 } 195 196 int 197 dt_prov_static_hook(struct dt_provider *dtpv, ...) 198 { 199 struct dt_probe *dtp; 200 struct dt_pcb *dp; 201 uintptr_t args[5]; 202 va_list ap; 203 int i; 204 205 va_start(ap, dtpv); 206 dtp = va_arg(ap, struct dt_probe *); 207 for (i = 0; i < dtp->dtp_nargs; i++) { 208 args[i] = va_arg(ap, uintptr_t); 209 } 210 va_end(ap); 211 212 KASSERT(dtpv == dtp->dtp_prov); 213 214 smr_read_enter(); 215 SMR_SLIST_FOREACH(dp, &dtp->dtp_pcbs, dp_pnext) { 216 struct dt_evt *dtev; 217 218 dtev = dt_pcb_ring_get(dp, 0); 219 if (dtev == NULL) 220 continue; 221 222 dtev->dtev_args[0] = args[0]; 223 dtev->dtev_args[1] = args[1]; 224 dtev->dtev_args[2] = args[2]; 225 dtev->dtev_args[3] = args[3]; 226 dtev->dtev_args[4] = args[4]; 227 228 dt_pcb_ring_consume(dp, dtev); 229 } 230 smr_read_leave(); 231 return 1; 232 } 233