Reimplement the kernel tracepoint facility. The new implementation is
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 20 Jun 2005 17:59:33 +0000 (17:59 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 20 Jun 2005 17:59:33 +0000 (17:59 +0000)
completely generic and very easy to implement in modules.  Compile-time
optimizations are retained and sysctl generation is completely automatic.
Only the DDB command code has been retained from FreeBSD.

The logging macros are designed to allow subsystems to trivially declare
and use the facility.

This implementation is not quite complete, we also want to integrate a
stack backtrace logging facility.

sys/conf/options
sys/config/LINT
sys/i386/conf/LINT
sys/kern/kern_ktr.c
sys/sys/ktr.h

index c173216..df50382 100644 (file)
@@ -1,5 +1,5 @@
 # $FreeBSD: src/sys/conf/options,v 1.191.2.53 2003/06/04 17:56:58 sam Exp $
-# $DragonFly: src/sys/conf/options,v 1.32 2005/06/20 07:58:37 dillon Exp $
+# $DragonFly: src/sys/conf/options,v 1.33 2005/06/20 17:59:31 dillon Exp $
 #
 #        On the handling of kernel options
 #
@@ -524,9 +524,11 @@ HIFN_NO_RNG                opt_hifn.h
 
 # KTR options
 KTR                            opt_global.h
-KTR_MASK                       opt_ktr.h
-KTR_CPUMASK                    opt_ktr.h
-KTR_COMPILE                    opt_global.h
+KTR_ALL                                opt_ktr.h
+KTR_TOKENS                     opt_ktr.h
+KTR_MALLOC                     opt_ktr.h
+KTR_IPIQ                       opt_ktr.h
+KTR_MSGPORT                    opt_ktr.h
 KTR_ENTRIES                    opt_global.h
 KTR_VERBOSE                    opt_ktr.h
 
index 734d51e..b416a5b 100644 (file)
@@ -3,7 +3,7 @@
 #      as much of the source tree as it can.
 #
 # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $
-# $DragonFly: src/sys/config/LINT,v 1.55 2005/06/12 19:24:10 swildner Exp $
+# $DragonFly: src/sys/config/LINT,v 1.56 2005/06/20 17:59:33 dillon Exp $
 #
 # NB: You probably don't want to try running a kernel built from this
 # file.  Instead, you should start from GENERIC, and add options from
@@ -2661,10 +2661,7 @@ options  VFS_BIO_DEBUG
 options        XBONEHACK
 
 options        KTR
-options        KTR_MASK=1
-options        KTR_CPUMASK=1
-options        KTR_COMPILE=(KTR_ALL)   # Every trace class, see sys/ktr.h for
-                                       # the different class numbers
+options KTR_ALL
 options        KTR_ENTRIES=1024
 options        KTR_VERBOSE=1
 
index 005edfc..0859767 100644 (file)
@@ -3,7 +3,7 @@
 #      as much of the source tree as it can.
 #
 # $FreeBSD: src/sys/i386/conf/LINT,v 1.749.2.144 2003/06/04 17:56:59 sam Exp $
-# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.55 2005/06/12 19:24:10 swildner Exp $
+# $DragonFly: src/sys/i386/conf/Attic/LINT,v 1.56 2005/06/20 17:59:33 dillon Exp $
 #
 # NB: You probably don't want to try running a kernel built from this
 # file.  Instead, you should start from GENERIC, and add options from
@@ -2661,10 +2661,7 @@ options  VFS_BIO_DEBUG
 options        XBONEHACK
 
 options        KTR
-options        KTR_MASK=1
-options        KTR_CPUMASK=1
-options        KTR_COMPILE=(KTR_ALL)   # Every trace class, see sys/ktr.h for
-                                       # the different class numbers
+options KTR_ALL
 options        KTR_ENTRIES=1024
 options        KTR_VERBOSE=1
 
index 63ab1ad..5f536af 100644 (file)
@@ -1,6 +1,39 @@
-/*-
- * Copyright (c) 2004 Eirik Nygaard <eirikn@kerneled.com>
- * All rights reserved.
+/*
+ * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ * 
+ * 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. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS 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.
+ */
+/*
+ * The following copyright applies to the DDB command code:
+ *
  * Copyright (c) 2000 John Baldwin <jhb@FreeBSD.org>
  * All rights reserved.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
 /*
- * This module holds the global variables used by KTR and the ktr_tracepoint()
- * function that does the actual tracing.
+ * $DragonFly: src/sys/kern/kern_ktr.c,v 1.5 2005/06/20 17:59:32 dillon Exp $
  */
-
 /*
- * $FreeBSD: src/sys/kern/kern_ktr.c,v 1.43 2003/09/10 01:09:32 jhb Exp $
- * $DragonFly: src/sys/kern/kern_ktr.c,v 1.4 2005/04/20 14:27:29 joerg Exp $
+ * Kernel tracepoint facility.
  */
 
 #include "opt_ddb.h"
 #include <sys/param.h>
 #include <sys/cons.h>
 #include <sys/kernel.h>
-#include <sys/ktr.h>
 #include <sys/libkern.h>
 #include <sys/proc.h>
 #include <sys/sysctl.h>
+#include <sys/ktr.h>
 #include <sys/systm.h>
 #include <sys/time.h>
 #include <sys/malloc.h>
 #include <ddb/ddb.h>
 
 #ifndef KTR_ENTRIES
-#define        KTR_ENTRIES     1024
-#endif
-
-#ifndef KTR_MASK
-#define        KTR_MASK        (KTR_ALL)
-#endif
-
-#ifndef KTR_CPUMASK
-#define        KTR_CPUMASK     (~0)
-#endif
-
-#ifndef KTR_TIME
-#define        KTR_TIME        ktr_getts()
-#endif
-
-#ifndef KTR_CPU
-#define        KTR_CPU         mycpu->gd_cpuid;
+#define        KTR_ENTRIES             2048
 #endif
+#define KTR_ENTRIES_MASK       (KTR_ENTRIES - 1)
 
 MALLOC_DEFINE(M_KTR, "ktr", "ktr buffers");
 
-SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RD, 0, "KTR options");
+SYSCTL_NODE(_debug, OID_AUTO, ktr, CTLFLAG_RW, 0, "ktr");
 
