diff options
-rw-r--r-- | sys/alpha/alpha/db_interface.c | 148 | ||||
-rw-r--r-- | sys/amd64/amd64/db_interface.c | 121 | ||||
-rw-r--r-- | sys/i386/i386/db_interface.c | 121 | ||||
-rw-r--r-- | sys/kern/kern_ktr.c | 64 | ||||
-rw-r--r-- | sys/kern/kern_ktrace.c | 16 | ||||
-rw-r--r-- | sys/sys/ktr.h | 319 | ||||
-rw-r--r-- | sys/sys/ktrace.h | 2 |
7 files changed, 770 insertions, 21 deletions
diff --git a/sys/alpha/alpha/db_interface.c b/sys/alpha/alpha/db_interface.c index 1e015ae..bb3fbf8 100644 --- a/sys/alpha/alpha/db_interface.c +++ b/sys/alpha/alpha/db_interface.c @@ -58,12 +58,15 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/cons.h> +#include <sys/ktr.h> #include <vm/vm.h> #include <machine/db_machdep.h> #include <machine/pal.h> #include <machine/prom.h> +#include <machine/mutex.h> +#include <machine/smp.h> #include <alpha/alpha/db_instruction.h> @@ -163,6 +166,7 @@ kdb_trap(a0, a1, a2, entry, regs) if (entry != ALPHA_KENTRY_IF || (a0 != ALPHA_IF_CODE_BUGCHK && a0 != ALPHA_IF_CODE_BPT && a0 != ALPHA_IF_CODE_GENTRAP)) { +#if 0 if (ddb_mode) { db_printf("ddbprinttrap from 0x%lx\n", /* XXX */ regs->tf_regs[FRAME_PC]); @@ -173,9 +177,11 @@ kdb_trap(a0, a1, a2, entry, regs) */ return (0); } +#endif if (db_nofault) { jmp_buf *no_fault = db_nofault; db_nofault = 0; + mtx_exit(&Giant, MTX_DEF); longjmp(*no_fault, 1); } } @@ -188,6 +194,12 @@ kdb_trap(a0, a1, a2, entry, regs) s = splhigh(); +#if 0 + db_printf("stopping %x\n", PCPU_GET(other_cpus)); + stop_cpus(PCPU_GET(other_cpus)); + db_printf("stopped_cpus=%x\n", stopped_cpus); +#endif + db_active++; if (ddb_mode) { @@ -199,6 +211,10 @@ kdb_trap(a0, a1, a2, entry, regs) db_active--; +#if 0 + restart_cpus(stopped_cpus); +#endif + splx(s); *regs = ddb_regs; @@ -546,3 +562,135 @@ db_branch_taken(ins, pc, regs) return (newpc); } + +#ifdef KTR + +static struct { + int cur; + int first; +} tstate[NCPUS]; +static struct timespec lastt; +static int db_tcpu = 0xff; +static int db_mach_vtrace(void); + +DB_COMMAND(tbuf, db_mach_tbuf) +{ + int i; + + for (i = 0; i < NCPUS; i++) { + struct ktr_entry *k1, *ck, *kend; + struct globaldata *pp; + struct timespec newk; + + if ((pp = globaldata_find(i)) == NULL) + continue; + + k1 = (struct ktr_entry *)pp->gd_ktr_buf; + ck = k1; + timespecclear(&newk); + kend = (struct ktr_entry *)(pp->gd_ktr_buf + KTR_SIZE); + while (k1 != kend) { + if (timespecisset(&k1->ktr_tv) && + timespeccmp(&k1->ktr_tv, &newk, >)) { + newk = k1->ktr_tv; + ck = k1; + } + k1++; + } + tstate[i].cur = ((uintptr_t)(ck) - + (uintptr_t)pp->gd_ktr_buf) & (KTR_ESIZE-1); + tstate[i].first = tstate[i].cur | 0x80000000; + } + timespecclear(&lastt); + db_mach_vtrace(); + return; +} + +/* + * Print all trace entries + */ +DB_COMMAND(tall, db_mach_tall) +{ + int c; + + db_mach_tbuf(addr, have_addr, count, modif); + while (db_mach_vtrace()) { + c = cncheckc(); + if (c != -1) + break; + } + return; +} + +DB_COMMAND(tnext, db_mach_tnext) +{ + db_mach_vtrace(); +} + +static int +db_mach_vtrace(void) +{ + struct ktr_entry *kp; + struct ktr_entry *kpt; + char *d; + int i; + int wcpu; + struct globaldata *pp; + struct timespec ts; + + /* Pick the newest trace entry from all CPU's */ + kp = NULL; + wcpu = 0; + for (i = 0; i < NCPUS; i++) { + if (db_tcpu != 0xff && i != db_tcpu) + continue; + if (!(pp = globaldata_find(i))) + continue; + if (tstate[i].cur == tstate[i].first) + continue; + kpt = (struct ktr_entry *)((char *)pp->gd_ktr_buf + + tstate[i].cur); + if (!kp || timespeccmp(&kp->ktr_tv, &kpt->ktr_tv, <)) { + kp = kpt; + wcpu = i; + } + } + if (!kp) { + db_printf("--- End of trace buffer ---\n"); + return (0); + } + + d = kp->ktr_desc; + if (d == NULL) + d = "*** Empty ***"; +#if 0 + if (kernacc(d, 80, B_READ) == 0) + d = "*** Corrupt entry ***"; +#endif + else if (lastt.tv_sec == 0) { + db_printf("Newest entry at clock %d.%06ld\n", + kp->ktr_tv.tv_sec, + kp->ktr_tv.tv_nsec / 1000); + lastt = kp->ktr_tv; + } + db_printf("\r%x %3x ", wcpu, tstate[wcpu].cur >> KTR_SHFT); + ts = lastt; + /* timespecsub(&ts, &kp->ktr_tv); */ + db_printf("%4d.%06ld: ", ts.tv_sec, ts.tv_nsec / 1000); + lastt = kp->ktr_tv; + db_printf(d, kp->ktr_parm1, kp->ktr_parm2, kp->ktr_parm3, + kp->ktr_parm4, kp->ktr_parm5); +#if 0 + if (kdebug_vflag) + db_printf(" p1=%x p2=%x p3=%x p4=%x p5=%x", (u_int)kp->ktr_parm1, + (u_int)kp->ktr_parm2, (u_int)kp->ktr_parm3, + (u_int)kp->ktr_parm4, (u_int)kp->ktr_parm5); +#endif + db_printf("\n"); + tstate[wcpu].first &= ~0x80000000; + tstate[wcpu].cur = (tstate[wcpu].cur - sizeof(struct ktr_entry)) & + (KTR_ESIZE - 1); + return (1); +} + +#endif diff --git a/sys/amd64/amd64/db_interface.c b/sys/amd64/amd64/db_interface.c index b3dd292..a801301 100644 --- a/sys/amd64/amd64/db_interface.c +++ b/sys/amd64/amd64/db_interface.c @@ -33,6 +33,8 @@ #include <sys/systm.h> #include <sys/reboot.h> #include <sys/cons.h> +#include <sys/linker_set.h> +#include <sys/ktr.h> #include <machine/cpu.h> #ifdef SMP @@ -44,6 +46,9 @@ #include <vm/pmap.h> #include <ddb/ddb.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> #include <setjmp.h> @@ -137,14 +142,14 @@ kdb_trap(type, code, regs) #ifdef CPUSTOP_ON_DDBBREAK #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, other_cpus); + db_printf("\nCPU%d stopping CPUs: 0x%08x...", cpuid, other_cpus); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ /* We stop all CPUs except ourselves (obviously) */ stop_cpus(other_cpus); #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" stopped\n"); + db_printf(" stopped.\n"); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ #endif /* CPUSTOP_ON_DDBBREAK */ @@ -166,7 +171,7 @@ kdb_trap(type, code, regs) #ifdef CPUSTOP_ON_DDBBREAK #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d restarting CPUs: 0x%08x\n", cpuid, stopped_cpus); + db_printf("\nCPU%d restarting CPUs: 0x%08x...", cpuid, stopped_cpus); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ /* Restart all the CPUs we previously stopped */ @@ -178,7 +183,7 @@ kdb_trap(type, code, regs) restart_cpus(stopped_cpus); #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" restarted\n"); + db_printf(" restarted.\n"); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ #endif /* CPUSTOP_ON_DDBBREAK */ @@ -301,8 +306,8 @@ void Debugger(msg) const char *msg; { - static volatile u_char in_Debugger; - + static volatile u_char in_Debugger; + int flags; /* * XXX * Do nothing if the console is in graphics mode. This is @@ -313,9 +318,113 @@ Debugger(msg) return; if (!in_Debugger) { + flags = save_intr(); + disable_intr(); in_Debugger = 1; db_printf("Debugger(\"%s\")\n", msg); breakpoint(); in_Debugger = 0; + restore_intr(flags); + } +} + +#if defined(KTR) + +struct tstate { + int cur; + int first; +}; +static struct tstate tstate; +static struct timespec lastt; +static int db_mach_vtrace(void); + +DB_COMMAND(tbuf, db_mach_tbuf) +{ + struct ktr_entry *k1, *ck, *kend; + struct timespec newk; + + k1 = ktr_buf; + ck = k1; + timespecclear(&newk); + kend = ktr_buf + KTR_ENTRIES; + while (k1 != kend) { + if (timespecisset(&k1->ktr_tv) && + timespeccmp(&k1->ktr_tv, &newk, >)) { + newk = k1->ktr_tv; + ck = k1; + } + k1++; } + tstate.cur = ck - ktr_buf; + tstate.first = tstate.cur | 0x80000000; + timespecclear(&lastt); + db_mach_vtrace(); + + return; +} + +DB_COMMAND(tall, db_mach_tall) +{ + int c; + + db_mach_tbuf(addr, have_addr, count, modif); + while (db_mach_vtrace()) { + c = cncheckc(); + if (c != -1) + break; + } + + return; } + +DB_COMMAND(tnext, db_mach_tnext) +{ + db_mach_vtrace(); +} + +static int +db_mach_vtrace(void) +{ + struct ktr_entry *kp; + struct timespec ts; + char *d; + + kp = NULL; + if (tstate.cur != tstate.first) + kp = ktr_buf + tstate.cur; + else + kp = NULL; + + if (!kp) { + db_printf("--- End of trace buffer ---\n"); + return (0); + } + + d = kp->ktr_desc; + if (d == NULL) + d = "*** Empty ***"; + else if (lastt.tv_sec == 0) { + db_printf("Newest entry at clock %ld.%06ld\n", + kp->ktr_tv.tv_sec, + kp->ktr_tv.tv_nsec / 1000); + lastt = kp->ktr_tv; + } + ts = lastt; + db_printf("%4ld.%06ld: ", ts.tv_sec, ts.tv_nsec / 1000); + lastt = kp->ktr_tv; +#ifdef KTR_EXTEND + db_printf("cpu%d %s.%d\t%s", kp->ktr_cpu, kp->ktr_filename, + kp->ktr_line, kp->ktr_desc); +#else + db_printf(d, kp->ktr_parm1, kp->ktr_parm2, kp->ktr_parm3, + kp->ktr_parm4, kp->ktr_parm5); +#endif + db_printf("\n"); + tstate.first &= ~0x80000000; + if (--tstate.cur < 0) + tstate.cur = KTR_ENTRIES - 1; + + return (1); +} + +#endif diff --git a/sys/i386/i386/db_interface.c b/sys/i386/i386/db_interface.c index b3dd292..a801301 100644 --- a/sys/i386/i386/db_interface.c +++ b/sys/i386/i386/db_interface.c @@ -33,6 +33,8 @@ #include <sys/systm.h> #include <sys/reboot.h> #include <sys/cons.h> +#include <sys/linker_set.h> +#include <sys/ktr.h> #include <machine/cpu.h> #ifdef SMP @@ -44,6 +46,9 @@ #include <vm/pmap.h> #include <ddb/ddb.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_variables.h> #include <setjmp.h> @@ -137,14 +142,14 @@ kdb_trap(type, code, regs) #ifdef CPUSTOP_ON_DDBBREAK #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d stopping CPUs: 0x%08x\n", cpuid, other_cpus); + db_printf("\nCPU%d stopping CPUs: 0x%08x...", cpuid, other_cpus); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ /* We stop all CPUs except ourselves (obviously) */ stop_cpus(other_cpus); #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" stopped\n"); + db_printf(" stopped.\n"); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ #endif /* CPUSTOP_ON_DDBBREAK */ @@ -166,7 +171,7 @@ kdb_trap(type, code, regs) #ifdef CPUSTOP_ON_DDBBREAK #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf("\nCPU%d restarting CPUs: 0x%08x\n", cpuid, stopped_cpus); + db_printf("\nCPU%d restarting CPUs: 0x%08x...", cpuid, stopped_cpus); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ /* Restart all the CPUs we previously stopped */ @@ -178,7 +183,7 @@ kdb_trap(type, code, regs) restart_cpus(stopped_cpus); #if defined(VERBOSE_CPUSTOP_ON_DDBBREAK) - db_printf(" restarted\n"); + db_printf(" restarted.\n"); #endif /* VERBOSE_CPUSTOP_ON_DDBBREAK */ #endif /* CPUSTOP_ON_DDBBREAK */ @@ -301,8 +306,8 @@ void Debugger(msg) const char *msg; { - static volatile u_char in_Debugger; - + static volatile u_char in_Debugger; + int flags; /* * XXX * Do nothing if the console is in graphics mode. This is @@ -313,9 +318,113 @@ Debugger(msg) return; if (!in_Debugger) { + flags = save_intr(); + disable_intr(); in_Debugger = 1; db_printf("Debugger(\"%s\")\n", msg); breakpoint(); in_Debugger = 0; + restore_intr(flags); + } +} + +#if defined(KTR) + +struct tstate { + int cur; + int first; +}; +static struct tstate tstate; +static struct timespec lastt; +static int db_mach_vtrace(void); + +DB_COMMAND(tbuf, db_mach_tbuf) +{ + struct ktr_entry *k1, *ck, *kend; + struct timespec newk; + + k1 = ktr_buf; + ck = k1; + timespecclear(&newk); + kend = ktr_buf + KTR_ENTRIES; + while (k1 != kend) { + if (timespecisset(&k1->ktr_tv) && + timespeccmp(&k1->ktr_tv, &newk, >)) { + newk = k1->ktr_tv; + ck = k1; + } + k1++; } + tstate.cur = ck - ktr_buf; + tstate.first = tstate.cur | 0x80000000; + timespecclear(&lastt); + db_mach_vtrace(); + + return; +} + +DB_COMMAND(tall, db_mach_tall) +{ + int c; + + db_mach_tbuf(addr, have_addr, count, modif); + while (db_mach_vtrace()) { + c = cncheckc(); + if (c != -1) + break; + } + + return; } + +DB_COMMAND(tnext, db_mach_tnext) +{ + db_mach_vtrace(); +} + +static int +db_mach_vtrace(void) +{ + struct ktr_entry *kp; + struct timespec ts; + char *d; + + kp = NULL; + if (tstate.cur != tstate.first) + kp = ktr_buf + tstate.cur; + else + kp = NULL; + + if (!kp) { + db_printf("--- End of trace buffer ---\n"); + return (0); + } + + d = kp->ktr_desc; + if (d == NULL) + d = "*** Empty ***"; + else if (lastt.tv_sec == 0) { + db_printf("Newest entry at clock %ld.%06ld\n", + kp->ktr_tv.tv_sec, + kp->ktr_tv.tv_nsec / 1000); + lastt = kp->ktr_tv; + } + ts = lastt; + db_printf("%4ld.%06ld: ", ts.tv_sec, ts.tv_nsec / 1000); + lastt = kp->ktr_tv; +#ifdef KTR_EXTEND + db_printf("cpu%d %s.%d\t%s", kp->ktr_cpu, kp->ktr_filename, + kp->ktr_line, kp->ktr_desc); +#else + db_printf(d, kp->ktr_parm1, kp->ktr_parm2, kp->ktr_parm3, + kp->ktr_parm4, kp->ktr_parm5); +#endif + db_printf("\n"); + tstate.first &= ~0x80000000; + if (--tstate.cur < 0) + tstate.cur = KTR_ENTRIES - 1; + + return (1); +} + +#endif diff --git a/sys/kern/kern_ktr.c b/sys/kern/kern_ktr.c new file mode 100644 index 0000000..486379d --- /dev/null +++ b/sys/kern/kern_ktr.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2000 + * John Baldwin <jhb@FreeBSD.org>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * This module holds the global variables used by KTR. + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/ktr.h> +#include <sys/linker_set.h> +#include <sys/sysctl.h> + +#ifdef KTR_EXTEND +/* + * This variable is used only by gdb to work out what fields are in + * ktr_entry. + */ +int ktr_extend = 1; +SYSCTL_INT(_debug, OID_AUTO, ktr_extend, CTLFLAG_RD, &ktr_extend, 1, ""); +#else +int ktr_extend = 0; +SYSCTL_INT(_debug, OID_AUTO, ktr_extend, CTLFLAG_RD, &ktr_extend, 0, ""); +#endif + +int ktr_cpumask = KTR_CPUMASK; +SYSCTL_INT(_debug, OID_AUTO, ktr_cpumask, CTLFLAG_RW, &ktr_cpumask, KTR_CPUMASK, ""); + +int ktr_mask = KTR_MASK; +SYSCTL_INT(_debug, OID_AUTO, ktr_mask, CTLFLAG_RW, &ktr_mask, KTR_MASK, ""); + +int ktr_entries = KTR_ENTRIES; +SYSCTL_INT(_debug, OID_AUTO, ktr_entries, CTLFLAG_RD, &ktr_entries, KTR_ENTRIES, ""); + +volatile int ktr_idx = 0; +struct ktr_entry ktr_buf[KTR_ENTRIES]; diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index ef82c6c..e51f8d1 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -100,7 +100,7 @@ ktrsyscall(vp, code, narg, args) argp = &ktp->ktr_args[0]; for (i = 0; i < narg; i++) *argp++ = args[i]; - kth->ktr_buf = (caddr_t)ktp; + kth->ktr_buffer = (caddr_t)ktp; kth->ktr_len = len; ktrwrite(vp, kth, NULL); FREE(ktp, M_KTRACE); @@ -124,7 +124,7 @@ ktrsysret(vp, code, error, retval) ktp.ktr_error = error; ktp.ktr_retval = retval; /* what about val2 ? */ - kth->ktr_buf = (caddr_t)&ktp; + kth->ktr_buffer = (caddr_t)&ktp; kth->ktr_len = sizeof(struct ktr_sysret); ktrwrite(vp, kth, NULL); @@ -143,7 +143,7 @@ ktrnamei(vp, path) p->p_traceflag |= KTRFAC_ACTIVE; kth = ktrgetheader(KTR_NAMEI); kth->ktr_len = strlen(path); - kth->ktr_buf = path; + kth->ktr_buffer = path; ktrwrite(vp, kth, NULL); FREE(kth, M_KTRACE); @@ -168,7 +168,7 @@ ktrgenio(vp, fd, rw, uio, error) kth = ktrgetheader(KTR_GENIO); ktg.ktr_fd = fd; ktg.ktr_rw = rw; - kth->ktr_buf = (caddr_t)&ktg; + kth->ktr_buffer = (caddr_t)&ktg; kth->ktr_len = sizeof(struct ktr_genio); uio->uio_offset = 0; uio->uio_rw = UIO_WRITE; @@ -196,7 +196,7 @@ ktrpsig(vp, sig, action, mask, code) kp.action = action; kp.mask = *mask; kp.code = code; - kth->ktr_buf = (caddr_t)&kp; + kth->ktr_buffer = (caddr_t)&kp; kth->ktr_len = sizeof (struct ktr_psig); ktrwrite(vp, kth, NULL); @@ -217,7 +217,7 @@ ktrcsw(vp, out, user) kth = ktrgetheader(KTR_CSW); kc.out = out; kc.user = user; - kth->ktr_buf = (caddr_t)&kc; + kth->ktr_buffer = (caddr_t)&kc; kth->ktr_len = sizeof (struct ktr_csw); ktrwrite(vp, kth, NULL); @@ -365,7 +365,7 @@ utrace(curp, uap) kth = ktrgetheader(KTR_USER); MALLOC(cp, caddr_t, uap->len, M_KTRACE, M_WAITOK); if (!copyin(uap->addr, cp, uap->len)) { - kth->ktr_buf = cp; + kth->ktr_buffer = cp; kth->ktr_len = uap->len; ktrwrite(p->p_tracep, kth, NULL); } @@ -474,7 +474,7 @@ ktrwrite(vp, kth, uio) auio.uio_procp = curproc; if (kth->ktr_len > 0) { auio.uio_iovcnt++; - aiov[1].iov_base = kth->ktr_buf; + aiov[1].iov_base = kth->ktr_buffer; aiov[1].iov_len = kth->ktr_len; auio.uio_resid += kth->ktr_len; if (uio != NULL) diff --git a/sys/sys/ktr.h b/sys/sys/ktr.h new file mode 100644 index 0000000..fcafa6e --- /dev/null +++ b/sys/sys/ktr.h @@ -0,0 +1,319 @@ +/*- + * Copyright (c) 1996 Berkeley Software Design, Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Berkeley Software Design Inc's name may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from BSDI $Id: ktr.h,v 1.10.2.7 2000/03/16 21:44:42 cp Exp $ + * $FreeBSD$ + */ + +/* + * Wraparound kernel trace buffer support. + */ + +#ifndef _SYS_KTR_H_ +#define _SYS_KTR_H_ + +/* Requires sys/types.h, sys/time.h, machine/atomic.h, and machine/cpufunc.h */ + +#include <machine/atomic.h> +#include <machine/cpufunc.h> + +/* + * Trace classes + */ +#define KTR_GEN 0x00000001 /* General (TR) */ +#define KTR_NET 0x00000002 /* Network */ +#define KTR_DEV 0x00000004 /* Device driver */ +#define KTR_LOCK 0x00000008 /* MP locking */ +#define KTR_SMP 0x00000010 /* MP general */ +#define KTR_FS 0x00000020 /* Filesystem */ +#define KTR_PMAP 0x00000040 /* Pmap tracing */ +#define KTR_MALLOC 0x00000080 /* Malloc tracing */ +#define KTR_TRAP 0x00000100 /* Trap processing */ +#define KTR_INTR 0x00000200 /* Interrupt tracing */ +#define KTR_SIG 0x00000400 /* Signal processing */ +#define KTR_CLK 0x00000800 /* hardclock verbose */ +#define KTR_PROC 0x00001000 /* Process scheduling */ +#define KTR_SYSC 0x00002000 /* System call */ +#define KTR_INIT 0x00004000 /* System initialization */ +#define KTR_KGDB 0x00008000 /* Trace kgdb internals */ +#define KTR_IO 0x00010000 /* Upper I/O */ +#define KTR_LOCKMGR 0x00020000 +#define KTR_NFS 0x00040000 /* The obvious */ +#define KTR_VOP 0x00080000 /* The obvious */ +#define KTR_VM 0x00100000 /* The virtual memory system */ +#define KTR_IDLELOOP 0x00200000 /* checks done in the idle process */ + +/* + * Trace classes which can be assigned to particular use at compile time + * These must remain in high 22 as some assembly code counts on it + */ +#define KTR_CT1 0x010000000 +#define KTR_CT2 0x020000000 +#define KTR_CT3 0x040000000 +#define KTR_CT4 0x080000000 +#define KTR_CT5 0x100000000 +#define KTR_CT6 0x200000000 +#define KTR_CT7 0x400000000 +#define KTR_CT8 0x800000000 + +/* Trace classes to compile in */ +#ifndef KTR_COMPILE +#define KTR_COMPILE (KTR_GEN) +#endif + +#ifndef KTR_MASK +#define KTR_MASK (KTR_GEN) +#endif + +#ifndef KTR_CPUMASK +#define KTR_CPUMASK (~0) +#endif + +#ifndef LOCORE + +#include <sys/time.h> + +struct ktr_entry { + struct timespec ktr_tv; +#ifdef KTR_EXTEND +#ifndef KTRDESCSIZE +#define KTRDESCSIZE 80 +#endif +#ifndef KTRFILENAMESIZE +#define KTRFILENAMESIZE 32 +#endif + char ktr_desc [KTRDESCSIZE]; + char ktr_filename [KTRFILENAMESIZE]; + int ktr_line; + int ktr_cpu; +#else + char *ktr_desc; + u_long ktr_parm1; + u_long ktr_parm2; + u_long ktr_parm3; + u_long ktr_parm4; + u_long ktr_parm5; +#endif +}; + +/* These variables are used by gdb to analyse the output */ +extern int ktr_extend; + +extern int ktr_cpumask; +extern int ktr_mask; +extern int ktr_entries; + +extern volatile int ktr_idx; +extern struct ktr_entry ktr_buf[]; + +#endif /* !LOCORE */ +#ifdef KTR + +#ifndef KTR_ENTRIES +#define KTR_ENTRIES 1024 +#endif + +#ifdef KTR_EXTEND +#ifndef _TR_CPU +#ifdef SMP +#define _TR_CPU cpuid +#else +#define _TR_CPU 0 +#endif +#endif +#ifndef _TR +#define _TR() \ + struct ktr_entry *_ktrptr; \ + int _ktr_newidx, _ktr_saveidx; \ + int _tr_intrsave = save_intr(); \ + disable_intr(); \ + do { \ + _ktr_saveidx = ktr_idx; \ + _ktr_newidx = (ktr_idx + 1) % KTR_ENTRIES; \ + } while (atomic_cmpset_int(&ktr_idx, _ktr_saveidx, _ktr_newidx) == 0); \ + _ktrptr = &ktr_buf[_ktr_saveidx]; \ + restore_intr(_tr_intrsave); \ + nanotime(&_ktrptr->ktr_tv); \ + snprintf (_ktrptr->ktr_filename, KTRFILENAMESIZE, "%s", __FILE__); \ + _ktrptr->ktr_line = __LINE__; \ + _ktrptr->ktr_cpu = _TR_CPU; +#endif +#define CTR0(m, _desc) \ + if (KTR_COMPILE & m) { \ + if ((ktr_mask & (m)) && ((1 << _TR_CPU) & ktr_cpumask)) { \ + _TR() \ + memcpy (_ktrptr->ktr_desc, _desc, KTRDESCSIZE); \ + } \ + } +#define CTR1(m, _desc, _p1) \ + if (KTR_COMPILE & m) { \ + if ((ktr_mask & (m)) && ((1 << _TR_CPU) & ktr_cpumask)) { \ + _TR() \ + snprintf (_ktrptr->ktr_desc, KTRDESCSIZE, _desc, _p1); \ + } \ + } +#define CTR2(m, _desc, _p1, _p2) \ + if (KTR_COMPILE & m) { \ + if ((ktr_mask & (m)) && ((1 << _TR_CPU) & ktr_cpumask)) { \ + _TR() \ + snprintf (_ktrptr->ktr_desc, KTRDESCSIZE, _desc, _p1, _p2); \ + } \ + } +#define CTR3(m, _desc, _p1, _p2, _p3) \ + if (KTR_COMPILE & m) { \ + if ((ktr_mask & (m)) && ((1 << _TR_CPU) & ktr_cpumask)) { \ + _TR() \ + snprintf (_ktrptr->ktr_desc, KTRDESCSIZE, _desc, _p1, _p2, _p3); \ + } \ + } +#define CTR4(m, _desc, _p1, _p2, _p3, _p4) \ + if (KTR_COMPILE & m) { \ + if ((ktr_mask & (m)) && ((1 << _TR_CPU) & ktr_cpumask)) { \ + _TR() \ + snprintf (_ktrptr->ktr_desc, KTRDESCSIZE, _desc, _p1, _p2, _p3, _p4); \ + } \ + } +#define CTR5(m, _desc, _p1, _p2, _p3, _p4, _p5) \ + if (KTR_COMPILE & m) { \ + if ((ktr_mask & (m)) && ((1 << _TR_CPU) & ktr_cpumask)) { \ + _TR() \ + snprintf (_ktrptr->ktr_desc, KTRDESCSIZE, _desc, _p1, _p2, _p3, _p4, _p5); \ + } \ + } + +#else /* not extended */ +#ifndef _TR +#define _TR(_desc) \ + struct ktr_entry *_ktrptr; \ + int _ktr_newidx, _ktr_saveidx; \ + do { \ + _ktr_saveidx = ktr_idx; \ + _ktr_newidx = (ktr_idx + 1) % KTR_ENTRIES; \ + } while (atomic_cmpset_int(&ktr_idx, _ktr_saveidx, _ktr_newidx) == 0); \ + _ktrptr = &ktr_buf[_ktr_saveidx]; \ + nanotime(&_ktrptr->ktr_tv); \ + _ktrptr->ktr_desc = (_desc); +#endif +#define CTR0(m, _desc) \ + if (KTR_COMPILE & m) { \ + if (ktr_mask & (m)) { \ + _TR(_desc) \ + } \ + } +#define CTR1(m, _desc, _p1) \ + if (KTR_COMPILE & m) { \ + if (ktr_mask & (m)) { \ + _TR(_desc) \ + _ktrptr->ktr_parm1 = (u_long)(_p1); \ + } \ + } +#define CTR2(m, _desc, _p1, _p2) \ + if (KTR_COMPILE & m) { \ + if (ktr_mask & (m)) { \ + _TR(_desc) \ + _ktrptr->ktr_parm1 = (u_long)(_p1); \ + _ktrptr->ktr_parm2 = (u_long)(_p2); \ + } \ + } +#define CTR3(m, _desc, _p1, _p2, _p3) \ + if (KTR_COMPILE & m) { \ + if (ktr_mask & (m)) { \ + _TR(_desc) \ + _ktrptr->ktr_parm1 = (u_long)(_p1); \ + _ktrptr->ktr_parm2 = (u_long)(_p2); \ + _ktrptr->ktr_parm3 = (u_long)(_p3); \ + } \ + } +#define CTR4(m, _desc, _p1, _p2, _p3, _p4) \ + if (KTR_COMPILE & m) { \ + if (ktr_mask & (m)) { \ + _TR(_desc) \ + _ktrptr->ktr_parm1 = (u_long)(_p1); \ + _ktrptr->ktr_parm2 = (u_long)(_p2); \ + _ktrptr->ktr_parm3 = (u_long)(_p3); \ + _ktrptr->ktr_parm4 = (u_long)(_p4); \ + } \ + } +#define CTR5(m, _desc, _p1, _p2, _p3, _p4, _p5) \ + if (KTR_COMPILE & m) { \ + if (ktr_mask & (m)) { \ + _TR(_desc) \ + _ktrptr->ktr_parm1 = (u_long)(_p1); \ + _ktrptr->ktr_parm2 = (u_long)(_p2); \ + _ktrptr->ktr_parm3 = (u_long)(_p3); \ + _ktrptr->ktr_parm4 = (u_long)(_p4); \ + _ktrptr->ktr_parm5 = (u_long)(_p5); \ + } \ + } +#endif +#else /* KTR */ +#undef KTR_COMPILE +#define KTR_COMPILE 0 +#define CTR0(m, d) +#define CTR1(m, d, p1) +#define CTR2(m, d, p1, p2) +#define CTR3(m, d, p1, p2, p3) +#define CTR4(m, d, p1, p2, p3, p4) +#define CTR5(m, d, p1, p2, p3, p4, p5) +/* XXX vvvvvvvv ??? */ +#define SEG_ATR(d,s) +#define SEG_ATR_DESC(d,s) +#define ATR(d) +#define CATR(f,d,n) +#define CATRD(f,d,n) +#endif /* KTR */ + +#define TR0(d) CTR0(KTR_GEN, d) +#define TR1(d, p1) CTR1(KTR_GEN, d, p1) +#define TR2(d, p1, p2) CTR2(KTR_GEN, d, p1, p2) +#define TR3(d, p1, p2, p3) CTR3(KTR_GEN, d, p1, p2, p3) +#define TR4(d, p1, p2, p3, p4) CTR4(KTR_GEN, d, p1, p2, p3, p4) +#define TR5(d, p1, p2, p3, p4, p5) CTR5(KTR_GEN, d, p1, p2, p3, p4, p5) + +/* + * Trace initialization events, similar to CTR with KTR_INIT, but + * completely ifdef'ed out if KTR_INIT isn't in KTR_COMPILE (to + * save string space, the compiler doesn't optimize out strings + * for the conditional ones above). + */ +#if (KTR_COMPILE & KTR_INIT) != 0 +#define ITR0(d) CTR0(KTR_INIT, d) +#define ITR1(d, p1) CTR1(KTR_INIT, d, p1) +#define ITR2(d, p1, p2) CTR2(KTR_INIT, d, p1, p2) +#define ITR3(d, p1, p2, p3) CTR3(KTR_INIT, d, p1, p2, p3) +#define ITR4(d, p1, p2, p3, p4) CTR4(KTR_INIT, d, p1, p2, p3, p4) +#define ITR5(d, p1, p2, p3, p4, p5) CTR5(KTR_INIT, d, p1, p2, p3, p4, p5) +#else +#define ITR0(d) +#define ITR1(d, p1) +#define ITR2(d, p1, p2) +#define ITR3(d, p1, p2, p3) +#define ITR4(d, p1, p2, p3, p4) +#define ITR5(d, p1, p2, p3, p4, p5) +#endif + +#endif /* !_SYS_KTR_H_ */ diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h index a6a2442..7c84690 100644 --- a/sys/sys/ktrace.h +++ b/sys/sys/ktrace.h @@ -58,7 +58,7 @@ struct ktr_header { pid_t ktr_pid; /* process id */ char ktr_comm[MAXCOMLEN+1]; /* command name */ struct timeval ktr_time; /* timestamp */ - caddr_t ktr_buf; + caddr_t ktr_buffer; }; /* |