2 * Copyright (c) 2000 John Baldwin <jhb@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the author nor the names of any co-contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * This module holds the global variables used by KTR and the ktr_tracepoint()
32 * function that does the actual tracing.
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
42 #include <sys/param.h>
45 #include <sys/kernel.h>
47 #include <sys/libkern.h>
49 #include <sys/sysctl.h>
50 #include <sys/systm.h>
53 #include <machine/cpu.h>
55 #include <machine/ktr.h>
60 #include <ddb/db_output.h>
64 #define KTR_ENTRIES 1024
68 #define KTR_MASK (KTR_GEN)
72 #define KTR_CPUMASK (~0)
76 #define KTR_TIME get_cyclecount()
80 #define KTR_CPU PCPU_GET(cpuid)
83 SYSCTL_NODE(_debug
, OID_AUTO
, ktr
, CTLFLAG_RD
, 0, "KTR options");
85 int ktr_cpumask
= KTR_CPUMASK
;
86 TUNABLE_INT("debug.ktr.cpumask", &ktr_cpumask
);
87 SYSCTL_INT(_debug_ktr
, OID_AUTO
, cpumask
, CTLFLAG_RW
, &ktr_cpumask
, 0, "");
89 int ktr_mask
= KTR_MASK
;
90 TUNABLE_INT("debug.ktr.mask", &ktr_mask
);
91 SYSCTL_INT(_debug_ktr
, OID_AUTO
, mask
, CTLFLAG_RW
, &ktr_mask
, 0, "");
93 int ktr_compile
= KTR_COMPILE
;
94 SYSCTL_INT(_debug_ktr
, OID_AUTO
, compile
, CTLFLAG_RD
, &ktr_compile
, 0, "");
96 int ktr_entries
= KTR_ENTRIES
;
97 SYSCTL_INT(_debug_ktr
, OID_AUTO
, entries
, CTLFLAG_RD
, &ktr_entries
, 0, "");
99 int ktr_version
= KTR_VERSION
;
100 SYSCTL_INT(_debug_ktr
, OID_AUTO
, version
, CTLFLAG_RD
, &ktr_version
, 0, "");
102 volatile int ktr_idx
= 0;
103 struct ktr_entry ktr_buf
[KTR_ENTRIES
];
106 sysctl_debug_ktr_clear(SYSCTL_HANDLER_ARGS
)
111 error
= sysctl_handle_int(oidp
, &clear
, 0, req
);
112 if (error
|| !req
->newptr
)
116 bzero(ktr_buf
, sizeof(ktr_buf
));
122 SYSCTL_PROC(_debug_ktr
, OID_AUTO
, clear
, CTLTYPE_INT
|CTLFLAG_RW
, 0, 0,
123 sysctl_debug_ktr_clear
, "I", "Clear KTR Buffer");
126 int ktr_verbose
= KTR_VERBOSE
;
127 TUNABLE_INT("debug.ktr.verbose", &ktr_verbose
);
128 SYSCTL_INT(_debug_ktr
, OID_AUTO
, verbose
, CTLFLAG_RW
, &ktr_verbose
, 0, "");
133 char ktr_alq_file
[MAXPATHLEN
] = "/tmp/ktr.out";
135 int ktr_alq_depth
= KTR_ENTRIES
;
136 int ktr_alq_enabled
= 0;
137 int ktr_alq_failed
= 0;
140 SYSCTL_INT(_debug_ktr
, OID_AUTO
, alq_max
, CTLFLAG_RW
, &ktr_alq_max
, 0,
141 "Maximum number of entries to write");
142 SYSCTL_INT(_debug_ktr
, OID_AUTO
, alq_cnt
, CTLFLAG_RD
, &ktr_alq_cnt
, 0,
143 "Current number of written entries");
144 SYSCTL_INT(_debug_ktr
, OID_AUTO
, alq_failed
, CTLFLAG_RD
, &ktr_alq_failed
, 0,
145 "Number of times we overran the buffer");
146 SYSCTL_INT(_debug_ktr
, OID_AUTO
, alq_depth
, CTLFLAG_RW
, &ktr_alq_depth
, 0,
147 "Number of items in the write buffer");
148 SYSCTL_STRING(_debug_ktr
, OID_AUTO
, alq_file
, CTLFLAG_RW
, ktr_alq_file
,
149 sizeof(ktr_alq_file
), "KTR logging file");
152 sysctl_debug_ktr_alq_enable(SYSCTL_HANDLER_ARGS
)
157 enable
= ktr_alq_enabled
;
159 error
= sysctl_handle_int(oidp
, &enable
, 0, req
);
160 if (error
|| !req
->newptr
)
166 error
= alq_open(&ktr_alq
, (const char *)ktr_alq_file
,
167 req
->td
->td_ucred
, ALQ_DEFAULT_CMODE
,
168 sizeof(struct ktr_entry
), ktr_alq_depth
);
175 if (ktr_alq_enabled
== 0)
184 SYSCTL_PROC(_debug_ktr
, OID_AUTO
, alq_enable
,
185 CTLTYPE_INT
|CTLFLAG_RW
, 0, 0, sysctl_debug_ktr_alq_enable
,
186 "I", "Enable KTR logging");
190 ktr_tracepoint(u_int mask
, const char *file
, int line
, const char *format
,
191 u_long arg1
, u_long arg2
, u_long arg3
, u_long arg4
, u_long arg5
,
194 struct ktr_entry
*entry
;
196 struct ale
*ale
= NULL
;
198 int newindex
, saveindex
;
200 #if defined(KTR_VERBOSE) || defined(KTR_ALQ)
207 if ((ktr_mask
& mask
) == 0)
210 if (((1 << cpu
) & ktr_cpumask
) == 0)
212 #if defined(KTR_VERBOSE) || defined(KTR_ALQ)
214 if (td
->td_pflags
& TDP_INKTR
)
216 td
->td_pflags
|= TDP_INKTR
;
219 if (ktr_alq_enabled
&&
220 td
->td_critnest
== 0 &&
221 (td
->td_flags
& TDF_IDLETD
) == 0 &&
223 if (ktr_alq_max
&& ktr_alq_cnt
> ktr_alq_max
)
225 if ((ale
= alq_get(ktr_alq
, ALQ_NOWAIT
)) == NULL
) {
230 entry
= (struct ktr_entry
*)ale
->ae_data
;
236 newindex
= (saveindex
+ 1) & (KTR_ENTRIES
- 1);
237 } while (atomic_cmpset_rel_int(&ktr_idx
, saveindex
, newindex
) == 0);
238 entry
= &ktr_buf
[saveindex
];
240 entry
->ktr_timestamp
= KTR_TIME
;
241 entry
->ktr_cpu
= cpu
;
242 entry
->ktr_thread
= curthread
;
244 while (strncmp(file
, "../", 3) == 0)
246 entry
->ktr_file
= file
;
247 entry
->ktr_line
= line
;
251 printf("cpu%d ", cpu
);
253 if (ktr_verbose
> 1) {
254 printf("%s.%d\t", entry
->ktr_file
,
257 printf(format
, arg1
, arg2
, arg3
, arg4
, arg5
, arg6
);
261 entry
->ktr_desc
= format
;
262 entry
->ktr_parms
[0] = arg1
;
263 entry
->ktr_parms
[1] = arg2
;
264 entry
->ktr_parms
[2] = arg3
;
265 entry
->ktr_parms
[3] = arg4
;
266 entry
->ktr_parms
[4] = arg5
;
267 entry
->ktr_parms
[5] = arg6
;
270 alq_post(ktr_alq
, ale
);
273 #if defined(KTR_VERBOSE) || defined(KTR_ALQ)
274 td
->td_pflags
&= ~TDP_INKTR
;
284 static struct tstate tstate
;
285 static int db_ktr_verbose
;
286 static int db_mach_vtrace(void);
288 DB_SHOW_COMMAND(ktr
, db_ktr_all
)
291 tstate
.cur
= (ktr_idx
- 1) & (KTR_ENTRIES
- 1);
293 db_ktr_verbose
= index(modif
, 'v') != NULL
;
294 if (index(modif
, 'a') != NULL
) {
296 while (cncheckc() != -1)
297 if (db_mach_vtrace() == 0)
300 while (!db_pager_quit
)
301 if (db_mach_vtrace() == 0)
309 struct ktr_entry
*kp
;
311 if (tstate
.cur
== tstate
.first
) {
312 db_printf("--- End of trace buffer ---\n");
315 kp
= &ktr_buf
[tstate
.cur
];
317 /* Skip over unused entries. */
318 if (kp
->ktr_desc
== NULL
) {
319 db_printf("--- End of trace buffer ---\n");
322 db_printf("%d (%p", tstate
.cur
, kp
->ktr_thread
);
324 db_printf(":cpu%d", kp
->ktr_cpu
);
327 if (db_ktr_verbose
) {
328 db_printf(" %10.10lld %s.%d", (long long)kp
->ktr_timestamp
,
329 kp
->ktr_file
, kp
->ktr_line
);
332 db_printf(kp
->ktr_desc
, kp
->ktr_parms
[0], kp
->ktr_parms
[1],
333 kp
->ktr_parms
[2], kp
->ktr_parms
[3], kp
->ktr_parms
[4],
337 if (tstate
.first
== -1)
338 tstate
.first
= tstate
.cur
;
340 if (--tstate
.cur
< 0)
341 tstate
.cur
= KTR_ENTRIES
- 1;