kern_ktr.c revision 229272
150476Speter/*-
282486Sbde * Copyright (c) 2000 John Baldwin <jhb@FreeBSD.org>
321611Swosch * All rights reserved.
421611Swosch *
521611Swosch * Redistribution and use in source and binary forms, with or without
618052Sbde * modification, are permitted provided that the following conditions
794940Sru * are met:
894940Sru * 1. Redistributions of source code must retain the above copyright
994940Sru *    notice, this list of conditions and the following disclaimer.
1094940Sru * 2. Redistributions in binary form must reproduce the above copyright
1136494Sbde *    notice, this list of conditions and the following disclaimer in the
1218052Sbde *    documentation and/or other materials provided with the distribution.
1336494Sbde * 3. Neither the name of the author nor the names of any co-contributors
14125762Skientzle *    may be used to endorse or promote products derived from this software
15125255Sbde *    without specific prior written permission.
1639412Sphk *
17135771Strhodes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18135752Sdougb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19135549Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20135549Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21135599Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22125256Sbde * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23117183Sru * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24122404Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2579495Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2636494Sbde * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2776515Sbde * SUCH DAMAGE.
2869227Sbrian */
2936494Sbde
3039259Sgibbs/*
3176515Sbde * This module holds the global variables used by KTR and the ktr_tracepoint()
3236494Sbde * function that does the actual tracing.
3336494Sbde */
34125255Sbde
3536494Sbde#include <sys/cdefs.h>
3676515Sbde__FBSDID("$FreeBSD: head/sys/kern/kern_ktr.c 229272 2012-01-02 12:12:10Z ed $");
3739259Sgibbs
3836494Sbde#include "opt_ddb.h"
3936494Sbde#include "opt_ktr.h"
40135549Sdes#include "opt_alq.h"
4136494Sbde
4274535Sdes#include <sys/param.h>
4318052Sbde#include <sys/queue.h>
4476515Sbde#include <sys/alq.h>
4536494Sbde#include <sys/cons.h>
4676515Sbde#include <sys/cpuset.h>
4736494Sbde#include <sys/kernel.h>
48116318Speter#include <sys/ktr.h>
49112461Sru#include <sys/libkern.h>
5036494Sbde#include <sys/proc.h>
51125255Sbde#include <sys/sysctl.h>
52125255Sbde#include <sys/systm.h>
5347570Sache#include <sys/time.h>
5457538Sshin
5536494Sbde#include <machine/cpu.h>
56135752Sdougb#ifdef __sparc64__
5767523Sarchie#include <machine/ktr.h>
58135549Sdes#endif
59135549Sdes
60135599Sru#ifdef DDB
61125255Sbde#include <ddb/ddb.h>
62125255Sbde#include <ddb/db_output.h>
63125255Sbde#endif
64104465Sru
65120492Sfjoe#ifndef KTR_ENTRIES
66125255Sbde#define	KTR_ENTRIES	1024
6736494Sbde#endif
6836494Sbde
6965916Sache#ifndef KTR_MASK
70135752Sdougb#define	KTR_MASK	(0)
71135599Sru#endif
72135599Sru
7336494Sbde#ifndef KTR_TIME
74133362Sobrien#define	KTR_TIME	get_cyclecount()
7536494Sbde#endif
7676515Sbde
7790796Sgshapiro#ifndef KTR_CPU
7890796Sgshapiro#define	KTR_CPU		PCPU_GET(cpuid)
7990796Sgshapiro#endif
8036494Sbde
8165916SacheFEATURE(ktr, "Kernel support for KTR kernel tracing facility");
8252251Sbp
8336494Sbdestatic SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RD, 0, "KTR options");
8452419Sjulian
85121615Shartiint	ktr_mask = KTR_MASK;
8636494SbdeTUNABLE_INT("debug.ktr.mask", &ktr_mask);
8736494SbdeSYSCTL_INT(_debug_ktr, OID_AUTO, mask, CTLFLAG_RW,
8842916Sjdp    &ktr_mask, 0, "Bitmask of KTR event classes for which logging is enabled");
8942916Sjdp
90107256Sruint	ktr_compile = KTR_COMPILE;
9159770SbdeSYSCTL_INT(_debug_ktr, OID_AUTO, compile, CTLFLAG_RD,
92125381Sru    &ktr_compile, 0, "Bitmask of KTR event classes compiled into the kernel");
93107256Sru
94139113Sruint	ktr_entries = KTR_ENTRIES;
95125381SruSYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD,
96125381Sru    &ktr_entries, 0, "Number of entries in the KTR buffer");
97125381Sru
9876576Smarkmint	ktr_version = KTR_VERSION;
99125381SruSYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD,
100137675Sbz    &ktr_version, 0, "Version of the KTR interface");
101125381Sru
102137675Sbzcpuset_t ktr_cpumask;
103139113Srustatic char ktr_cpumask_str[CPUSETBUFSIZ];
104125381SruTUNABLE_STR("debug.ktr.cpumask", ktr_cpumask_str, sizeof(ktr_cpumask_str));
105125381Sru
10642916Sjdpstatic void
107137675Sbzktr_cpumask_initializer(void *dummy __unused)
108137675Sbz{
109137675Sbz
11089705Sru	CPU_FILL(&ktr_cpumask);
111137675Sbz#ifdef KTR_CPUMASK
11242916Sjdp	if (cpusetobj_strscan(&ktr_cpumask, KTR_CPUMASK) == -1)
11376515Sbde		CPU_FILL(&ktr_cpumask);
11436494Sbde#endif
115125269Smarcel
11641231Sjdp	/*
11736494Sbde	 * TUNABLE_STR() runs with SI_ORDER_MIDDLE priority, thus it must be
118125255Sbde	 * already set, if necessary.
11936494Sbde	 */
120125256Sbde	if (ktr_cpumask_str[0] != '\0' &&
121121054Semax	    cpusetobj_strscan(&ktr_cpumask, ktr_cpumask_str) == -1)
12288142Sru		CPU_FILL(&ktr_cpumask);
123125255Sbde}
124125255SbdeSYSINIT(ktr_cpumask_initializer, SI_SUB_TUNABLES, SI_ORDER_ANY,
125125537Sru    ktr_cpumask_initializer, NULL);
12636494Sbde
12741231Sjdpstatic int
12836494Sbdesysctl_debug_ktr_cpumask(SYSCTL_HANDLER_ARGS)
12918052Sbde{
13076515Sbde	char lktr_cpumask_str[CPUSETBUFSIZ];
131109725Sru	cpuset_t imask;
132101224Srwatson	int error;
133104465Sru
13436494Sbde	cpusetobj_strprint(lktr_cpumask_str, &ktr_cpumask);
13576515Sbde	error = sysctl_handle_string(oidp, lktr_cpumask_str,
13644757Smarkm	    sizeof(lktr_cpumask_str), req);
13736494Sbde	if (error != 0 || req->newptr == NULL)
13836494Sbde		return (error);
13994578Sdes	if (cpusetobj_strscan(&imask, lktr_cpumask_str) == -1)
14036494Sbde		return (EINVAL);
141	CPU_COPY(&imask, &ktr_cpumask);
142
143	return (error);
144}
145SYSCTL_PROC(_debug_ktr, OID_AUTO, cpumask,
146    CTLFLAG_RW | CTLFLAG_MPSAFE | CTLTYPE_STRING, NULL, 0,
147    sysctl_debug_ktr_cpumask, "S",
148    "Bitmask of CPUs on which KTR logging is enabled");
149
150volatile int	ktr_idx = 0;
151struct	ktr_entry ktr_buf[KTR_ENTRIES];
152
153static int
154sysctl_debug_ktr_clear(SYSCTL_HANDLER_ARGS)
155{
156	int clear, error;
157
158	clear = 0;
159	error = sysctl_handle_int(oidp, &clear, 0, req);
160	if (error || !req->newptr)
161		return (error);
162
163	if (clear) {
164		bzero(ktr_buf, sizeof(ktr_buf));
165		ktr_idx = 0;
166	}
167
168	return (error);
169}
170SYSCTL_PROC(_debug_ktr, OID_AUTO, clear, CTLTYPE_INT|CTLFLAG_RW, 0, 0,
171    sysctl_debug_ktr_clear, "I", "Clear KTR Buffer");
172
173#ifdef KTR_VERBOSE
174int	ktr_verbose = KTR_VERBOSE;
175TUNABLE_INT("debug.ktr.verbose", &ktr_verbose);
176SYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0, "");
177#endif
178
179#ifdef KTR_ALQ
180struct alq *ktr_alq;
181char	ktr_alq_file[MAXPATHLEN] = "/tmp/ktr.out";
182int	ktr_alq_cnt = 0;
183int	ktr_alq_depth = KTR_ENTRIES;
184int	ktr_alq_enabled = 0;
185int	ktr_alq_failed = 0;
186int	ktr_alq_max = 0;
187
188SYSCTL_INT(_debug_ktr, OID_AUTO, alq_max, CTLFLAG_RW, &ktr_alq_max, 0,
189    "Maximum number of entries to write");
190SYSCTL_INT(_debug_ktr, OID_AUTO, alq_cnt, CTLFLAG_RD, &ktr_alq_cnt, 0,
191    "Current number of written entries");
192SYSCTL_INT(_debug_ktr, OID_AUTO, alq_failed, CTLFLAG_RD, &ktr_alq_failed, 0,
193    "Number of times we overran the buffer");
194SYSCTL_INT(_debug_ktr, OID_AUTO, alq_depth, CTLFLAG_RW, &ktr_alq_depth, 0,
195    "Number of items in the write buffer");
196SYSCTL_STRING(_debug_ktr, OID_AUTO, alq_file, CTLFLAG_RW, ktr_alq_file,
197    sizeof(ktr_alq_file), "KTR logging file");
198
199static int
200sysctl_debug_ktr_alq_enable(SYSCTL_HANDLER_ARGS)
201{
202	int error;
203	int enable;
204
205	enable = ktr_alq_enabled;
206
207	error = sysctl_handle_int(oidp, &enable, 0, req);
208	if (error || !req->newptr)
209		return (error);
210
211	if (enable) {
212		if (ktr_alq_enabled)
213			return (0);
214		error = alq_open(&ktr_alq, (const char *)ktr_alq_file,
215		    req->td->td_ucred, ALQ_DEFAULT_CMODE,
216		    sizeof(struct ktr_entry), ktr_alq_depth);
217		if (error == 0) {
218			ktr_alq_cnt = 0;
219			ktr_alq_failed = 0;
220			ktr_alq_enabled = 1;
221		}
222	} else {
223		if (ktr_alq_enabled == 0)
224			return (0);
225		ktr_alq_enabled = 0;
226		alq_close(ktr_alq);
227		ktr_alq = NULL;
228	}
229
230	return (error);
231}
232SYSCTL_PROC(_debug_ktr, OID_AUTO, alq_enable,
233    CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_debug_ktr_alq_enable,
234    "I", "Enable KTR logging");
235#endif
236
237void
238ktr_tracepoint(u_int mask, const char *file, int line, const char *format,
239    u_long arg1, u_long arg2, u_long arg3, u_long arg4, u_long arg5,
240    u_long arg6)
241{
242	struct ktr_entry *entry;
243#ifdef KTR_ALQ
244	struct ale *ale = NULL;
245#endif
246	int newindex, saveindex;
247#if defined(KTR_VERBOSE) || defined(KTR_ALQ)
248	struct thread *td;
249#endif
250	int cpu;
251
252	if (panicstr)
253		return;
254	if ((ktr_mask & mask) == 0)
255		return;
256	cpu = KTR_CPU;
257	if (!CPU_ISSET(cpu, &ktr_cpumask))
258		return;
259#if defined(KTR_VERBOSE) || defined(KTR_ALQ)
260	td = curthread;
261	if (td->td_pflags & TDP_INKTR)
262		return;
263	td->td_pflags |= TDP_INKTR;
264#endif
265#ifdef KTR_ALQ
266	if (ktr_alq_enabled) {
267		if (td->td_critnest == 0 &&
268		    (td->td_flags & TDF_IDLETD) == 0 &&
269		    td != ald_thread) {
270			if (ktr_alq_max && ktr_alq_cnt > ktr_alq_max)
271				goto done;
272			if ((ale = alq_get(ktr_alq, ALQ_NOWAIT)) == NULL) {
273				ktr_alq_failed++;
274				goto done;
275			}
276			ktr_alq_cnt++;
277			entry = (struct ktr_entry *)ale->ae_data;
278		} else {
279			goto done;
280		}
281	} else
282#endif
283	{
284		do {
285			saveindex = ktr_idx;
286			newindex = (saveindex + 1) & (KTR_ENTRIES - 1);
287		} while (atomic_cmpset_rel_int(&ktr_idx, saveindex, newindex) == 0);
288		entry = &ktr_buf[saveindex];
289	}
290	entry->ktr_timestamp = KTR_TIME;
291	entry->ktr_cpu = cpu;
292	entry->ktr_thread = curthread;
293	if (file != NULL)
294		while (strncmp(file, "../", 3) == 0)
295			file += 3;
296	entry->ktr_file = file;
297	entry->ktr_line = line;
298#ifdef KTR_VERBOSE
299	if (ktr_verbose) {
300#ifdef SMP
301		printf("cpu%d ", cpu);
302#endif
303		if (ktr_verbose > 1) {
304			printf("%s.%d\t", entry->ktr_file,
305			    entry->ktr_line);
306		}
307		printf(format, arg1, arg2, arg3, arg4, arg5, arg6);
308		printf("\n");
309	}
310#endif
311	entry->ktr_desc = format;
312	entry->ktr_parms[0] = arg1;
313	entry->ktr_parms[1] = arg2;
314	entry->ktr_parms[2] = arg3;
315	entry->ktr_parms[3] = arg4;
316	entry->ktr_parms[4] = arg5;
317	entry->ktr_parms[5] = arg6;
318#ifdef KTR_ALQ
319	if (ktr_alq_enabled && ale)
320		alq_post(ktr_alq, ale);
321done:
322#endif
323#if defined(KTR_VERBOSE) || defined(KTR_ALQ)
324	td->td_pflags &= ~TDP_INKTR;
325#endif
326}
327
328#ifdef DDB
329
330struct tstate {
331	int	cur;
332	int	first;
333};
334static	struct tstate tstate;
335static	int db_ktr_verbose;
336static	int db_mach_vtrace(void);
337
338DB_SHOW_COMMAND(ktr, db_ktr_all)
339{
340
341	tstate.cur = (ktr_idx - 1) & (KTR_ENTRIES - 1);
342	tstate.first = -1;
343	db_ktr_verbose = 0;
344	db_ktr_verbose |= (strchr(modif, 'v') != NULL) ? 2 : 0;
345	db_ktr_verbose |= (strchr(modif, 'V') != NULL) ? 1 : 0; /* just timestap please */
346	if (strchr(modif, 'a') != NULL) {
347		db_disable_pager();
348		while (cncheckc() != -1)
349			if (db_mach_vtrace() == 0)
350				break;
351	} else {
352		while (!db_pager_quit)
353			if (db_mach_vtrace() == 0)
354				break;
355	}
356}
357
358static int
359db_mach_vtrace(void)
360{
361	struct ktr_entry	*kp;
362
363	if (tstate.cur == tstate.first) {
364		db_printf("--- End of trace buffer ---\n");
365		return (0);
366	}
367	kp = &ktr_buf[tstate.cur];
368
369	/* Skip over unused entries. */
370	if (kp->ktr_desc == NULL) {
371		db_printf("--- End of trace buffer ---\n");
372		return (0);
373	}
374	db_printf("%d (%p", tstate.cur, kp->ktr_thread);
375#ifdef SMP
376	db_printf(":cpu%d", kp->ktr_cpu);
377#endif
378	db_printf(")");
379	if (db_ktr_verbose >= 1) {
380		db_printf(" %10.10lld", (long long)kp->ktr_timestamp);
381	}
382	if (db_ktr_verbose >= 2) {
383		db_printf(" %s.%d", kp->ktr_file, kp->ktr_line);
384	}
385	db_printf(": ");
386	db_printf(kp->ktr_desc, kp->ktr_parms[0], kp->ktr_parms[1],
387	    kp->ktr_parms[2], kp->ktr_parms[3], kp->ktr_parms[4],
388	    kp->ktr_parms[5]);
389	db_printf("\n");
390
391	if (tstate.first == -1)
392		tstate.first = tstate.cur;
393
394	if (--tstate.cur < 0)
395		tstate.cur = KTR_ENTRIES - 1;
396
397	return (1);
398}
399
400#endif	/* DDB */
401