On Sat, 24 Mar 2007 16:51:38 -0700 Wink Saville wrote: > This is the Trec driver, Makefile, header files. > Enable trec in Kernel hacking configuration menu. > > Signed-off-by: Wink Saville <[EMAIL PROTECTED]> > ---
> diff --git a/drivers/trec/trec.c b/drivers/trec/trec.c > new file mode 100644 > index 0000000..0b04b71 > --- /dev/null > +++ b/drivers/trec/trec.c > @@ -0,0 +1,404 @@ ... > + > +struct trec_dev_struct > +{ > + struct cdev cdev; /* Character device > structure */ Fit in 80 columns, please. > +}; > + > +MODULE_AUTHOR("Wink Saville"); > +MODULE_LICENSE("Dual BSD/GPL"); > + > +/* > + * Module parameters > + */ > +int major = 240; /* 240 a "local/expermental" device number for the > moment */ > +int minor = 1; > + > +module_param(major, int, S_IRUGO); > +module_param(minor, int, S_IRUGO); > + > +/* > + * Forward declarations > + */ > +static int trec_open(struct inode *inode, struct file *file); > +static int trec_release(struct inode *inode, struct file *file); > + > +/* > + * File operations > + */ > +struct file_operations trec_f_ops = { > + .owner = THIS_MODULE, > + .open = trec_open, > + .release = trec_release, > +}; > + > +struct trec_struct { > + uint64_t tsc; > + unsigned long pc; > + unsigned long tsk; > + unsigned int pid; > + unsigned long v1; > + unsigned long v2; > +}; > + > +/* > + * Change trec_buffer_struct.data to be a pointer to a PAGE in the future > + */ > +#define TREC_DATA_SIZE 0x200 > +struct trec_buffer_struct { > + struct trec_buffer_struct * next; > + struct trec_struct * cur; > + struct trec_struct * end; > + struct trec_struct data[TREC_DATA_SIZE]; Kernel style is: sturct trec_struct *cur; > +}; > + > +/* > + * Number of buffers must be a multiple of two so we can > + * snapshot the buffers and the minimum should be 4. > + */ > +#define TREC_COUNT 2 > +struct trec_buffer_struct trec_buffers[2][TREC_COUNT]; > +int trec_idx = 0; > +spinlock_t trec_lock = SPIN_LOCK_UNLOCKED; > + > +struct trec_buffer_struct * trec_buffer_cur = NULL; > +struct trec_buffer_struct * trec_buffer_snapshot = NULL; Pointer style. + don't init to NULL. > + > +struct trec_dev_struct trec_dev; > + > +/** > + * Print an address symbol if available to the buffer > + * this is from traps.c > + */ Don't use kernel-doc indicator ("/**") unless the function block comment is actually in kernel-doc syntax (see Documentation/kernel-doc-nano-HOWTO.txt). > +static int snprint_address(char *b, int bsize, unsigned long address) > +{ > +#ifdef CONFIG_KALLSYMS > + unsigned long offset = 0, symsize; > + const char *symname; > + char *modname; > + char *delim = ":"; > + int n; > + char namebuf[128]; > + > + symname = kallsyms_lookup(address, &symsize, &offset, &modname, > namebuf); > + if (!symname) { > + n = 0; > + } else { > + if (!modname) > + modname = delim = ""; > + n = snprintf(b, bsize, "0x%016lx %s%s%s%s+0x%lx/0x%lx", > + address, delim, modname, delim, symname, offset, > symsize); > + } > + return n; > +#else > + return snprintf(b, bsize, "0x%016lx", address); > +#endif > +} > +/* > + * Snapshot the current trecs > + */ > +void trec_snapshot(void) > +{ > + int flags; > + > + spin_lock_irqsave(&trec_lock, flags); > + trec_buffer_snapshot = trec_buffer_cur; > + trec_idx = trec_idx ^ 1; > + trec_buffer_cur = &trec_buffers[trec_idx][0]; > + spin_unlock_irqrestore(&trec_lock, flags); > +} > +EXPORT_SYMBOL(trec_snapshot); What (if anything) prevents multiple snapshots from overwriting each other, or from being overwritten while one is printing? > +/* > + * trec_print > + */ > +void trec_print_snapshot(void) > +{ > + int i; > + struct trec_buffer_struct *cur_buffer; > + > + if (!trec_buffer_snapshot) > + trec_snapshot(); > + > + cur_buffer = trec_buffer_snapshot->next; > + for (i = 0; i < TREC_COUNT; i++) { > + struct trec_struct *cur; > + > + for (cur = &cur_buffer->data[0]; > + cur < cur_buffer->cur; > + cur += 1) { > + char b[256]; > + int n; > + > + n = snprintf(b, sizeof(b), KERN_ERR "t=%20llu pid=%5u > tsk=%p v1=%p v2=%p ", > + cur->tsc, cur->pid, (void *)cur->tsk, (void > *)cur->v1, (void *)cur->v2); > + n += snprint_address(b+n, sizeof(b)-n, cur->pc); > + printk("%s\n", b); > + } > + cur_buffer = cur_buffer->next; > + } > +} > +EXPORT_SYMBOL(trec_print_snapshot); > + > +/* > + * Sysrq support for trec's > + */ > +#ifdef CONFIG_MAGIC_SYSRQ > +/* > + * trec print snapshot handler for sysrq > + */ > +static void sysrq_handle_trec_print_snapshot(int key, struct tty_struct > *tty) > +{ > + trec_print_snapshot(); > +} > + > +/* > + * trec snapshot handler for sysrq > + */ > +static void sysrq_handle_trec_snapshot(int key, struct tty_struct *tty) > +{ > + trec_snapshot(); > +} > + > +static struct sysrq_key_op sysrq_trec_snapshot_op = > +{ > + .handler = sysrq_handle_trec_snapshot, > + .help_msg = "Trec snapshot(Y)", > + .action_msg = "Trec snapshot", > +}; > + > +static struct sysrq_key_op sysrq_trec_print_snapshot_op = > +{ > + .handler = sysrq_handle_trec_print_snapshot, > + .help_msg = "Print current trec snapshot", (Z) should be on the help_msg, not on the action_msg. > + .action_msg = "Trec print snapshot(Z)", > +}; > + > +/* > + * Initilize trec sysrq support Initialize > + */ > +static int __init setup_trec_sysrq(void) > +{ > + DPK("setup_trec_sysrq y=trec_snapshot z=trec_print_snapshot\n"); > + register_sysrq_key('y', &sysrq_trec_snapshot_op); > + register_sysrq_key('z', &sysrq_trec_print_snapshot_op); > + return 0; > +} > +__initcall(setup_trec_sysrq); > +#endif /* CONFIG_MAGIC_SYSRQ */ > +/* > + * Init routine for the trec device > + */ > +static int __init trec_device_init(void) > +{ > + int result; > + dev_t dev_number = 0; > + static struct class *trec_class; > + > + DPK("trec_device_init: E\n"); > + > + if (major) { > + dev_number = MKDEV(major, minor); > + result = register_chrdev_region(dev_number, 1, "trec"); > + DPK("trec_device_init: static major result=%d\n", result); > + } else { > + result = alloc_chrdev_region(&dev_number, minor, 1, "trec"); > + major = MAJOR(dev_number); > + DPK("trec_device_init: dynamic major result=%d\n", result); > + } > + > + if (result < 0) { > + printk(KERN_WARNING "trec: can't get major %d\n", major); > + goto err; > + } > + > + cdev_init(&trec_dev.cdev, &trec_f_ops); > + trec_dev.cdev.owner = THIS_MODULE; > + trec_dev.cdev.ops = &trec_f_ops; > + > + result = cdev_add(&trec_dev.cdev, dev_number, 1); > + if (result) > + { > + DPK("trec_device_init: cdev_add failed\n"); > + goto err; > + } > + > + /* > + * Make a trec class and create the device > + */ > + trec_class = class_create(THIS_MODULE, "trec"); > + class_device_create(trec_class, NULL, dev_number, NULL, "trec"); > + > + /* > + * If the trec buffers have not been initialized do so > + */ > + if (trec_buffer_cur == NULL) { > + trec_init(); > + } Style: no braces on one-statement "blocks". > +} > diff --git a/include/asm-i386/trec.h b/include/asm-i386/trec.h > new file mode 100644 > index 0000000..1de4dc6 > --- /dev/null > +++ b/include/asm-i386/trec.h > @@ -0,0 +1,33 @@ > +/* > + * Copyright (C) 2007 Saville Software, Inc. > + * > + * This code may be used for any purpose whatsoever, but > + * no warranty of any kind is provided. > + */ > + > +#ifndef _ASM_I386_TREC_H > +#define _ASM_I386_TREC_H > + > +#ifndef __ASSEMBLY__ > + > +#if CONFIG_X86_TSC > +#include <asm/msr.h> > + > +/* > + * read x86 time stamp counter. > + */ > +static uint64_t inline rd_tsc(void) > +{ > + volatile uint64_t value; > + > + rdtscll(value); > + > + return value; > +} > +#else > + #define rd_tsc() (0) We don't typically indent (#if/) #else block contents like this. > +#endif /* CONFIG_X86_TSC */ > + > +#endif /* !__ASSEMBLY__ */ > + > +#endif /* _ASM_I386_TREC_H */ > diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug > index 3f3e740..db53fdb 100644 > --- a/lib/Kconfig.debug > +++ b/lib/Kconfig.debug > @@ -303,6 +303,13 @@ config STACKTRACE > depends on DEBUG_KERNEL > depends on STACKTRACE_SUPPORT > > +config TREC > + def_bool n > + bool "Trace record support" > + depends on DEBUG_KERNEL > + help > + Trace records are a light weight tracing facility lightweight ... facility. > + > config DEBUG_KOBJECT > bool "kobject debugging" > depends on DEBUG_KERNEL --- ~Randy *** Remember to use Documentation/SubmitChecklist when testing your code *** - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/