Bring in the remainder of the post-SoC amd64 enchilada.
[dragonfly.git] / sys / kern / kern_ktr.c
CommitLineData
d3776285
MD
1/*
2 * Copyright (c) 2005 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34/*
35 * The following copyright applies to the DDB command code:
36 *
81540c2d
EN
37 * Copyright (c) 2000 John Baldwin <jhb@FreeBSD.org>
38 * All rights reserved.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the author nor the names of any co-contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 */
81540c2d 64/*
ffc26552 65 * $DragonFly: src/sys/kern/kern_ktr.c,v 1.23 2008/02/12 23:33:23 corecode Exp $
81540c2d 66 */
81540c2d 67/*
d3776285 68 * Kernel tracepoint facility.
81540c2d
EN
69 */
70
71#include "opt_ddb.h"
72#include "opt_ktr.h"
73
74#include <sys/param.h>
75#include <sys/cons.h>
76#include <sys/kernel.h>
81540c2d
EN
77#include <sys/libkern.h>
78#include <sys/proc.h>
79#include <sys/sysctl.h>
d3776285 80#include <sys/ktr.h>
81540c2d
EN
81#include <sys/systm.h>
82#include <sys/time.h>
8e273a1d 83#include <sys/malloc.h>
c2751817 84#include <sys/spinlock.h>
8e273a1d 85#include <sys/thread2.h>
c2751817 86#include <sys/spinlock2.h>
8e273a1d 87#include <sys/ctype.h>
81540c2d
EN
88
89#include <machine/cpu.h>
90#include <machine/cpufunc.h>
91#include <machine/specialreg.h>
92#include <machine/md_var.h>
93
94#include <ddb/ddb.h>
95
96#ifndef KTR_ENTRIES
d3776285 97#define KTR_ENTRIES 2048
81540c2d 98#endif
d3776285 99#define KTR_ENTRIES_MASK (KTR_ENTRIES - 1)
81540c2d 100
96328d40
MD
101/*
102 * test logging support. When ktr_testlogcnt is non-zero each synchronization
0b698dca 103 * interrupt will issue six back-to-back ktr logging messages on cpu 0
96328d40
MD
104 * so the user can determine KTR logging overheads.
105 */
106#if !defined(KTR_TESTLOG)
107#define KTR_TESTLOG KTR_ALL
108#endif
109KTR_INFO_MASTER(testlog);
8cb417fa 110#if KTR_TESTLOG
96328d40
MD
111KTR_INFO(KTR_TESTLOG, testlog, test1, 0, "test1", sizeof(void *) * 4);
112KTR_INFO(KTR_TESTLOG, testlog, test2, 1, "test2", sizeof(void *) * 4);
113KTR_INFO(KTR_TESTLOG, testlog, test3, 2, "test3", sizeof(void *) * 4);
0b698dca
MD
114KTR_INFO(KTR_TESTLOG, testlog, test4, 3, "test4", 0);
115KTR_INFO(KTR_TESTLOG, testlog, test5, 4, "test5", 0);
116KTR_INFO(KTR_TESTLOG, testlog, test6, 5, "test6", 0);
c2751817 117#ifdef SMP
72d379df 118KTR_INFO(KTR_TESTLOG, testlog, pingpong, 6, "pingpong", 0);
c2751817
MD
119KTR_INFO(KTR_TESTLOG, testlog, pipeline, 7, "pipeline", 0);
120#endif
121KTR_INFO(KTR_TESTLOG, testlog, crit_beg, 8, "crit_beg", 0);
122KTR_INFO(KTR_TESTLOG, testlog, crit_end, 9, "crit_end", 0);
123KTR_INFO(KTR_TESTLOG, testlog, spin_beg, 10, "spin_beg", 0);
124KTR_INFO(KTR_TESTLOG, testlog, spin_end, 11, "spin_end", 0);
96328d40 125#define logtest(name) KTR_LOG(testlog_ ## name, 0, 0, 0, 0)
0b698dca 126#define logtest_noargs(name) KTR_LOG(testlog_ ## name)
8cb417fa 127#endif
96328d40 128
8e273a1d
EN
129MALLOC_DEFINE(M_KTR, "ktr", "ktr buffers");
130
d3776285 131SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RW, 0, "ktr");
81540c2d 132
ffc26552 133int ktr_entries = KTR_ENTRIES;
81540c2d
EN
134SYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD, &ktr_entries, 0, "");
135
ffc26552 136int ktr_version = KTR_VERSION;
81540c2d
EN
137SYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD, &ktr_version, 0, "");
138
af6ff89e
MD
139static int ktr_stacktrace = 1;
140SYSCTL_INT(_debug_ktr, OID_AUTO, stacktrace, CTLFLAG_RD, &ktr_stacktrace, 0, "");
141
374133e3
MD
142static int ktr_resynchronize = 0;
143SYSCTL_INT(_debug_ktr, OID_AUTO, resynchronize, CTLFLAG_RW, &ktr_resynchronize, 0, "");
144
96328d40
MD
145#if KTR_TESTLOG
146static int ktr_testlogcnt = 0;
147SYSCTL_INT(_debug_ktr, OID_AUTO, testlogcnt, CTLFLAG_RW, &ktr_testlogcnt, 0, "");
72d379df
MD
148static int ktr_testipicnt = 0;
149static int ktr_testipicnt_remainder;
150SYSCTL_INT(_debug_ktr, OID_AUTO, testipicnt, CTLFLAG_RW, &ktr_testipicnt, 0, "");
c2751817
MD
151static int ktr_testcritcnt = 0;
152SYSCTL_INT(_debug_ktr, OID_AUTO, testcritcnt, CTLFLAG_RW, &ktr_testcritcnt, 0, "");
153static int ktr_testspincnt = 0;
154SYSCTL_INT(_debug_ktr, OID_AUTO, testspincnt, CTLFLAG_RW, &ktr_testspincnt, 0, "");
96328d40
MD
155#endif
156
d3776285
MD
157/*
158 * Give cpu0 a static buffer so the tracepoint facility can be used during
159 * early boot (note however that we still use a critical section, XXX).
160 */
161static struct ktr_entry ktr_buf0[KTR_ENTRIES];
ffc26552
SS
162struct ktr_entry *ktr_buf[MAXCPU] = { &ktr_buf0[0] };
163int ktr_idx[MAXCPU];
0b698dca 164#ifdef SMP
374133e3
MD
165static int ktr_sync_state = 0;
166static int ktr_sync_count;
167static int64_t ktr_sync_tsc;
0b698dca 168#endif
374133e3
MD
169struct callout ktr_resync_callout;
170
81540c2d
EN
171#ifdef KTR_VERBOSE
172int ktr_verbose = KTR_VERBOSE;
173TUNABLE_INT("debug.ktr.verbose", &ktr_verbose);
174SYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0, "");
175#endif
176
ba39e2e0
MD
177static void ktr_resync_callback(void *dummy __unused);
178
c2751817 179extern int64_t tsc_offsets[];
0b698dca 180
81540c2d
EN
181static void
182ktr_sysinit(void *dummy)
183{
8e273a1d
EN
184 int i;
185
d3776285 186 for(i = 1; i < ncpus; ++i) {
77652cad 187 ktr_buf[i] = kmalloc(KTR_ENTRIES * sizeof(struct ktr_entry),
d3776285 188 M_KTR, M_WAITOK | M_ZERO);
8e273a1d 189 }
ba39e2e0
MD
190 callout_init(&ktr_resync_callout);
191 callout_reset(&ktr_resync_callout, hz / 10, ktr_resync_callback, NULL);
81540c2d 192}
ba39e2e0 193SYSINIT(ktr_sysinit, SI_BOOT2_KLD, SI_ORDER_ANY, ktr_sysinit, NULL);
374133e3 194
374133e3
MD
195/*
196 * Try to resynchronize the TSC's for all cpus. This is really, really nasty.
197 * We have to send an IPIQ message to all remote cpus, wait until they
198 * get into their IPIQ processing code loop, then do an even stricter hard
199 * loop to get the cpus as close to synchronized as we can to get the most
200 * accurate reading.
201 *
202 * This callback occurs on cpu0.
203 */
8cb417fa 204#if KTR_TESTLOG
72d379df 205static void ktr_pingpong_remote(void *dummy);
c2751817 206static void ktr_pipeline_remote(void *dummy);
8cb417fa 207#endif
374133e3 208
527fddf7 209#if defined(SMP) && defined(_RDTSC_SUPPORTED_)
b4c3db6f
MD
210
211static void ktr_resync_remote(void *dummy);
374133e3
MD
212extern cpumask_t smp_active_mask;
213
214/*
215 * We use a callout callback instead of a systimer because we cannot afford
216 * to preempt anyone to do this, or we might deadlock a spin-lock or
217 * serializer between two cpus.
218 */
219static
220void
221ktr_resync_callback(void *dummy __unused)
222{
223 int count;
224
225 KKASSERT(mycpu->gd_cpuid == 0);
96328d40
MD
226
227#if KTR_TESTLOG
228 /*
229 * Test logging
230 */
231 if (ktr_testlogcnt) {
232 --ktr_testlogcnt;
233 cpu_disable_intr();
234 logtest(test1);
235 logtest(test2);
236 logtest(test3);
0b698dca
MD
237 logtest_noargs(test4);
238 logtest_noargs(test5);
239 logtest_noargs(test6);
96328d40
MD
240 cpu_enable_intr();
241 }
72d379df
MD
242
243 /*
244 * Test IPI messaging
245 */
246 if (ktr_testipicnt && ktr_testipicnt_remainder == 0 && ncpus > 1) {
247 ktr_testipicnt_remainder = ktr_testipicnt;
248 ktr_testipicnt = 0;
249 lwkt_send_ipiq_bycpu(1, ktr_pingpong_remote, NULL);
250 }
c2751817
MD
251
252 /*
253 * Test critical sections
254 */
255 if (ktr_testcritcnt) {
256 crit_enter();
257 crit_exit();
258 logtest_noargs(crit_beg);
259 for (count = ktr_testcritcnt; count; --count) {
260 crit_enter();
261 crit_exit();
262 }
263 logtest_noargs(crit_end);
264 ktr_testcritcnt = 0;
265 }
266
267 /*
268 * Test spinlock sections
269 */
270 if (ktr_testspincnt) {
271 struct spinlock spin;
272
273 spin_init(&spin);
d666840a
MD
274 spin_lock_wr(&spin);
275 spin_unlock_wr(&spin);
c2751817
MD
276 logtest_noargs(spin_beg);
277 for (count = ktr_testspincnt; count; --count) {
d666840a
MD
278 spin_lock_wr(&spin);
279 spin_unlock_wr(&spin);
280 }
281 logtest_noargs(spin_end);
282 logtest_noargs(spin_beg);
283 for (count = ktr_testspincnt; count; --count) {
284 spin_lock_rd(&spin);
285 spin_unlock_rd(&spin);
c2751817
MD
286 }
287 logtest_noargs(spin_end);
288 ktr_testspincnt = 0;
289 }
96328d40
MD
290#endif
291
292 /*
293 * Resynchronize the TSC
294 */
374133e3
MD
295 if (ktr_resynchronize == 0)
296 goto done;
297 if ((cpu_feature & CPUID_TSC) == 0)
298 return;
0b698dca
MD
299
300 /*
301 * Send the synchronizing IPI and wait for all cpus to get into
302 * their spin loop. We must process incoming IPIs while waiting
303 * to avoid a deadlock.
304 */
374133e3
MD
305 crit_enter();
306 ktr_sync_count = 0;
307 ktr_sync_state = 1;
308 ktr_sync_tsc = rdtsc();
309 count = lwkt_send_ipiq_mask(mycpu->gd_other_cpus & smp_active_mask,
310 (ipifunc1_t)ktr_resync_remote, NULL);
311 while (ktr_sync_count != count)
312 lwkt_process_ipiq();
0b698dca
MD
313
314 /*
315 * Continuously update the TSC for cpu 0 while waiting for all other
316 * cpus to finish stage 2.
317 */
374133e3
MD
318 cpu_disable_intr();
319 ktr_sync_tsc = rdtsc();
320 cpu_sfence();
321 ktr_sync_state = 2;
322 cpu_sfence();
323 while (ktr_sync_count != 0) {
324 ktr_sync_tsc = rdtsc();
325 cpu_lfence();
326 cpu_nop();
327 }
328 cpu_enable_intr();
329 crit_exit();
330 ktr_sync_state = 0;
331done:
332 callout_reset(&ktr_resync_callout, hz / 10, ktr_resync_callback, NULL);
333}
334
0b698dca
MD
335/*
336 * The remote-end of the KTR synchronization protocol runs on all cpus except
337 * cpu 0. Since this is an IPI function, it is entered with the current
338 * thread in a critical section.
339 */
374133e3
MD
340static void
341ktr_resync_remote(void *dummy __unused)
342{
343 volatile int64_t tsc1 = ktr_sync_tsc;
344 volatile int64_t tsc2;
345
0b698dca
MD
346 /*
347 * Inform the master that we have entered our hard loop.
348 */
374133e3
MD
349 KKASSERT(ktr_sync_state == 1);
350 atomic_add_int(&ktr_sync_count, 1);
351 while (ktr_sync_state == 1) {
352 lwkt_process_ipiq();
353 }
0b698dca
MD
354
355 /*
356 * Now the master is in a hard loop, synchronize the TSC and
357 * we are done.
358 */
374133e3
MD
359 cpu_disable_intr();
360 KKASSERT(ktr_sync_state == 2);
361 tsc2 = ktr_sync_tsc;
362 if (tsc2 > tsc1)
363 tsc_offsets[mycpu->gd_cpuid] = rdtsc() - tsc2;
364 atomic_subtract_int(&ktr_sync_count, 1);
365 cpu_enable_intr();
366}
81540c2d 367
8cb417fa
MD
368#if KTR_TESTLOG
369
72d379df
MD
370static
371void
372ktr_pingpong_remote(void *dummy __unused)
373{
c2751817
MD
374 int other_cpu;
375
72d379df 376 logtest_noargs(pingpong);
c2751817 377 other_cpu = 1 - mycpu->gd_cpuid;
72d379df
MD
378 if (ktr_testipicnt_remainder) {
379 --ktr_testipicnt_remainder;
c2751817
MD
380 lwkt_send_ipiq_bycpu(other_cpu, ktr_pingpong_remote, NULL);
381 } else {
382 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
383 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
384 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
385 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
386 lwkt_send_ipiq_bycpu(other_cpu, ktr_pipeline_remote, NULL);
72d379df
MD
387 }
388}
389
c2751817
MD
390static
391void
392ktr_pipeline_remote(void *dummy __unused)
393{
394 logtest_noargs(pipeline);
395}
396
8cb417fa
MD
397#endif
398
0b698dca
MD
399#else /* !SMP */
400
401/*
402 * The resync callback for UP doesn't do anything other then run the test
403 * log messages. If test logging is not enabled, don't bother resetting
404 * the callout.
405 */
406static
407void
408ktr_resync_callback(void *dummy __unused)
409{
410#if KTR_TESTLOG
411 /*
412 * Test logging
413 */
414 if (ktr_testlogcnt) {
415 --ktr_testlogcnt;
416 cpu_disable_intr();
417 logtest(test1);
418 logtest(test2);
419 logtest(test3);
420 logtest_noargs(test4);
421 logtest_noargs(test5);
422 logtest_noargs(test6);
423 cpu_enable_intr();
424 }
425 callout_reset(&ktr_resync_callout, hz / 10, ktr_resync_callback, NULL);
426#endif
427}
428
374133e3 429#endif
81540c2d 430
0b698dca
MD
431/*
432 * KTR_WRITE_ENTRY - Primary entry point for kernel trace logging
433 */
0855a2af
JG
434
435void
436ktr_write_str_entry(struct ktr_info *info, const char *file, int line, const char *jg_format, ...)
437{
438 __va_list va;
439 struct ktr_entry *entry;
440 int cpu;
441 __va_start(va, jg_format);
442
443 cpu = mycpu->gd_cpuid;
444 if (!ktr_buf[cpu])
445 return;
446
447 crit_enter();
448 entry = ktr_buf[cpu] + (ktr_idx[cpu] & KTR_ENTRIES_MASK);
449 ++ktr_idx[cpu];
450#ifdef _RDTSC_SUPPORTED_
451 if (cpu_feature & CPUID_TSC) {
452#ifdef SMP
453 entry->ktr_timestamp = rdtsc() - tsc_offsets[cpu];
454#else
455 entry->ktr_timestamp = rdtsc();
456#endif
457 } else
458#endif
459 {
460 entry->ktr_timestamp = get_approximate_time_t();
461 }
462 entry->ktr_info = info;
463 entry->ktr_file = file;
464 entry->ktr_line = line;
465 crit_exit();
466 kvsnprintf(entry->ktr_data, KTR_BUFSIZE, jg_format, va);
467 ((char *)(entry->ktr_data))[KTR_BUFSIZE - 1] = '\0';
468 if (ktr_stacktrace)
469 cpu_ktr_caller(entry);
470#ifdef KTR_VERBOSE
471 if (ktr_verbose && info->kf_format) {
472#ifdef SMP
473 kprintf("cpu%d ", cpu);
474#endif
475 if (ktr_verbose > 1) {
476 kprintf("%s.%d\t", entry->ktr_file, entry->ktr_line);
477 }
478 kvprintf(info->kf_format, ptr);
479 kprintf("\n");
480 }
481#endif
482 __va_end(va);
483}
484
d3776285 485static __inline
81540c2d 486void
d3776285
MD
487ktr_write_entry(struct ktr_info *info, const char *file, int line,
488 const void *ptr)
81540c2d
EN
489{
490 struct ktr_entry *entry;
d3776285
MD
491 int cpu;
492
493 cpu = mycpu->gd_cpuid;
b4cb74b5
SW
494 if (!ktr_buf[cpu])
495 return;
496
497 crit_enter();
498 entry = ktr_buf[cpu] + (ktr_idx[cpu] & KTR_ENTRIES_MASK);
499 ++ktr_idx[cpu];
527fddf7 500#ifdef _RDTSC_SUPPORTED_
b4cb74b5 501 if (cpu_feature & CPUID_TSC) {
0b698dca 502#ifdef SMP
b4cb74b5 503 entry->ktr_timestamp = rdtsc() - tsc_offsets[cpu];
0b698dca 504#else
b4cb74b5 505 entry->ktr_timestamp = rdtsc();
0b698dca 506#endif
527fddf7
MD
507 } else
508#endif
509 {
b4cb74b5 510 entry->ktr_timestamp = get_approximate_time_t();
8e273a1d 511 }
b4cb74b5
SW
512 entry->ktr_info = info;
513 entry->ktr_file = file;
514 entry->ktr_line = line;
515 crit_exit();
516 if (info->kf_data_size > KTR_BUFSIZE)
0855a2af 517 bcopy(ptr, entry->ktr_data, KTR_BUFSIZE);
b4cb74b5 518 else if (info->kf_data_size)
0855a2af 519 bcopy(ptr, entry->ktr_data, info->kf_data_size);
b4cb74b5
SW
520 if (ktr_stacktrace)
521 cpu_ktr_caller(entry);
81540c2d 522#ifdef KTR_VERBOSE
d3776285 523 if (ktr_verbose && info->kf_format) {
81540c2d 524#ifdef SMP
6ea70f76 525 kprintf("cpu%d ", cpu);
81540c2d
EN
526#endif
527 if (ktr_verbose > 1) {
6ea70f76 528 kprintf("%s.%d\t", entry->ktr_file, entry->ktr_line);
81540c2d 529 }
379210cb 530 kvprintf(info->kf_format, ptr);
6ea70f76 531 kprintf("\n");
81540c2d
EN
532 }
533#endif
d3776285
MD
534}
535
536void
537ktr_log(struct ktr_info *info, const char *file, int line, ...)
538{
539 __va_list va;
540
af6ff89e
MD
541 if (panicstr == NULL) {
542 __va_start(va, line);
543 ktr_write_entry(info, file, line, va);
544 __va_end(va);
545 }
d3776285
MD
546}
547
548void
549ktr_log_ptr(struct ktr_info *info, const char *file, int line, const void *ptr)
550{
af6ff89e
MD
551 if (panicstr == NULL) {
552 ktr_write_entry(info, file, line, ptr);
553 }
81540c2d
EN
554}
555
556#ifdef DDB
557
8e273a1d 558#define NUM_LINES_PER_PAGE 19
81540c2d
EN
559
560struct tstate {
561 int cur;
562 int first;
563};
d3776285 564
81540c2d 565static int db_ktr_verbose;
d3776285 566static int db_mach_vtrace(int cpu, struct ktr_entry *kp, int idx);
81540c2d
EN
567
568DB_SHOW_COMMAND(ktr, db_ktr_all)
569{
8e273a1d
EN
570 int a_flag = 0;
571 int c;
81540c2d 572 int nl = 0;
8e273a1d
EN
573 int i;
574 struct tstate tstate[MAXCPU];
575 int printcpu = -1;
576
577 for(i = 0; i < ncpus; i++) {
578 tstate[i].first = -1;
d3776285 579 tstate[i].cur = ktr_idx[i] & KTR_ENTRIES_MASK;
8e273a1d
EN
580 }
581 db_ktr_verbose = 0;
582 while ((c = *(modif++)) != '\0') {
583 if (c == 'v') {
584 db_ktr_verbose = 1;
585 }
586 else if (c == 'a') {
587 a_flag = 1;
81540c2d 588 }
8e273a1d
EN
589 else if (c == 'c') {
590 printcpu = 0;
591 while ((c = *(modif++)) != '\0') {
592 if (isdigit(c)) {
593 printcpu *= 10;
594 printcpu += c - '0';
595 }
596 else {
597 modif++;
598 break;
599 }
600 }
601 modif--;
81540c2d
EN
602 }
603 }
8e273a1d
EN
604 if (printcpu > ncpus - 1) {
605 db_printf("Invalid cpu number\n");
606 return;
607 }
608 /*
609 * Lopp throug all the buffers and print the content of them, sorted
610 * by the timestamp.
611 */
612 while (1) {
613 int counter;
614 u_int64_t highest_ts;
615 int highest_cpu;
616 struct ktr_entry *kp;
617
618 if (a_flag == 1 && cncheckc() != -1)
619 return;
620 highest_ts = 0;
621 highest_cpu = -1;
622 /*
623 * Find the lowest timestamp
624 */
625 for (i = 0, counter = 0; i < ncpus; i++) {
d3776285
MD
626 if (ktr_buf[i] == NULL)
627 continue;
8e273a1d
EN
628 if (printcpu != -1 && printcpu != i)
629 continue;
630 if (tstate[i].cur == -1) {
631 counter++;
632 if (counter == ncpus) {
633 db_printf("--- End of trace buffer ---\n");
634 return;
635 }
636 continue;
637 }
638 if (ktr_buf[i][tstate[i].cur].ktr_timestamp > highest_ts) {
639 highest_ts = ktr_buf[i][tstate[i].cur].ktr_timestamp;
640 highest_cpu = i;
641 }
642 }
643 i = highest_cpu;
644 KKASSERT(i != -1);
645 kp = &ktr_buf[i][tstate[i].cur];
646 if (tstate[i].first == -1)
647 tstate[i].first = tstate[i].cur;
648 if (--tstate[i].cur < 0)
649 tstate[i].cur = KTR_ENTRIES - 1;
650 if (tstate[i].first == tstate[i].cur) {
d3776285 651 db_mach_vtrace(i, kp, tstate[i].cur + 1);
8e273a1d
EN
652 tstate[i].cur = -1;
653 continue;
654 }
d3776285 655 if (ktr_buf[i][tstate[i].cur].ktr_info == NULL)
8e273a1d
EN
656 tstate[i].cur = -1;
657 if (db_more(&nl) == -1)
658 break;
d3776285 659 if (db_mach_vtrace(i, kp, tstate[i].cur + 1) == 0)
8e273a1d
EN
660 tstate[i].cur = -1;
661 }
81540c2d
EN
662}
663
664static int
d3776285 665db_mach_vtrace(int cpu, struct ktr_entry *kp, int idx)
81540c2d 666{
d3776285 667 if (kp->ktr_info == NULL)
8e273a1d 668 return(0);
81540c2d 669#ifdef SMP
d3776285 670 db_printf("cpu%d ", cpu);
81540c2d 671#endif
8e273a1d 672 db_printf("%d: ", idx);
81540c2d
EN
673 if (db_ktr_verbose) {
674 db_printf("%10.10lld %s.%d\t", (long long)kp->ktr_timestamp,
675 kp->ktr_file, kp->ktr_line);
676 }
d3776285 677 db_printf("%s\t", kp->ktr_info->kf_name);
af6ff89e 678 db_printf("from(%p,%p) ", kp->ktr_caller1, kp->ktr_caller2);
d3776285 679 if (kp->ktr_info->kf_format) {
0855a2af
JG
680 if (strcmp(kp->ktr_info->kf_format, "STR") == 0) {
681 db_printf("%s", kp->ktr_data);
682 } else {
683 int64_t *args = kp->ktr_data;
684 db_printf(kp->ktr_info->kf_format,
685 args[0], args[1], args[2], args[3],
686 args[4], args[5], args[6], args[7],
687 args[8], args[9], args[10], args[11]);
688 }
d3776285
MD
689
690 }
81540c2d
EN
691 db_printf("\n");
692
8e273a1d 693 return(1);
81540c2d
EN
694}
695
696#endif /* DDB */