xref: /openbsd/sys/dev/dt/dt_prov_static.c (revision 5a38ef86)
1 /*	$OpenBSD: dt_prov_static.c,v 1.11 2021/11/24 09:47:49 claudio 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_PROBE2(sched, off__cpu, "pid_t", "pid_t");
43 DT_STATIC_PROBE0(sched, on__cpu);
44 DT_STATIC_PROBE0(sched, remain__cpu);
45 DT_STATIC_PROBE0(sched, sleep);
46 DT_STATIC_PROBE0(sched, wakeup);
47 
48 /*
49  * Raw syscalls
50  */
51 DT_STATIC_PROBE1(raw_syscalls, sys_enter, "register_t");
52 DT_STATIC_PROBE1(raw_syscalls, sys_exit, "register_t");
53 
54 /*
55  * UVM
56  */
57 DT_STATIC_PROBE3(uvm, fault, "vaddr_t", "vm_fault_t", "vm_prot_t");
58 DT_STATIC_PROBE3(uvm, map_insert, "vaddr_t", "vaddr_t", "vm_prot_t");
59 DT_STATIC_PROBE3(uvm, map_remove, "vaddr_t", "vaddr_t", "vm_prot_t");
60 DT_STATIC_PROBE4(uvm, malloc, "int", "void *", "size_t", "int");
61 DT_STATIC_PROBE3(uvm, free, "int", "void *", "size_t");
62 DT_STATIC_PROBE3(uvm, pool_get, "void *", "void *", "int");
63 DT_STATIC_PROBE2(uvm, pool_put, "void *", "void *");
64 
65 /*
66  * VFS
67  */
68 DT_STATIC_PROBE3(vfs, bufcache_rel, "long", "int", "int64_t");
69 DT_STATIC_PROBE3(vfs, bufcache_take, "long", "int", "int64_t");
70 DT_STATIC_PROBE4(vfs, cleaner, "long", "int", "long", "long");
71 
72 /*
73  * VMM
74  */
75 DT_STATIC_PROBE2(vmm, guest_enter, "void *", "void *");
76 DT_STATIC_PROBE3(vmm, guest_exit, "void *", "void *", "uint64_t");
77 
78 /*
79  * SMR
80  */
81 DT_STATIC_PROBE3(smr, call, "void *", "void *", "int");
82 DT_STATIC_PROBE2(smr, called, "void *", "void *");
83 DT_STATIC_PROBE1(smr, barrier_enter, "int");
84 DT_STATIC_PROBE1(smr, barrier_exit, "int");
85 DT_STATIC_PROBE0(smr, wakeup);
86 DT_STATIC_PROBE2(smr, thread, "uint64_t", "uint64_t");
87 
88 
89 /*
90  * List of all static probes
91  */
92 struct dt_probe *dtps_static[] = {
93 	/* Scheduler */
94 	&_DT_STATIC_P(sched, dequeue),
95 	&_DT_STATIC_P(sched, enqueue),
96 	&_DT_STATIC_P(sched, off__cpu),
97 	&_DT_STATIC_P(sched, on__cpu),
98 	&_DT_STATIC_P(sched, remain__cpu),
99 	&_DT_STATIC_P(sched, sleep),
100 	&_DT_STATIC_P(sched, wakeup),
101 	/* Raw syscalls */
102 	&_DT_STATIC_P(raw_syscalls, sys_enter),
103 	&_DT_STATIC_P(raw_syscalls, sys_exit),
104 	/* UVM */
105 	&_DT_STATIC_P(uvm, fault),
106 	&_DT_STATIC_P(uvm, map_insert),
107 	&_DT_STATIC_P(uvm, map_remove),
108 	&_DT_STATIC_P(uvm, malloc),
109 	&_DT_STATIC_P(uvm, free),
110 	&_DT_STATIC_P(uvm, pool_get),
111 	&_DT_STATIC_P(uvm, pool_put),
112 	/* VFS */
113 	&_DT_STATIC_P(vfs, bufcache_rel),
114 	&_DT_STATIC_P(vfs, bufcache_take),
115 	&_DT_STATIC_P(vfs, cleaner),
116 	/* VMM */
117 	&_DT_STATIC_P(vmm, guest_enter),
118 	&_DT_STATIC_P(vmm, guest_exit),
119 	/* SMR */
120 	&_DT_STATIC_P(smr, call),
121 	&_DT_STATIC_P(smr, called),
122 	&_DT_STATIC_P(smr, barrier_enter),
123 	&_DT_STATIC_P(smr, barrier_exit),
124 	&_DT_STATIC_P(smr, wakeup),
125 	&_DT_STATIC_P(smr, thread),
126 };
127 
128 int
129 dt_prov_static_init(void)
130 {
131 	int i;
132 
133 	for (i = 0; i < nitems(dtps_static); i++)
134 		dt_dev_register_probe(dtps_static[i]);
135 
136 	return i;
137 }
138 
139 int
140 dt_prov_static_alloc(struct dt_probe *dtp, struct dt_softc *sc,
141     struct dt_pcb_list *plist, struct dtioc_req *dtrq)
142 {
143 	struct dt_pcb *dp;
144 
145 	KASSERT(dtioc_req_isvalid(dtrq));
146 	KASSERT(TAILQ_EMPTY(plist));
147 
148 	dp = dt_pcb_alloc(dtp, sc);
149 	if (dp == NULL)
150 		return ENOMEM;
151 
152 	dp->dp_filter = dtrq->dtrq_filter;
153 	dp->dp_evtflags = dtrq->dtrq_evtflags;
154 	TAILQ_INSERT_HEAD(plist, dp, dp_snext);
155 
156 	return 0;
157 }
158 
159 int
160 dt_prov_static_hook(struct dt_provider *dtpv, ...)
161 {
162 	struct dt_probe *dtp;
163 	struct dt_pcb *dp;
164 	uintptr_t args[5];
165 	va_list ap;
166 	int i;
167 
168 	va_start(ap, dtpv);
169 	dtp = va_arg(ap, struct dt_probe *);
170 	for (i = 0; i < dtp->dtp_nargs; i++) {
171 		args[i] = va_arg(ap, uintptr_t);
172 	}
173 	va_end(ap);
174 
175 	KASSERT(dtpv == dtp->dtp_prov);
176 
177 	smr_read_enter();
178 	SMR_SLIST_FOREACH(dp, &dtp->dtp_pcbs, dp_pnext) {
179 		struct dt_evt *dtev;
180 
181 		dtev = dt_pcb_ring_get(dp, 0);
182 		if (dtev == NULL)
183 			continue;
184 
185 		dtev->dtev_args[0] = args[0];
186 		dtev->dtev_args[1] = args[1];
187 		dtev->dtev_args[2] = args[2];
188 		dtev->dtev_args[3] = args[3];
189 		dtev->dtev_args[4] = args[4];
190 
191 		dt_pcb_ring_consume(dp, dtev);
192 	}
193 	smr_read_leave();
194 	return 1;
195 }
196