1 /*- 2 * Copyright (c) 2004 Eirik Nygaard <eirikn@kerneled.com> 3 * All rights reserved. 4 * Copyright (c) 2000 John Baldwin <jhb@FreeBSD.org> 5 * All rights reserved. 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 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the author nor the names of any co-contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 /* 33 * This module holds the global variables used by KTR and the ktr_tracepoint() 34 * function that does the actual tracing. 35 */ 36 37 /* 38 * $FreeBSD: src/sys/kern/kern_ktr.c,v 1.43 2003/09/10 01:09:32 jhb Exp $ 39 * $DragonFly: src/sys/kern/kern_ktr.c,v 1.4 2005/04/20 14:27:29 joerg Exp $ 40 */ 41 42 #include "opt_ddb.h" 43 #include "opt_ktr.h" 44 45 #include <sys/param.h> 46 #include <sys/cons.h> 47 #include <sys/kernel.h> 48 #include <sys/ktr.h> 49 #include <sys/libkern.h> 50 #include <sys/proc.h> 51 #include <sys/sysctl.h> 52 #include <sys/systm.h> 53 #include <sys/time.h> 54 #include <sys/malloc.h> 55 #include <sys/thread2.h> 56 #include <sys/ctype.h> 57 58 #include <machine/cpu.h> 59 #include <machine/cpufunc.h> 60 #include <machine/specialreg.h> 61 #include <machine/md_var.h> 62 63 #include <ddb/ddb.h> 64 65 #ifndef KTR_ENTRIES 66 #define KTR_ENTRIES 1024 67 #endif 68 69 #ifndef KTR_MASK 70 #define KTR_MASK (KTR_ALL) 71 #endif 72 73 #ifndef KTR_CPUMASK 74 #define KTR_CPUMASK (~0) 75 #endif 76 77 #ifndef KTR_TIME 78 #define KTR_TIME ktr_getts() 79 #endif 80 81 #ifndef KTR_CPU 82 #define KTR_CPU mycpu->gd_cpuid; 83 #endif 84 85 MALLOC_DEFINE(M_KTR, "ktr", "ktr buffers"); 86 87 SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RD, 0, "KTR options"); 88 89 int ktr_cpumask = KTR_CPUMASK; 90 TUNABLE_INT("debug.ktr.cpumask", &ktr_cpumask); 91 SYSCTL_INT(_debug_ktr, OID_AUTO, cpumask, CTLFLAG_RW, &ktr_cpumask, 0, ""); 92 93 int ktr_mask = KTR_MASK; 94 TUNABLE_INT("debug.ktr.mask", &ktr_mask); 95 SYSCTL_INT(_debug_ktr, OID_AUTO, mask, CTLFLAG_RW, &ktr_mask, 0, ""); 96 97 int ktr_entries = KTR_ENTRIES; 98 SYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD, &ktr_entries, 0, ""); 99 100 int ktr_version = KTR_VERSION; 101 SYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD, &ktr_version, 0, ""); 102 103 int ktr_discarded; 104 SYSCTL_INT(_debug_ktr, OID_AUTO, discarded, CTLFLAG_RD, &ktr_discarded, 0, ""); 105 106 volatile int ktr_idx[MAXCPU], ktr_initiated = 0; 107 struct ktr_entry *ktr_buf[MAXCPU]; 108 109 #ifdef KTR_VERBOSE 110 int ktr_verbose = KTR_VERBOSE; 111 TUNABLE_INT("debug.ktr.verbose", &ktr_verbose); 112 SYSCTL_INT(_debug_ktr, OID_AUTO, verbose, CTLFLAG_RW, &ktr_verbose, 0, ""); 113 #endif 114 115 static void 116 ktr_sysinit(void *dummy) 117 { 118 int i; 119 120 for(i = 0; i < ncpus; i++) { 121 ktr_buf[i] = malloc(KTR_ENTRIES * sizeof(struct ktr_entry), 122 M_KTR, M_WAITOK); 123 ktr_idx[i] = -1; 124 } 125 ktr_initiated++; 126 } 127 SYSINIT(announce, SI_SUB_INTRINSIC, SI_ORDER_FIRST, ktr_sysinit, NULL); 128 129 static __inline int 130 ktr_nextindex(int cpu) 131 { 132 int ktrindex; 133 134 crit_enter(); 135 ktrindex = ktr_idx[cpu] = (ktr_idx[cpu] + 1) & (KTR_ENTRIES - 1); 136 crit_exit(); 137 return(ktrindex); 138 } 139 140 static __inline uint64_t 141 ktr_getts(void) 142 { 143 if (cpu_feature & CPUID_TSC) 144 return(rdtsc()); 145 return(get_approximate_time_t()); 146 } 147 148 void 149 ktr_tracepoint(u_int mask, const char *file, int line, const char *format, 150 u_long arg1, u_long arg2, u_long arg3, u_long arg4, u_long arg5, 151 u_long arg6) 152 { 153 struct ktr_entry *entry; 154 int cpu, newindex; 155 156 if (ktr_initiated == 0) { 157 ktr_discarded++; 158 return; 159 } 160 if (panicstr) 161 return; 162 if ((ktr_mask & mask) == 0) 163 return; 164 cpu = KTR_CPU; 165 if (((1 << cpu) & ktr_cpumask) == 0) 166 return; 167 newindex = ktr_nextindex(cpu); 168 entry = &ktr_buf[cpu][newindex]; 169 entry->ktr_timestamp = KTR_TIME; 170 entry->ktr_cpu = cpu; 171 if (file != NULL) 172 while (strncmp(file, "../", 3) == 0) 173 file += 3; 174 entry->ktr_file = file; 175 entry->ktr_line = line; 176 #ifdef KTR_VERBOSE 177 if (ktr_verbose) { 178 #ifdef SMP 179 printf("cpu%d ", cpu); 180 #endif 181 if (ktr_verbose > 1) { 182 printf("%s.%d\t", entry->ktr_file, entry->ktr_line); 183 } 184 printf(format, arg1, arg2, arg3, arg4, arg5, arg6); 185 printf("\n"); 186 } 187 #endif 188 entry->ktr_desc = format; 189 entry->ktr_parms[0] = arg1; 190 entry->ktr_parms[1] = arg2; 191 entry->ktr_parms[2] = arg3; 192 entry->ktr_parms[3] = arg4; 193 entry->ktr_parms[4] = arg5; 194 entry->ktr_parms[5] = arg6; 195 } 196 197 #ifdef DDB 198 199 #define NUM_LINES_PER_PAGE 19 200 201 struct tstate { 202 int cur; 203 int first; 204 }; 205 static int db_ktr_verbose; 206 static int db_mach_vtrace(struct ktr_entry *kp, int idx); 207 208 DB_SHOW_COMMAND(ktr, db_ktr_all) 209 { 210 int a_flag = 0; 211 int c; 212 int nl = 0; 213 int i; 214 struct tstate tstate[MAXCPU]; 215 int printcpu = -1; 216 217 for(i = 0; i < ncpus; i++) { 218 tstate[i].first = -1; 219 tstate[i].cur = ktr_idx[i]; 220 } 221 db_ktr_verbose = 0; 222 while ((c = *(modif++)) != '\0') { 223 if (c == 'v') { 224 db_ktr_verbose = 1; 225 } 226 else if (c == 'a') { 227 a_flag = 1; 228 } 229 else if (c == 'c') { 230 printcpu = 0; 231 while ((c = *(modif++)) != '\0') { 232 if (isdigit(c)) { 233 printcpu *= 10; 234 printcpu += c - '0'; 235 } 236 else { 237 modif++; 238 break; 239 } 240 } 241 modif--; 242 } 243 } 244 if (printcpu > ncpus - 1) { 245 db_printf("Invalid cpu number\n"); 246 return; 247 } 248 /* 249 * Lopp throug all the buffers and print the content of them, sorted 250 * by the timestamp. 251 */ 252 while (1) { 253 int counter; 254 u_int64_t highest_ts; 255 int highest_cpu; 256 struct ktr_entry *kp; 257 258 if (a_flag == 1 && cncheckc() != -1) 259 return; 260 highest_ts = 0; 261 highest_cpu = -1; 262 /* 263 * Find the lowest timestamp 264 */ 265 for (i = 0, counter = 0; i < ncpus; i++) { 266 if (printcpu != -1 && printcpu != i) 267 continue; 268 if (tstate[i].cur == -1) { 269 counter++; 270 if (counter == ncpus) { 271 db_printf("--- End of trace buffer ---\n"); 272 return; 273 } 274 continue; 275 } 276 if (ktr_buf[i][tstate[i].cur].ktr_timestamp > highest_ts) { 277 highest_ts = ktr_buf[i][tstate[i].cur].ktr_timestamp; 278 highest_cpu = i; 279 } 280 } 281 i = highest_cpu; 282 KKASSERT(i != -1); 283 kp = &ktr_buf[i][tstate[i].cur]; 284 if (tstate[i].first == -1) 285 tstate[i].first = tstate[i].cur; 286 if (--tstate[i].cur < 0) 287 tstate[i].cur = KTR_ENTRIES - 1; 288 if (tstate[i].first == tstate[i].cur) { 289 db_mach_vtrace(kp, tstate[i].cur + 1); 290 tstate[i].cur = -1; 291 continue; 292 } 293 if (ktr_buf[i][tstate[i].cur].ktr_desc == NULL) 294 tstate[i].cur = -1; 295 if (db_more(&nl) == -1) 296 break; 297 if (db_mach_vtrace(kp, tstate[i].cur + 1) == 0) 298 tstate[i].cur = -1; 299 } 300 } 301 302 static int 303 db_mach_vtrace(struct ktr_entry *kp, int idx) 304 { 305 if (kp->ktr_desc == NULL) 306 return(0); 307 #ifdef SMP 308 db_printf("cpu%d ", kp->ktr_cpu); 309 #endif 310 db_printf("%d: ", idx); 311 if (db_ktr_verbose) { 312 db_printf("%10.10lld %s.%d\t", (long long)kp->ktr_timestamp, 313 kp->ktr_file, kp->ktr_line); 314 } 315 db_printf(kp->ktr_desc, kp->ktr_parms[0], kp->ktr_parms[1], 316 kp->ktr_parms[2], kp->ktr_parms[3], kp->ktr_parms[4], 317 kp->ktr_parms[5]); 318 db_printf("\n"); 319 320 return(1); 321 } 322 323 #endif /* DDB */ 324