1 /* $OpenBSD: dt_prov_static.c,v 1.24 2025/01/09 17:43:33 mvs 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, socket, "void *", "int", "int");
104 DT_STATIC_PROBE3(refcnt, syncache, "void *", "int", "int");
105 DT_STATIC_PROBE3(refcnt, tdb, "void *", "int", "int");
106
107 /*
108 * List of all static probes
109 */
110 struct dt_probe *const dtps_static[] = {
111 /* Scheduler */
112 &_DT_STATIC_P(sched, dequeue),
113 &_DT_STATIC_P(sched, enqueue),
114 &_DT_STATIC_P(sched, fork),
115 &_DT_STATIC_P(sched, off__cpu),
116 &_DT_STATIC_P(sched, on__cpu),
117 &_DT_STATIC_P(sched, remain__cpu),
118 &_DT_STATIC_P(sched, sleep),
119 &_DT_STATIC_P(sched, steal),
120 &_DT_STATIC_P(sched, unsleep),
121 &_DT_STATIC_P(sched, wakeup),
122 /* Raw syscalls */
123 &_DT_STATIC_P(raw_syscalls, sys_enter),
124 &_DT_STATIC_P(raw_syscalls, sys_exit),
125 /* UVM */
126 &_DT_STATIC_P(uvm, fault),
127 &_DT_STATIC_P(uvm, map_insert),
128 &_DT_STATIC_P(uvm, map_remove),
129 &_DT_STATIC_P(uvm, malloc),
130 &_DT_STATIC_P(uvm, free),
131 &_DT_STATIC_P(uvm, pool_get),
132 &_DT_STATIC_P(uvm, pool_put),
133 /* VFS */
134 &_DT_STATIC_P(vfs, bufcache_rel),
135 &_DT_STATIC_P(vfs, bufcache_take),
136 &_DT_STATIC_P(vfs, cleaner),
137 #ifdef __amd64__
138 /* VMM */
139 &_DT_STATIC_P(vmm, guest_enter),
140 &_DT_STATIC_P(vmm, guest_exit),
141 &_DT_STATIC_P(vmm, inout),
142 #endif /* __amd64__ */
143 /* SMR */
144 &_DT_STATIC_P(smr, call),
145 &_DT_STATIC_P(smr, called),
146 &_DT_STATIC_P(smr, barrier_enter),
147 &_DT_STATIC_P(smr, barrier_exit),
148 &_DT_STATIC_P(smr, wakeup),
149 &_DT_STATIC_P(smr, thread),
150 /* refcnt */
151 &_DT_STATIC_P(refcnt, none),
152 &_DT_STATIC_P(refcnt, ethmulti),
153 &_DT_STATIC_P(refcnt, ifaddr),
154 &_DT_STATIC_P(refcnt, ifmaddr),
155 &_DT_STATIC_P(refcnt, inpcb),
156 &_DT_STATIC_P(refcnt, rtentry),
157 &_DT_STATIC_P(refcnt, socket),
158 &_DT_STATIC_P(refcnt, syncache),
159 &_DT_STATIC_P(refcnt, tdb),
160 };
161
162 struct dt_probe *const *dtps_index_refcnt;
163
164 int
dt_prov_static_init(void)165 dt_prov_static_init(void)
166 {
167 int i;
168
169 for (i = 0; i < nitems(dtps_static); i++) {
170 if (dtps_static[i] == &_DT_STATIC_P(refcnt, none))
171 dtps_index_refcnt = &dtps_static[i];
172 dt_dev_register_probe(dtps_static[i]);
173 }
174
175 return i;
176 }
177
178 int
dt_prov_static_alloc(struct dt_probe * dtp,struct dt_softc * sc,struct dt_pcb_list * plist,struct dtioc_req * dtrq)179 dt_prov_static_alloc(struct dt_probe *dtp, struct dt_softc *sc,
180 struct dt_pcb_list *plist, struct dtioc_req *dtrq)
181 {
182 struct dt_pcb *dp;
183
184 KASSERT(TAILQ_EMPTY(plist));
185
186 dp = dt_pcb_alloc(dtp, sc);
187 if (dp == NULL)
188 return ENOMEM;
189
190 dp->dp_evtflags = dtrq->dtrq_evtflags;
191 TAILQ_INSERT_HEAD(plist, dp, dp_snext);
192
193 return 0;
194 }
195
196 int
dt_prov_static_hook(struct dt_provider * dtpv,...)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