-int    ktr_cpumask = KTR_CPUMASK;
+int32_t        ktr_cpumask = -1;
 TUNABLE_INT("debug.ktr.cpumask", &ktr_cpumask);
 SYSCTL_INT(_debug_ktr, OID_AUTO, cpumask, CTLFLAG_RW, &ktr_cpumask, 0, "");
 
-int    ktr_mask = KTR_MASK;
-TUNABLE_INT("debug.ktr.mask", &ktr_mask);
-SYSCTL_INT(_debug_ktr, OID_AUTO, mask, CTLFLAG_RW, &ktr_mask, 0, "");
-
 int    ktr_entries = KTR_ENTRIES;
 SYSCTL_INT(_debug_ktr, OID_AUTO, entries, CTLFLAG_RD, &ktr_entries, 0, "");
 
 int    ktr_version = KTR_VERSION;
 SYSCTL_INT(_debug_ktr, OID_AUTO, version, CTLFLAG_RD, &ktr_version, 0, "");
 
-int ktr_discarded;
-SYSCTL_INT(_debug_ktr, OID_AUTO, discarded, CTLFLAG_RD, &ktr_discarded, 0, "");
-
-volatile int   ktr_idx[MAXCPU], ktr_initiated = 0;
-struct ktr_entry *ktr_buf[MAXCPU];
+/*
+ * Give cpu0 a static buffer so the tracepoint facility can be used during
+ * early boot (note however that we still use a critical section, XXX).
+ */
+static struct  ktr_entry ktr_buf0[KTR_ENTRIES];
+static struct  ktr_entry *ktr_buf[MAXCPU] = { &ktr_buf0[0] };
+static int     ktr_idx[MAXCPU];
 
 #ifdef KTR_VERBOSE
 int    ktr_verbose = KTR_VERBOSE;
