xref: /openbsd/sys/dev/dt/dt_prov_static.c (revision d415bd75)
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