From 67c0249b96cb05bce8299da3f4fe970395a1ce6a Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Thu, 19 Apr 2012 17:19:40 -0400 Subject: [PATCH] - sched-tick SDT probe. - FBT probe point discovery and probe creation. - Moving code around for the kernel pseudo-module handling since it gets used by both the SDT code and the FBT code. Signed-off-by: Kris Van Hees --- dtrace/dtrace_dev.c | 4 ++ dtrace/dtrace_util.c | 1 + dtrace/fbt.h | 7 -- dtrace/fbt_dev.c | 166 +++++++++++++++++++++++++++++++++++++++++++ dtrace/fbt_mod.c | 25 ++++++- dtrace/sdt_dev.c | 3 + dtrace/sdt_impl.h | 9 +++ 7 files changed, 206 insertions(+), 9 deletions(-) delete mode 100644 dtrace/fbt.h diff --git a/dtrace/dtrace_dev.c b/dtrace/dtrace_dev.c index c3e76af41f0e..3f68182db370 100644 --- a/dtrace/dtrace_dev.c +++ b/dtrace/dtrace_dev.c @@ -1213,6 +1213,8 @@ int dtrace_dev_init(void) return rc; } + dtrace_os_init(); + dtrace_modload = dtrace_module_loaded; dtrace_modunload = dtrace_module_unloaded; #ifdef FIXME @@ -1328,4 +1330,6 @@ void dtrace_dev_exit(void) misc_deregister(&dtrace_dev); dtrace_probe_exit(); + + dtrace_os_exit(); } diff --git a/dtrace/dtrace_util.c b/dtrace/dtrace_util.c index beb222d44d88..79bd70cc6e5d 100644 --- a/dtrace/dtrace_util.c +++ b/dtrace/dtrace_util.c @@ -51,6 +51,7 @@ void *dtrace_vzalloc_try(unsigned long size) __GFP_NORETRY | __GFP_NOWARN | __GFP_ZERO, PAGE_KERNEL); } +EXPORT_SYMBOL(dtrace_vzalloc_try); /* * Return a duplicate copy of a string. If the specified string is NULL, this diff --git a/dtrace/fbt.h b/dtrace/fbt.h deleted file mode 100644 index 6b6134943d17..000000000000 --- a/dtrace/fbt.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _FBT_H_ -#define _FBT_H_ - -extern int fbt_dev_init(void); -extern void fbt_dev_exit(void); - -#endif /* _FBT_H_ */ diff --git a/dtrace/fbt_dev.c b/dtrace/fbt_dev.c index f46dc89369f8..2b367db078f5 100644 --- a/dtrace/fbt_dev.c +++ b/dtrace/fbt_dev.c @@ -27,8 +27,163 @@ #include #include +#include +#include +#include +#include "dtrace.h" #include "dtrace_dev.h" +#include "fbt_impl.h" + +#define FBT_PATCHVAL 0xf0 +#define FBT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask) +#define FBT_PROBETAB_SIZE 0x8000 /* 32k entries -- 128K total */ + +static fbt_probe_t **fbt_probetab; +static int fbt_probetab_size; +static int fbt_probetab_mask; + +static unsigned long fbt_cnt_entry = 0; +static unsigned long fbt_cnt_return = 0; + +static void *fbt_provide_probe(struct module *mp, char *func, + uint8_t opc, uint8_t *addr, + void *pfbt) +{ + fbt_probe_t *fbt; + fbt_probe_t *prev; + + switch (opc) { + case FBT_PUSHL_EBP: + fbt = kzalloc(sizeof(fbt_probe_t), GFP_KERNEL); + fbt->fbp_name = func; + fbt->fbp_id = dtrace_probe_create(fbt_id, mp->name, func, + "entry", 3, fbt); + fbt->fbp_module = mp; + fbt->fbp_loadcnt = 1; /* FIXME */ + fbt->fbp_primary = 1; /* FIXME */ + fbt->fbp_patchpoint = addr; + fbt->fbp_patchval = FBT_PATCHVAL; + fbt->fbp_savedval = *addr; + fbt->fbp_rval = opc; + fbt->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(addr)]; + + fbt_probetab[FBT_ADDR2NDX(addr)] = fbt; + + mp->fbt_nprobes++; + + fbt_cnt_entry++; + + return fbt; + case FBT_RET: + case FBT_RET_IMM16: + fbt = kzalloc(sizeof(fbt_probe_t), GFP_KERNEL); + fbt->fbp_name = func; + + prev = (fbt_probe_t *)pfbt; + if (prev != NULL) { + prev->fbp_next = fbt; + fbt->fbp_id = prev->fbp_id; + } else { + fbt->fbp_id = dtrace_probe_create(fbt_id, mp->name, + func, "return", 3, + fbt); + } + + fbt->fbp_module = mp; + fbt->fbp_loadcnt = 1; /* FIXME */ + fbt->fbp_primary = 1; /* FIXME */ + fbt->fbp_patchpoint = addr; + fbt->fbp_patchval = FBT_PATCHVAL; + fbt->fbp_savedval = *addr; + fbt->fbp_rval = opc; + fbt->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(addr)]; + + fbt_probetab[FBT_ADDR2NDX(addr)] = fbt; + + mp->fbt_nprobes++; + + fbt_cnt_return++; + + return fbt; + default: + printk(KERN_INFO "FBT: Invalid opcode for %s\n", func); + + return NULL; + } +} + +void fbt_provide_module(void *arg, struct module *mp) +{ + printk(KERN_INFO "FBT: provide_module(%s)...\n", mp->name); + + /* + * Nothing to do if the module FBT probes were already created. + */ + if (mp->fbt_nprobes != 0) + return; + +#if 1 +{ +ktime_t tm0; +ktime_t tm1; + +tm0 = dtrace_gethrtime(); + dtrace_fbt_init(fbt_provide_probe); +tm1 = dtrace_gethrtime(); +printk(KERN_INFO "FBT: dtrace_fbt_init() took %lld nsec\n", (signed long long)tm1.tv64 - tm0.tv64); +} + + printk(KERN_INFO "FBT: Number of entry probes: %lu\n", fbt_cnt_entry); + printk(KERN_INFO "FBT: Number of return probes: %lu\n", fbt_cnt_return); +#else + analyze_symbols(); +#endif +} + +int _fbt_enable(void *arg, dtrace_id_t id, void *parg) +{ + return 1; +} + +void _fbt_disable(void *arg, dtrace_id_t id, void *parg) +{ +} + +void fbt_destroy(void *arg, dtrace_id_t id, void *parg) +{ + fbt_probe_t *fbt = parg; + fbt_probe_t *nxt, *hbp, *lst; + struct module *mp = fbt->fbp_module; + int ndx; + + do { + if (mp != NULL) + mp->fbt_nprobes--; + + ndx = FBT_ADDR2NDX(fbt->fbp_patchpoint); + lst = NULL; + hbp = fbt_probetab[ndx]; + + while (hbp != fbt) { + ASSERT(hbp != NULL); + + lst = hbp; + hbp = hbp->fbp_hashnext; + } + + if (lst != NULL) + lst->fbp_hashnext = fbt->fbp_hashnext; + else + fbt_probetab[ndx] = fbt->fbp_hashnext; + + nxt = fbt->fbp_next; + + kfree(fbt); + + fbt = nxt; + } while (fbt != NULL); +} static long fbt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -64,6 +219,13 @@ int fbt_dev_init(void) { int ret = 0; + if (fbt_probetab_size == 0) + fbt_probetab_size = FBT_PROBETAB_SIZE; + + fbt_probetab_mask = fbt_probetab_size - 1; + fbt_probetab = dtrace_vzalloc_try(fbt_probetab_size * + sizeof (fbt_probe_t *)); + ret = misc_register(&fbt_dev); if (ret) pr_err("%s: Can't register misc device %d\n", @@ -75,4 +237,8 @@ int fbt_dev_init(void) void fbt_dev_exit(void) { misc_deregister(&fbt_dev); + + vfree(fbt_probetab); + fbt_probetab_mask = 0; + fbt_probetab_size = 0; } diff --git a/dtrace/fbt_mod.c b/dtrace/fbt_mod.c index c1accf70221f..d1fdb08c409c 100644 --- a/dtrace/fbt_mod.c +++ b/dtrace/fbt_mod.c @@ -29,17 +29,38 @@ #include "dtrace.h" #include "dtrace_dev.h" -#include "fbt.h" +#include "fbt_impl.h" MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)"); MODULE_DESCRIPTION("Function Boundary Tracing"); MODULE_VERSION("v0.1"); +#if 0 MODULE_LICENSE("CDDL"); +#else +MODULE_LICENSE("GPL"); /* FIXME - Cheating */ +#endif static const dtrace_pattr_t fbt_attr = { +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, }; +DT_PROVIDER_POPS(fbt) + static dtrace_pops_t fbt_pops = { + NULL, + fbt_provide_module, + fbt_enable, + fbt_disable, + NULL, + NULL, + NULL, + NULL, + NULL, + fbt_destroy }; -DT_PROVIDER_MODULE(fbt, DTRACE_PRIV_KERNEL); +DT_PROVIDER_MODULE(fbt, DTRACE_PRIV_KERNEL) diff --git a/dtrace/sdt_dev.c b/dtrace/sdt_dev.c index 07e08bf78a82..847a4dc60e13 100644 --- a/dtrace/sdt_dev.c +++ b/dtrace/sdt_dev.c @@ -54,6 +54,9 @@ static sdt_argdesc_t sdt_args[] = { { "proc", "signal-handle", 2, 0 /* 2 */, "void (*)(void)" }, { "proc", "signal-send", 0, 0, "struct task_struct *", }, { "proc", "signal-send", 1, 0, "int", }, + + { "sched", "tick", 0, 0, "struct task_struct *", }, + { NULL, } }; diff --git a/dtrace/sdt_impl.h b/dtrace/sdt_impl.h index c6a066d56e1a..e26f795de507 100644 --- a/dtrace/sdt_impl.h +++ b/dtrace/sdt_impl.h @@ -20,6 +20,15 @@ typedef struct sdt_probe { struct sdt_probe *sdp_hashnext; /* next on hash */ } sdt_probe_t; +typedef struct sdt_argdesc { + char *sda_provider; + char *sda_name; + int sda_ndx; + int sda_mapping; + char *sda_native; + char *sda_xlate; +} sdt_argdesc_t; + extern dtrace_mprovider_t sdt_providers[]; extern void sdt_provide_module(void *, struct module *); -- 2.50.1