@@ -117,81 +129,68 @@ ktr_sysinit(void *dummy)
 {
        int i;
 
-       for(i = 0; i < ncpus; i++) {
+       for(i = 1; i < ncpus; ++i) {
                ktr_buf[i] = malloc(KTR_ENTRIES * sizeof(struct ktr_entry),
-                               M_KTR, M_WAITOK);
-               ktr_idx[i] = -1;
+                                   M_KTR, M_WAITOK | M_ZERO);
        }
-       ktr_initiated++;
-}
-SYSINIT(announce, SI_SUB_INTRINSIC, SI_ORDER_FIRST, ktr_sysinit, NULL);
-
-static __inline int
-ktr_nextindex(int cpu)
-{
-       int ktrindex;
-
-       crit_enter();
-       ktrindex = ktr_idx[cpu] = (ktr_idx[cpu] + 1) & (KTR_ENTRIES - 1);
-       crit_exit();
-       return(ktrindex);
 }
 
-static __inline uint64_t
-ktr_getts(void)
-{
-       if (cpu_feature & CPUID_TSC)
-               return(rdtsc());
-       return(get_approximate_time_t());
-}
+SYSINIT(announce, SI_SUB_INTRINSIC, SI_ORDER_FIRST, ktr_sysinit, NULL);
 
+static __inline
 void
