162ae6c89SJason Evans /* 262ae6c89SJason Evans * Copyright (c) 2000 362ae6c89SJason Evans * John Baldwin <jhb@FreeBSD.org>. All rights reserved. 462ae6c89SJason Evans * 562ae6c89SJason Evans * Redistribution and use in source and binary forms, with or without 662ae6c89SJason Evans * modification, are permitted provided that the following conditions 762ae6c89SJason Evans * are met: 862ae6c89SJason Evans * 1. Redistributions of source code must retain the above copyright 962ae6c89SJason Evans * notice, this list of conditions and the following disclaimer. 1062ae6c89SJason Evans * 2. Redistributions in binary form must reproduce the above copyright 1162ae6c89SJason Evans * notice, this list of conditions and the following disclaimer in the 1262ae6c89SJason Evans * documentation and/or other materials provided with the distribution. 1362ae6c89SJason Evans * 4. Neither the name of the author nor the names of any co-contributors 1462ae6c89SJason Evans * may be used to endorse or promote products derived from this software 1562ae6c89SJason Evans * without specific prior written permission. 1662ae6c89SJason Evans * 170959cc66SJohn Baldwin * THIS SOFTWARE IS PROVIDED BY JOHN BALDWIN AND CONTRIBUTORS ``AS IS'' AND 1862ae6c89SJason Evans * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1962ae6c89SJason Evans * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 200959cc66SJohn Baldwin * ARE DISCLAIMED. IN NO EVENT SHALL JOHN BALDWIN OR THE VOICES IN HIS HEAD 2162ae6c89SJason Evans * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2262ae6c89SJason Evans * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2362ae6c89SJason Evans * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2462ae6c89SJason Evans * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2562ae6c89SJason Evans * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2662ae6c89SJason Evans * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 2762ae6c89SJason Evans * THE POSSIBILITY OF SUCH DAMAGE. 2862ae6c89SJason Evans * 2962ae6c89SJason Evans * $FreeBSD$ 3062ae6c89SJason Evans */ 3162ae6c89SJason Evans 3262ae6c89SJason Evans /* 33d8f03321SJohn Baldwin * This module holds the global variables used by KTR and the ktr_tracepoint() 34d8f03321SJohn Baldwin * function that does the actual tracing. 3562ae6c89SJason Evans */ 3662ae6c89SJason Evans 37de362218SJohn Baldwin #include "opt_ddb.h" 38d8f03321SJohn Baldwin #include "opt_ktr.h" 39d8f03321SJohn Baldwin 40de362218SJohn Baldwin #include <sys/param.h> 4162ae6c89SJason Evans #include <sys/types.h> 42de362218SJohn Baldwin #include <sys/cons.h> 4362ae6c89SJason Evans #include <sys/time.h> 44a0a7328bSJohn Baldwin #include <sys/kernel.h> 4562ae6c89SJason Evans #include <sys/ktr.h> 46d8f03321SJohn Baldwin #include <sys/libkern.h> 4762ae6c89SJason Evans #include <sys/linker_set.h> 4862ae6c89SJason Evans #include <sys/sysctl.h> 49d8f03321SJohn Baldwin #include <sys/systm.h> 50bf619f95SJohn Baldwin #include <machine/globals.h> 51d8f03321SJohn Baldwin #include <machine/stdarg.h> 52d8f03321SJohn Baldwin 53de362218SJohn Baldwin #include <ddb/ddb.h> 54de362218SJohn Baldwin 55d8f03321SJohn Baldwin #ifndef KTR_MASK 56d8f03321SJohn Baldwin #define KTR_MASK (KTR_GEN) 57d8f03321SJohn Baldwin #endif 58d8f03321SJohn Baldwin 59d8f03321SJohn Baldwin #ifndef KTR_CPUMASK 60d8f03321SJohn Baldwin #define KTR_CPUMASK (~0) 61d8f03321SJohn Baldwin #endif 62d8f03321SJohn Baldwin 63d8f03321SJohn Baldwin #ifdef SMP 64d8f03321SJohn Baldwin #define KTR_CPU cpuid 65d8f03321SJohn Baldwin #else 66d8f03321SJohn Baldwin #define KTR_CPU 0 67d8f03321SJohn Baldwin #endif 6862ae6c89SJason Evans 6962ae6c89SJason Evans #ifdef KTR_EXTEND 70a0a7328bSJohn Baldwin #define KTR_EXTEND_DEFAULT 1 71a0a7328bSJohn Baldwin #else 72a0a7328bSJohn Baldwin #define KTR_EXTEND_DEFAULT 0 73a0a7328bSJohn Baldwin #endif 74a0a7328bSJohn Baldwin 75a0a7328bSJohn Baldwin #ifdef KTR_VERBOSE 76a0a7328bSJohn Baldwin #define KTR_VERBOSE_DEFAULT 1 77a0a7328bSJohn Baldwin #else 78a0a7328bSJohn Baldwin #define KTR_VERBOSE_DEFAULT 0 79a0a7328bSJohn Baldwin #endif 80a0a7328bSJohn Baldwin 81a0a7328bSJohn Baldwin SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RD, 0, "KTR options"); 82a0a7328bSJohn Baldwin 8362ae6c89SJason Evans /* 8462ae6c89SJason Evans * This variable is used only by gdb to work out what fields are in 8562ae6c89SJason Evans * ktr_entry. 8662ae6c89SJason Evans */ 87a0a7328bSJohn Baldwin int ktr_extend = KTR_EXTEND_DEFAULT; 88a0a7328bSJohn Baldwin SYSCTL_INT(_debug_ktr, OID_AUTO, extend, CTLFLAG_RD, &ktr_extend, 0, ""); 8962ae6c89SJason Evans 90a0a7328bSJohn Baldwin int ktr_cpumask; 91a0a7328bSJohn Baldwin TUNABLE_INT_DECL("debug.ktr.cpumask", KTR_CPUMASK, ktr_cpumask); 92a0a7328bSJohn Baldwin SYSCTL_INT(_debug_ktr, OID_AUTO, cpumask, CTLFLAG_RW, &ktr_cpumask, 0, ""); 9362ae6c89SJason Evans 94a0a7328bSJohn Baldwin int ktr_mask; 95a0a7328bSJohn Baldwin TUNABLE_INT_DECL("debug.ktr.mask", KTR_MASK, ktr_mask); 96a0a7328bSJohn Baldwin SYSCTL_INT(_debug_ktr, OID_AUTO, mask, CTLFLAG_RW, &ktr_mask, 0, ""); 9762ae6c89SJason Evans 9862ae6c89SJason Evans int ktr_entries = KTR_ENTRIES; 99a0a7328bSJohn Baldwin SYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD, &ktr_entries, 0, ""); 10062ae6c89SJason Evans 10162ae6c89SJason Evans volatile int ktr_idx = 0; 10262ae6c89SJason Evans struct ktr_entry ktr_buf[KTR_ENTRIES]; 103d8f03321SJohn Baldwin 104a0a7328bSJohn Baldwin int ktr_verbose; 105a0a7328bSJohn Baldwin TUNABLE_INT_DECL("debug.ktr.verbose", KTR_VERBOSE_DEFAULT, ktr_verbose); 106a0a7328bSJohn Baldwin SYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0, ""); 107d8f03321SJohn Baldwin 108d8f03321SJohn Baldwin #ifdef KTR 109d8f03321SJohn Baldwin #ifdef KTR_EXTEND 110d8f03321SJohn Baldwin void 111d8f03321SJohn Baldwin ktr_tracepoint(u_int mask, char *filename, u_int line, char *format, ...) 112d8f03321SJohn Baldwin #else 113d8f03321SJohn Baldwin void 114d8f03321SJohn Baldwin ktr_tracepoint(u_int mask, char *format, u_long arg1, u_long arg2, u_long arg3, 115d8f03321SJohn Baldwin u_long arg4, u_long arg5) 116d8f03321SJohn Baldwin #endif 117d8f03321SJohn Baldwin { 118d8f03321SJohn Baldwin struct ktr_entry *entry; 119d8f03321SJohn Baldwin int newindex, saveindex, saveintr; 120d8f03321SJohn Baldwin #ifdef KTR_EXTEND 121d8f03321SJohn Baldwin va_list ap; 122d8f03321SJohn Baldwin #endif 123d8f03321SJohn Baldwin 124d664747bSJohn Baldwin if (panicstr) 125d664747bSJohn Baldwin return; 126d8f03321SJohn Baldwin if ((ktr_mask & mask) == 0) 127d8f03321SJohn Baldwin return; 128d8f03321SJohn Baldwin #ifdef KTR_EXTEND 129d8f03321SJohn Baldwin if (((1 << KTR_CPU) & ktr_cpumask) == 0) 130d8f03321SJohn Baldwin return; 131d8f03321SJohn Baldwin #endif 132d8f03321SJohn Baldwin saveintr = save_intr(); 133d8f03321SJohn Baldwin disable_intr(); 134d8f03321SJohn Baldwin do { 135d8f03321SJohn Baldwin saveindex = ktr_idx; 136d8f03321SJohn Baldwin newindex = (saveindex + 1) & (KTR_ENTRIES - 1); 137d8f03321SJohn Baldwin } while (atomic_cmpset_rel_int(&ktr_idx, saveindex, newindex) == 0); 138d8f03321SJohn Baldwin entry = &ktr_buf[saveindex]; 139d8f03321SJohn Baldwin restore_intr(saveintr); 1407fcd0cb3SGreg Lehey if (ktr_mask & KTR_LOCK) 1417fcd0cb3SGreg Lehey /* 1427fcd0cb3SGreg Lehey * We can't use nanotime with KTR_LOCK, it would cause 1437fcd0cb3SGreg Lehey * endless recursion, at least under the Intel 1447fcd0cb3SGreg Lehey * architecture. 1457fcd0cb3SGreg Lehey */ 146d664747bSJohn Baldwin getnanotime(&entry->ktr_tv); 1477fcd0cb3SGreg Lehey else 1487fcd0cb3SGreg Lehey nanotime(&entry->ktr_tv); 149d8f03321SJohn Baldwin #ifdef KTR_EXTEND 150d8f03321SJohn Baldwin strncpy(entry->ktr_filename, filename, KTRFILENAMESIZE - 1); 151d8f03321SJohn Baldwin entry->ktr_filename[KTRFILENAMESIZE - 1] = '\0'; 152d8f03321SJohn Baldwin entry->ktr_line = line; 153d8f03321SJohn Baldwin entry->ktr_cpu = KTR_CPU; 154d8f03321SJohn Baldwin va_start(ap, format); 155d8f03321SJohn Baldwin vsnprintf(entry->ktr_desc, KTRDESCSIZE, format, ap); 156d8f03321SJohn Baldwin va_end(ap); 157d8f03321SJohn Baldwin if (ktr_verbose) { 15822f1b342SJohn Baldwin #ifdef SMP 15922f1b342SJohn Baldwin printf("cpu%d ", entry->ktr_cpu); 16022f1b342SJohn Baldwin #endif 16122f1b342SJohn Baldwin if (ktr_verbose > 1) 16222f1b342SJohn Baldwin printf("%s.%d\t", entry->ktr_filename, entry->ktr_line); 163d8f03321SJohn Baldwin va_start(ap, format); 164d8f03321SJohn Baldwin vprintf(format, ap); 165d8f03321SJohn Baldwin printf("\n"); 166d8f03321SJohn Baldwin va_end(ap); 167d8f03321SJohn Baldwin } 168d8f03321SJohn Baldwin #else 169d8f03321SJohn Baldwin entry->ktr_desc = format; 170d8f03321SJohn Baldwin entry->ktr_parm1 = arg1; 171d8f03321SJohn Baldwin entry->ktr_parm2 = arg2; 172d8f03321SJohn Baldwin entry->ktr_parm3 = arg3; 173d8f03321SJohn Baldwin entry->ktr_parm4 = arg4; 174d8f03321SJohn Baldwin entry->ktr_parm5 = arg5; 175d8f03321SJohn Baldwin #endif 176d8f03321SJohn Baldwin } 177de362218SJohn Baldwin 178de362218SJohn Baldwin #ifdef DDB 179de362218SJohn Baldwin 180de362218SJohn Baldwin struct tstate { 181de362218SJohn Baldwin int cur; 182de362218SJohn Baldwin int first; 183de362218SJohn Baldwin }; 184de362218SJohn Baldwin static struct tstate tstate; 185de362218SJohn Baldwin static int db_ktr_verbose; 186de362218SJohn Baldwin static int db_mach_vtrace(void); 187de362218SJohn Baldwin 188de362218SJohn Baldwin DB_COMMAND(tbuf, db_mach_tbuf) 189de362218SJohn Baldwin { 190de362218SJohn Baldwin 191de362218SJohn Baldwin tstate.cur = (ktr_idx - 1) & (KTR_ENTRIES - 1); 192de362218SJohn Baldwin tstate.first = -1; 193de362218SJohn Baldwin if (strcmp(modif, "v") == 0) 194de362218SJohn Baldwin db_ktr_verbose = 1; 195de362218SJohn Baldwin else 196de362218SJohn Baldwin db_ktr_verbose = 0; 197de362218SJohn Baldwin db_mach_vtrace(); 198de362218SJohn Baldwin 199de362218SJohn Baldwin return; 200de362218SJohn Baldwin } 201de362218SJohn Baldwin 202de362218SJohn Baldwin DB_COMMAND(tall, db_mach_tall) 203de362218SJohn Baldwin { 204de362218SJohn Baldwin int c; 205de362218SJohn Baldwin 206de362218SJohn Baldwin db_mach_tbuf(addr, have_addr, count, modif); 207de362218SJohn Baldwin while (db_mach_vtrace()) { 208de362218SJohn Baldwin c = cncheckc(); 209de362218SJohn Baldwin if (c != -1) 210de362218SJohn Baldwin break; 211de362218SJohn Baldwin } 212de362218SJohn Baldwin 213de362218SJohn Baldwin return; 214de362218SJohn Baldwin } 215de362218SJohn Baldwin 216de362218SJohn Baldwin DB_COMMAND(tnext, db_mach_tnext) 217de362218SJohn Baldwin { 218de362218SJohn Baldwin 219de362218SJohn Baldwin if (strcmp(modif, "v") == 0) 220de362218SJohn Baldwin db_ktr_verbose ^= 1; 221de362218SJohn Baldwin db_mach_vtrace(); 222de362218SJohn Baldwin } 223de362218SJohn Baldwin 224de362218SJohn Baldwin static int 225de362218SJohn Baldwin db_mach_vtrace(void) 226de362218SJohn Baldwin { 227de362218SJohn Baldwin struct ktr_entry *kp; 228de362218SJohn Baldwin 229de362218SJohn Baldwin if (tstate.cur == tstate.first) { 230de362218SJohn Baldwin db_printf("--- End of trace buffer ---\n"); 231de362218SJohn Baldwin return (0); 232de362218SJohn Baldwin } 233de362218SJohn Baldwin kp = &ktr_buf[tstate.cur]; 234de362218SJohn Baldwin 235de362218SJohn Baldwin /* Skip over unused entries. */ 236de362218SJohn Baldwin #ifdef KTR_EXTEND 237de362218SJohn Baldwin if (kp->ktr_desc[0] != '\0') { 238de362218SJohn Baldwin #else 239de362218SJohn Baldwin if (kp->ktr_desc != NULL) { 240de362218SJohn Baldwin #endif 241de362218SJohn Baldwin db_printf("%d: ", tstate.cur); 242de362218SJohn Baldwin if (db_ktr_verbose) 243de362218SJohn Baldwin db_printf("%4ld.%06ld ", kp->ktr_tv.tv_sec, 244de362218SJohn Baldwin kp->ktr_tv.tv_nsec / 1000); 245de362218SJohn Baldwin #ifdef KTR_EXTEND 246de362218SJohn Baldwin #ifdef SMP 247de362218SJohn Baldwin db_printf("cpu%d ", kp->ktr_cpu); 248de362218SJohn Baldwin #endif 249de362218SJohn Baldwin if (db_ktr_verbose) 250de362218SJohn Baldwin db_printf("%s.%d\t", kp->ktr_filename, kp->ktr_line); 251de362218SJohn Baldwin db_printf("%s", kp->ktr_desc); 252de362218SJohn Baldwin #else 253de362218SJohn Baldwin db_printf(kp->ktr_desc, kp->ktr_parm1, kp->ktr_parm2, 254de362218SJohn Baldwin kp->ktr_parm3, kp->ktr_parm4, kp->ktr_parm5); 255de362218SJohn Baldwin #endif 256de362218SJohn Baldwin db_printf("\n"); 257de362218SJohn Baldwin } 258de362218SJohn Baldwin 259de362218SJohn Baldwin if (tstate.first == -1) 260de362218SJohn Baldwin tstate.first = tstate.cur; 261de362218SJohn Baldwin 262de362218SJohn Baldwin if (--tstate.cur < 0) 263de362218SJohn Baldwin tstate.cur = KTR_ENTRIES - 1; 264de362218SJohn Baldwin 265de362218SJohn Baldwin return (1); 266de362218SJohn Baldwin } 267de362218SJohn Baldwin 268de362218SJohn Baldwin #endif /* DDB */ 269d8f03321SJohn Baldwin #endif /* KTR */ 270