-ktr_tracepoint(u_int mask, const char *file, int line, const char *format,
-    u_long arg1, u_long arg2, u_long arg3, u_long arg4, u_long arg5,
-    u_long arg6)
+ktr_write_entry(struct ktr_info *info, const char *file, int line,
+               const void *ptr)
 {
        struct ktr_entry *entry;
-       int cpu, newindex;
-
-       if (ktr_initiated == 0) {
-               ktr_discarded++;
-               return;
+       int cpu;
+
+       cpu = mycpu->gd_cpuid;
+       if (ktr_buf[cpu]) {
+               crit_enter();
+               entry = ktr_buf[cpu] + (ktr_idx[cpu] & KTR_ENTRIES_MASK);
+               ++ktr_idx[cpu];
+               crit_exit();
+               if (cpu_feature & CPUID_TSC)
+                       entry->ktr_timestamp = rdtsc();
+               else
+                       entry->ktr_timestamp = get_approximate_time_t();
+               entry->ktr_info = info;
+               entry->ktr_file = file;
+               entry->ktr_line = line;
+               if (info->kf_data_size > KTR_BUFSIZE)
+                       bcopyi(ptr, entry->ktr_data, KTR_BUFSIZE);
+               else
+                       bcopyi(ptr, entry->ktr_data, info->kf_data_size);
        }
-       if (panicstr)
-               return;
-       if ((ktr_mask & mask) == 0)
-               return;
-       cpu = KTR_CPU;
-       if (((1 << cpu) & ktr_cpumask) == 0)
-               return;
-       newindex = ktr_nextindex(cpu);
-       entry = &ktr_buf[cpu][newindex];
-       entry->ktr_timestamp = KTR_TIME;
-       entry->ktr_cpu = cpu;
-       if (file != NULL)
-               while (strncmp(file, "../", 3) == 0)
-                       file += 3;
-       entry->ktr_file = file;
-       entry->ktr_line = line;
 #ifdef KTR_VERBOSE
-       if (ktr_verbose) {
+       if (ktr_verbose && info->kf_format) {
 #ifdef SMP
                printf("cpu%d ", cpu);
 #endif
                if (ktr_verbose > 1) {
                        printf("%s.%d\t", entry->ktr_file, entry->ktr_line);
                }
-               printf(format, arg1, arg2, arg3, arg4, arg5, arg6);
+               vprintf(info->kf_format, ptr);
                printf("\n");
        }
 #endif
-       entry->ktr_desc = format;
-       entry->ktr_parms[0] = arg1;
-       entry->ktr_parms[1] = arg2;
-       entry->ktr_parms[2] = arg3;
-       entry->ktr_parms[3] = arg4;
-       entry->ktr_parms[4] = arg5;
-       entry->ktr_parms[5] = arg6;
+}
+
+void
+ktr_log(struct ktr_info *info, const char *file, int line, ...)
+{
+       __va_list va;
+
+       __va_start(va, line);
+       ktr_write_entry(info, file, line, va);
+       __va_end(va);
+}
+
+void
+ktr_log_ptr(struct ktr_info *info, const char *file, int line, const void *ptr)
+{
+       ktr_write_entry(info, file, line, ptr);
 }
 
 #ifdef DDB
@@ -202,8 +201,9 @@ struct tstate {
        int     cur;
        int     first;
 };
+
 static int db_ktr_verbose;
-static int db_mach_vtrace(struct ktr_entry *kp, int idx);
+static int db_mach_vtrace(int cpu, struct ktr_entry *kp, int idx);
 
 DB_SHOW_COMMAND(ktr, db_ktr_all)
 {
@@ -216,7 +216,7 @@ DB_SHOW_COMMAND(ktr, db_ktr_all)
 
        for(i = 0; i < ncpus; i++) {
                tstate[i].first = -1;
-               tstate[i].cur = ktr_idx[i];
+               tstate[i].cur = ktr_idx[i] & KTR_ENTRIES_MASK;
        }
        db_ktr_verbose = 0;
        while ((c = *(modif++)) != '\0') {
@@ -263,6 +263,8 @@ DB_SHOW_COMMAND(ktr, db_ktr_all)
                 * Find the lowest timestamp
                 */
                for (i = 0, counter = 0; i < ncpus; i++) {
+                       if (ktr_buf[i] == NULL)
+                               continue;
                        if (printcpu != -1 && printcpu != i)
                                continue;
                        if (tstate[i].cur == -1) {
@@ -286,35 +288,41 @@ DB_SHOW_COMMAND(ktr, db_ktr_all)
                if (--tstate[i].cur < 0)
                        tstate[i].cur = KTR_ENTRIES - 1;
                if (tstate[i].first == tstate[i].cur) {
-                       db_mach_vtrace(kp, tstate[i].cur + 1);
+                       db_mach_vtrace(i, kp, tstate[i].cur + 1);
                        tstate[i].cur = -1;
                        continue;
                }
-               if (ktr_buf[i][tstate[i].cur].ktr_desc == NULL)
+               if (ktr_buf[i][tstate[i].cur].ktr_info == NULL)
                        tstate[i].cur = -1;
                if (db_more(&nl) == -1)
                        break;
-               if (db_mach_vtrace(kp, tstate[i].cur + 1) == 0)
+               if (db_mach_vtrace(i, kp, tstate[i].cur + 1) == 0)
                        tstate[i].cur = -1;
        }
 }
 
 static int
-db_mach_vtrace(struct ktr_entry *kp, int idx)
+db_mach_vtrace(int cpu, struct ktr_entry *kp, int idx)
 {
-       if (kp->ktr_desc == NULL)
+       if (kp->ktr_info == NULL)
                return(0);
 #ifdef SMP
-       db_printf("cpu%d ", kp->ktr_cpu);
+       db_printf("cpu%d ", cpu);
 #endif
        db_printf("%d: ", idx);
        if (db_ktr_verbose) {
                db_printf("%10.10lld %s.%d\t", (long long)kp->ktr_timestamp,
                    kp->ktr_file, kp->ktr_line);
        }
-       db_printf(kp->ktr_desc, kp->ktr_parms[0], kp->ktr_parms[1],
-           kp->ktr_parms[2], kp->ktr_parms[3], kp->ktr_parms[4],
-           kp->ktr_parms[5]);
+       db_printf("%s\t", kp->ktr_info->kf_name);
+       if (kp->ktr_info->kf_format) {
+               int32_t *args = (int32_t *)kp->ktr_data;
+               db_printf(kp->ktr_info->kf_format,
+                         args[0], args[1], args[2], args[3],
+                         args[4], args[5], args[6], args[7],
+                         args[8], args[9], args[10], args[11]);
+           
+       }
        db_printf("\n");
 
        return(1);
index a464af5..b259de5 100644 (file)
@@ -1,37 +1,41 @@
-/*-
- * Copyright (c) 1996 Berkeley Software Design, Inc. All rights reserved.
- *
+/*
+ * Copyright (c) 2005 The DragonFly Project.  All rights reserved.
+ * 
+ * This code is derived from software contributed to The DragonFly Project
+ * by Matthew Dillon <dillon@backplane.com>
+ * 
  * 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
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS 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: /repoman/r/ncvs/src/sys/sys/ktr.h,v 1.21 2003/03/11 20:07:22 jhb Exp $
- * $DragonFly: src/sys/sys/ktr.h,v 1.4 2005/03/09 23:26:11 hmp Exp $
+ * 
+ * $DragonFly: src/sys/sys/ktr.h,v 1.5 2005/06/20 17:59:30 dillon Exp $
  */
-
 /*
- *     Wraparound kernel trace buffer support.
+ * Generic Kernel trace buffer support.  
+ *
  */
 
 #ifndef _SYS_KTR_H_
 #include "opt_ktr.h"
 #endif
 
-/*
- * 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_EVH         0x00020000              /* Eventhandler */
-#define        KTR_NFS         0x00040000              /* NFS */
-#define        KTR_VOP         0x00080000              /* VFS and VNODE ops */
-#define        KTR_VM          0x00100000              /* The virtual memory system */
-#define        KTR_RUNQ        0x00200000              /* Run queue */
-#define        KTR_CONTENTION  0x00800000              /* Lock contention */
-#define        KTR_ALL         0x00ffffff
-
-/*
- * 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         0x01000000
-#define        KTR_CT2         0x02000000
-#define        KTR_CT3         0x04000000
-#define        KTR_CT4         0x08000000
-#define        KTR_CT5         0x10000000
-#define        KTR_CT6         0x20000000
-#define        KTR_CT7         0x40000000
-#define        KTR_CT8         0x80000000
-
-/* Trace classes to compile in */
-#ifndef KTR_COMPILE
-#define        KTR_COMPILE     (KTR_ALL)
+#if !defined(KTR_ALL)
+#define KTR_ALL                0
 #endif
 
-/*
- * Version number for ktr_entry struct.  Increment this when you break binary
- * compatibility.
- */
-#define        KTR_VERSION     1
-
-#define        KTR_PARMS       6
+#define        KTR_BUFSIZE     48
+#define KTR_VERSION    2
 
 #ifndef LOCORE
 
+struct ktr_info {
+       const char *kf_name;    /* human-interpreted subsystem name */
+       int32_t *kf_master_enable; /* the master enable variable */
+       const char *kf_format;  /* data format */
+       int kf_data_size;       /* relevance of the data buffer */
+};
+
 struct ktr_entry {
        u_int64_t ktr_timestamp;
-       int     ktr_cpu;
-       int     ktr_line;
+       struct ktr_info *ktr_info;
        const   char *ktr_file;
-       const   char *ktr_desc;
-       u_long  ktr_parms[KTR_PARMS];
+       void    *ktr_caller1;
+       void    *ktr_caller2;
+       int32_t ktr_line;
+       int32_t ktr_unused;
+       char    ktr_data[KTR_BUFSIZE];
 };
 
-extern int ktr_cpumask;
-extern int ktr_mask;
-extern int ktr_entries;
-extern int ktr_verbose;
-
-extern volatile int ktr_idx[MAXCPU];
-extern struct ktr_entry *ktr_buf[MAXCPU];
+void   ktr_log(struct ktr_info *info, const char *file, int line, ...);
+void   ktr_log_ptr(struct ktr_info *info, const char *file, int line, const void *ptr);
 
-#endif /* !LOCORE */
+/*
+ * Take advantage of constant integer optimizations by the compiler
+ * to optimize-out disabled code at compile-time.  If KTR_ENABLE_<name>
+ * is 0, the compiler avoids generating all related code when KTR is enabled.
+ */
 
 #ifdef KTR
 
-void   ktr_tracepoint(u_int mask, const char *file, int line,
-           const char *format, u_long arg1, u_long arg2, u_long arg3,
-           u_long arg4, u_long arg5, u_long arg6);
-
-#define CTR6(m, format, p1, p2, p3, p4, p5, p6) do {                   \
-       if (KTR_COMPILE & (m))                                          \
-               ktr_tracepoint((m), __FILE__, __LINE__, format,         \
-                   (u_long)(p1), (u_long)(p2), (u_long)(p3),           \
-                   (u_long)(p4), (u_long)(p5), (u_long)(p6));          \
-       } while(0)
-#define        CTR0(m, format)                 CTR6(m, format, 0, 0, 0, 0, 0, 0)
-#define        CTR1(m, format, p1)             CTR6(m, format, p1, 0, 0, 0, 0, 0)
-#define        CTR2(m, format, p1, p2)         CTR6(m, format, p1, p2, 0, 0, 0, 0)
-#define        CTR3(m, format, p1, p2, p3)     CTR6(m, format, p1, p2, p3, 0, 0, 0)
-#define        CTR4(m, format, p1, p2, p3, p4) CTR6(m, format, p1, p2, p3, p4, 0, 0)
-#define        CTR5(m, format, p1, p2, p3, p4, p5)     CTR6(m, format, p1, p2, p3, p4, p5, 0)
-#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)
-#define        CTR6(m, d, p1, p2, p3, p4, p5, p6)
-#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)
-#define        TR6(d, p1, p2, p3, p4, p5, p6)  CTR6(KTR_GEN, d, p1, p2, p3, p4, p5, p6)
+SYSCTL_DECL(_debug_ktr);
+
+#define KTR_INFO_MASTER(master)                                                    \
+           SYSCTL_NODE(_debug_ktr, OID_AUTO, master, CTLFLAG_RW, 0, "");   \
+           int ktr_ ## master ## _enable = -1;                             \
+           SYSCTL_INT(_debug_ktr, OID_AUTO, master ## _enable, CTLFLAG_RW, \
+                       &ktr_ ## master ## _enable, 0, "")
+
+#define KTR_INFO_MASTER_EXTERN(master)                                 \
+           SYSCTL_DECL(_debug_ktr_ ## master);                         \
+           extern int ktr_ ## master ## _enable                        \
 
 /*
- * 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).
+ * This creates a read-only sysctl so the user knows what the mask
+ * definitions are and a number of static const int's which are used
+ * by the compiler to optimize the trace logging at compile-time and
+ * run-time.
  */
-#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)
-#define        ITR6(d, p1, p2, p3, p4, p5, p6) CTR6(KTR_INIT, d, p1, p2, p3, p4, p5, p6)
+#define KTR_INFO(compile, master, name, maskbit, format, datasize)     \
+           static const int ktr_ ## master ## _ ## name ## _mask =     \
+               1 << maskbit;                                           \
+           static const int ktr_ ## master ## _ ## name ## _enable =   \
+               compile;                                                \
+           static int ktr_ ## master ## _ ## name ## _mask_ro =        \
+               1 << maskbit;                                           \
+           SYSCTL_INT(_debug_ktr_ ## master, OID_AUTO, name ## _mask,  \
+               CTLFLAG_RD, &ktr_ ## master ## _ ## name ## _mask_ro,   \
+               0, "");                                                 \
+           static struct ktr_info ktr_info_ ## master ## _ ## name = { \
+               #master "_" #name,                                      \
+               &ktr_ ## master ## _enable,                             \
+               format,                                                 \
+               datasize }
+
+#define KTR_LOG(name, args...)                                         \
+           if (ktr_ ## name ## _enable &&                              \
+             (ktr_ ## name ## _mask & *ktr_info_ ## name .kf_master_enable)) \
+           ktr_log(&ktr_info_ ## name, __FILE__, __LINE__, ##args)
+
+#define KTR_LOG_PTR(name, ptr)                                         \
+           if (ktr_ ## name ## _enable &&                              \
+             (ktr_ ## name ## _mask & *ktr_info_ ## name .kf_master_enable)) \
+           ktr_log_ptr(&ktr_info_ ## name, __FILE__, __LINE__, ptr)
+
 #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)
-#define        ITR6(d, p1, p2, p3, p4, p5, p6)
+
+#define KTR_INFO_MASTER(master)                                                \
+           const static int ktr_ ## master ## _enable = 0
+
+#define KTR_INFO_MASTER_EXTERN(master)                                 \
+           const static int ktr_ ## master ## _enable = 0
+
+#define KTR_INFO(master, name, maskbit, format, datasize)              \
+           static const int ktr_ ## master ## _ ## name ## _mask =     \
+               1 << maskbit
+
+#define KTR_LOG(info, args...)
+#define KTR_LOG_PTR(info, ptr)
+
 #endif
 
+#endif /* !LOCORE */
 #endif /* !_SYS_KTR_H_ */