obj-$(CONFIG_DT_CORE) += dtrace.o
obj-$(CONFIG_DT_FASTTRAP) += fasttrap.o
+obj-$(CONFIG_DT_FBT) += fbt.o
obj-$(CONFIG_DT_PROFILE) += profile.o
obj-$(CONFIG_DT_SDT) += sdt.o
obj-$(CONFIG_DT_SYSTRACE) += systrace.o
dtrace_ptofapi.o dtrace_predicate.o \
dtrace_spec.o dtrace_state.o dtrace_util.o
fasttrap-y := fasttrap_mod.o fasttrap_dev.o fasttrap_$(UTS_MACHINE).o
+fbt-y := fbt_mod.o fbt_dev.o fbt_$(UTS_MACHINE).o
profile-y := profile_mod.o profile_dev.o
sdt-y := sdt_mod.o sdt_dev.o sdt_$(UTS_MACHINE).o
systrace-y := systrace_mod.o systrace_dev.o
uint64_t dtrace_getarg(int argno, int aframes)
{
- uintptr_t val;
struct sparc_v9_frame *fp;
uint64_t rval;
- int lvl;
/*
* Account for the fact that dtrace_getarg() consumes an additional
#ifdef FIXME
if (argno < 6) {
- if ((lvl = dtrace_fish(aframes, REG_I0 + argno, &val)) == 0)
+ if ((lvl = dtrace_fish(aframes, ASM_REG_I0 + argno, &val)) == 0)
return val;
} else {
- if ((lvl = dtrace_fish(aframes, REG_I6, &val)) == 0) {
+ if ((lvl = dtrace_fish(aframes, ASM_REG_I6, &val)) == 0) {
/*
* We have a stack pointer; grab the argument.
*/
{
struct pt_regs *rp = task_pt_regs(task);
- if (reg <= REG_O7) /* G[0-7], O[0-7] */
+ if (reg <= ASM_REG_O7) /* G[0-7], O[0-7] */
return rp->u_regs[reg]; /* 0 .. 15 */
- if (reg <= REG_I7) { /* L[0-7], I[0-7] */
+ if (reg <= ASM_REG_I7) { /* L[0-7], I[0-7] */
if (rp->tstate & TSTATE_PRIV) {
struct reg_window *rw;
rw = (struct reg_window *)(rp->u_regs[14] + STACK_BIAS);
- if (reg <= REG_L7)
- return rw->locals[reg - REG_L0];
+ if (reg <= ASM_REG_L7)
+ return rw->locals[reg - ASM_REG_L0];
else
- return rw->ins[reg - REG_I0];
+ return rw->ins[reg - ASM_REG_I0];
} else {
mm_segment_t old_fs;
struct reg_window __user *rw;
DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
- if (reg <= REG_L7)
- val = dtrace_fulword(&rw->locals[reg - REG_L0]);
+ if (reg <= ASM_REG_L7)
+ val = dtrace_fulword(
+ &rw->locals[reg - ASM_REG_L0]
+ );
else
- val = dtrace_fulword(&rw->locals[reg - REG_I0]);
+ val = dtrace_fulword(
+ &rw->locals[reg - ASM_REG_I0]
+ );
DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
void pdata_init(dtrace_module_t *pdata, struct module *mp)
{
- if (mp->pdata)
- pdata->sdt_tab = mp->pdata;
+ if (mp->pdata) {
+ pdata->sdt_tab = (asm_instr_t *)((uintptr_t)mp->pdata +
+ DTRACE_PD_SDT_OFF(mp));
+ pdata->fbt_tab = (asm_instr_t *)((uintptr_t)mp->pdata +
+ DTRACE_PD_FBT_OFF(mp));
+ } else {
+ pdata->sdt_tab = NULL;
+ pdata->fbt_tab = NULL;
+ }
}
void pdata_cleanup(dtrace_module_t *pdata, struct module *mp)
{
- mp->pdata = pdata->sdt_tab;
+ mp->pdata = (void *)((uintptr_t)pdata->sdt_tab - DTRACE_PD_SDT_OFF(mp));
}
return (*(const uint32_t *)ap - *(const uint32_t *)bp);
}
-#if 0
-static int fasttrap_uint64_cmp(const void *ap, const void *bp)
-{
- return (*(const uint64_t *)ap - *(const uint64_t *)bp);
-}
-#endif
-
void fasttrap_meta_create_probe(void *arg, void *parg,
dtrace_helper_probedesc_t *dhpb)
{
const dtrace_pattr_t *pa)
{
fasttrap_provider_t *fp, *new_fp = NULL;
- fasttrap_proc_t *proc;
+ fasttrap_proc_t *proc = NULL;
fasttrap_bucket_t *bucket;
char provname[DTRACE_PROVNAMELEN];
struct task_struct *p;
void fasttrap_set_enabled(struct pt_regs *regs)
{
- regs->u_regs[REG_O0] = 1;
+ regs->u_regs[ASM_REG_O0] = 1;
}
--- /dev/null
+/*
+ * FILE: fbt_dev.c
+ * DESCRIPTION: Function Boundary Tracing: device file handling
+ *
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright 2010, 2011, 2012, 2013 Oracle, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/kallsyms.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/dtrace_fbt.h>
+
+#include "dtrace.h"
+#include "dtrace_dev.h"
+#include "fbt_impl.h"
+
+#define FBT_PROBETAB_SIZE 0x8000 /* 32k entries -- 128K total */
+
+fbt_probe_t **fbt_probetab;
+int fbt_probetab_size = FBT_PROBETAB_SIZE;
+int fbt_probetab_mask;
+
+static void *fbt_provide_probe(struct module *mp, char *func, int type, int
+ stype, asm_instr_t *addr, void *pfbt)
+{
+ fbt_probe_t *fbp;
+ fbt_probe_t *prev;
+
+ /*
+ * Only syscalls for now...
+ */
+ if (strncmp(func, "SyS_", 4))
+ return NULL;
+
+ switch (type) {
+ case FBT_ENTRY:
+ fbp = kzalloc(sizeof(fbt_probe_t), GFP_KERNEL);
+ fbp->fbp_name = kstrdup(func, GFP_KERNEL);
+ fbp->fbp_id = dtrace_probe_create(fbt_id, mp->name, func,
+ "entry", 3, fbp);
+ fbp->fbp_module = mp;
+ fbp->fbp_loadcnt = 1; /* FIXME */
+ fbp->fbp_primary = 1; /* FIXME */
+ fbp->fbp_patchpoint = addr;
+ fbt_provide_probe_arch(fbp, type, stype);
+ fbp->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(addr)];
+
+ fbt_probetab[FBT_ADDR2NDX(addr)] = fbp;
+
+ PDATA(mp)->fbt_probe_cnt++;
+
+ return fbp;
+ case FBT_RETURN:
+ fbp = kzalloc(sizeof(fbt_probe_t), GFP_KERNEL);
+ fbp->fbp_name = kstrdup(func, GFP_KERNEL);
+
+ prev = (fbt_probe_t *)pfbt;
+ if (prev != NULL) {
+ prev->fbp_next = fbp;
+ fbp->fbp_id = prev->fbp_id;
+ } else {
+ fbp->fbp_id = dtrace_probe_create(fbt_id, mp->name,
+ func, "return", 3,
+ fbp);
+ }
+
+ fbp->fbp_module = mp;
+ fbp->fbp_loadcnt = 1; /* FIXME */
+ fbp->fbp_primary = 1; /* FIXME */
+ fbp->fbp_patchpoint = addr;
+ fbt_provide_probe_arch(fbp, type, stype);
+ fbp->fbp_hashnext = fbt_probetab[FBT_ADDR2NDX(addr)];
+
+ fbt_probetab[FBT_ADDR2NDX(addr)] = fbp;
+
+ PDATA(mp)->fbt_probe_cnt++;
+
+ return fbp;
+ default:
+ printk(KERN_INFO "FBT: Invalid probe type %d (%d) for %s\n",
+ type, stype, func);
+
+ return NULL;
+ }
+}
+
+void fbt_provide_module(void *arg, struct module *mp)
+{
+ /*
+ * Nothing to do if the module FBT probes were already created.
+ */
+ if (PDATA(mp)->fbt_probe_cnt != 0)
+ return;
+
+ if (strncmp(mp->name, "vmlinux", 7))
+ return;
+
+ dtrace_fbt_init((fbt_add_probe_fn)fbt_provide_probe);
+}
+
+int _fbt_enable(void *arg, dtrace_id_t id, void *parg)
+{
+ fbt_probe_t *fbp = parg;
+ fbt_probe_t *curr;
+
+ /*
+ * Ensure that we have a reference to the module.
+ */
+ if (!try_module_get(fbp->fbp_module))
+ return -EAGAIN;
+
+ /*
+ * If at least one other enabled probe exists for this module, drop the
+ * reference we took above, because we only need one to prevent the
+ * module from being unloaded.
+ */
+ PDATA(fbp->fbp_module)->enabled_cnt++;
+ if (PDATA(fbp->fbp_module)->enabled_cnt > 1)
+ module_put(fbp->fbp_module);
+
+ for (curr = fbp; curr != NULL; curr = curr->fbp_next)
+ fbt_enable_arch(curr, id, arg);
+
+ return 0;
+}
+
+void _fbt_disable(void *arg, dtrace_id_t id, void *parg)
+{
+ fbt_probe_t *fbp = parg;
+ fbt_probe_t *curr;
+
+ for (curr = fbp; curr != NULL; curr = curr->fbp_next)
+ fbt_disable_arch(curr, id, arg);
+
+ /*
+ * If we are disabling a probe, we know it was enabled, and therefore
+ * we know that we have a reference on the module to prevent it from
+ * being unloaded. If we disable the last probe on the module, we can
+ * drop the reference.
+ */
+ PDATA(fbp->fbp_module)->enabled_cnt--;
+ if (PDATA(fbp->fbp_module)->enabled_cnt == 0)
+ module_put(fbp->fbp_module);
+}
+
+void fbt_destroy(void *arg, dtrace_id_t id, void *parg)
+{
+ fbt_probe_t *fbp = parg;
+ fbt_probe_t *nxt, *hbp, *lst;
+ struct module *mp = fbp->fbp_module;
+ int ndx;
+
+ do {
+ if (mp != NULL)
+ PDATA(mp)->fbt_probe_cnt--;
+
+ ndx = FBT_ADDR2NDX(fbp->fbp_patchpoint);
+ lst = NULL;
+ hbp = fbt_probetab[ndx];
+
+ while (hbp != fbp) {
+ ASSERT(hbp != NULL);
+
+ lst = hbp;
+ hbp = hbp->fbp_hashnext;
+ }
+
+ if (lst != NULL)
+ lst->fbp_hashnext = fbp->fbp_hashnext;
+ else
+ fbt_probetab[ndx] = fbp->fbp_hashnext;
+
+ nxt = fbp->fbp_next;
+
+ kfree(fbp);
+
+ fbp = nxt;
+ } while (fbp != NULL);
+}
+
+static long fbt_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return -EAGAIN;
+}
+
+static int fbt_open(struct inode *inode, struct file *file)
+{
+ return -EAGAIN;
+}
+
+static int fbt_close(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static const struct file_operations fbt_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = fbt_ioctl,
+ .open = fbt_open,
+ .release = fbt_close,
+};
+
+static struct miscdevice fbt_dev = {
+ .minor = DT_DEV_FBT_MINOR,
+ .name = "fbt",
+ .nodename = "dtrace/provider/fbt",
+ .fops = &fbt_fops,
+};
+
+int fbt_dev_init(void)
+{
+ int ret = 0;
+
+ 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",
+ fbt_dev.name, fbt_dev.minor);
+
+ fbt_dev_init_arch();
+
+ return ret;
+}
+
+void fbt_dev_exit(void)
+{
+ fbt_dev_exit_arch();
+
+ misc_deregister(&fbt_dev);
+
+ vfree(fbt_probetab);
+ fbt_probetab_mask = 0;
+ fbt_probetab_size = 0;
+}
--- /dev/null
+#ifndef _FBT_H_
+#define _FBT_H_
+
+#include <asm/dtrace_arch.h>
+
+typedef struct fbt_probe {
+ char *fbp_name; /* name of probe */
+ dtrace_id_t fbp_id; /* probe ID */
+ struct module *fbp_module; /* defining module */
+ int fbp_loadcnt; /* load count for module */
+ int fbp_primary; /* non-zero if primary mod */
+ asm_instr_t *fbp_patchpoint;/* patch point */
+ asm_instr_t fbp_patchval; /* instruction to patch */
+ asm_instr_t fbp_savedval; /* saved instruction value */
+ uintptr_t fbp_roffset;
+ int fbp_rval;
+ struct fbt_probe *fbp_next; /* next probe */
+ struct fbt_probe *fbp_hashnext; /* next on hash */
+} fbt_probe_t;
+
+#define FBT_ADDR2NDX(addr) ((((uintptr_t)(addr)) >> 4) & \
+ fbt_probetab_mask)
+
+extern fbt_probe_t **fbt_probetab;
+extern int fbt_probetab_size;
+extern int fbt_probetab_mask;
+
+extern void fbt_provide_probe_arch(fbt_probe_t *, int, int);
+extern void fbt_enable_arch(fbt_probe_t *, dtrace_id_t, void *);
+extern void fbt_disable_arch(fbt_probe_t *, dtrace_id_t, void *);
+
+extern void fbt_provide_module(void *, struct module *);
+extern int _fbt_enable(void *, dtrace_id_t, void *);
+extern void _fbt_disable(void *, dtrace_id_t, void *);
+extern void fbt_destroy(void *, dtrace_id_t, void *);
+
+extern dtrace_provider_id_t fbt_id;
+
+extern int fbt_dev_init_arch(void);
+extern void fbt_dev_exit_arch(void);
+
+extern int fbt_dev_init(void);
+extern void fbt_dev_exit(void);
+
+#endif /* _FBT_H_ */
--- /dev/null
+/*
+ * FILE: fbt_mod.c
+ * DESCRIPTION: Function Boundary Tracing: module handling
+ *
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright 2010, 2011, 2012, 2013 Oracle, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <linux/module.h>
+
+#include "dtrace.h"
+#include "dtrace_dev.h"
+#include "fbt_impl.h"
+
+MODULE_AUTHOR("Kris Van Hees (kris.van.hees@oracle.com)");
+MODULE_DESCRIPTION("Function Boundary Tracing");
+MODULE_VERSION("v0.1");
+MODULE_LICENSE("CDDL");
+
+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)
--- /dev/null
+/*
+ * FILE: fbt_sparc64.c
+ * DESCRIPTION: Function Boundary Tracing: architecture-specific implementation
+ *
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright 2010-2014 Oracle, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <linux/dtrace_fbt.h>
+#include <asm/dtrace_util.h>
+#include <dtrace/isa_arch.h>
+
+#include "dtrace.h"
+#include "dtrace_dev.h"
+#include "fbt_impl.h"
+
+/*
+ * For entry probes, we generate the following trampoline (for id < 0xfff):
+ *
+ * sethi %hi(id), %o0
+ * or %o0, %lo(id), %o0
+ * mov %i0, %o1
+ * mov %i1, %o2
+ * mov %i2, %o3
+ * mov %i3, %o4
+ * mov %i4, %o5
+ * call dtrace_probe
+ * nop
+ * sethi %hi(instr), %o7
+ * or %o7, %lo(instr), %o7
+ * retl
+ * nop
+ *
+ * otherwise we use:
+ *
+ * or %g0, id, %o0
+ * mov %i0, %o1
+ * mov %i1, %o2
+ * mov %i2, %o3
+ * mov %i3, %o4
+ * mov %i4, %o5
+ * call dtrace_probe
+ * nop
+ * sethi %hi(instr), %o7
+ * or %o7, %lo(instr), %o7
+ * retl
+ * nop
+ */
+#ifndef FBT_TRAMP_SIZE
+# error The kernel must define FBT_TRAMP_SIZE!
+#elif FBT_TRAMP_SIZE < 13
+# error FBT_TRAMP_SIZE must be at least 13 instructions!
+#endif
+
+static void add_entry_tramp(fbt_probe_t *fbp, int nargs)
+{
+ struct module *mp = fbp->fbp_module;
+ dtrace_id_t id = fbp->fbp_id;
+ size_t idx = PDATA(mp)->fbt_probe_cnt;
+ asm_instr_t *trampoline = &(PDATA(mp)->fbt_tab[idx *
+ FBT_TRAMP_SIZE]);
+ asm_instr_t *instr = trampoline;
+
+ if (id > (uint32_t)ASM_SIMM13_MAX) {
+ *instr++ = ASM_SETHI(id, ASM_REG_O0);
+ *instr++ = ASM_ORLO(ASM_REG_O0, id, ASM_REG_O0);
+ } else
+ *instr++ = ASM_ORSIMM13(ASM_REG_G0, id, ASM_REG_O0);
+
+ if (nargs >= 1)
+ *instr++ = ASM_MOV(ASM_REG_I0, ASM_REG_O1);
+ if (nargs >= 2)
+ *instr++ = ASM_MOV(ASM_REG_I1, ASM_REG_O2);
+ if (nargs >= 3)
+ *instr++ = ASM_MOV(ASM_REG_I2, ASM_REG_O3);
+ if (nargs >= 4)
+ *instr++ = ASM_MOV(ASM_REG_I3, ASM_REG_O4);
+ if (nargs >= 5)
+ *instr++ = ASM_MOV(ASM_REG_I4, ASM_REG_O5);
+
+ *instr = ASM_CALL(instr, dtrace_probe);
+ instr++;
+
+ *instr++ = ASM_NOP;
+
+ if ((uintptr_t)fbp->fbp_patchpoint > (uintptr_t)ASM_SIMM13_MAX) {
+ *instr++ = ASM_SETHI(
+ (uintptr_t)fbp->fbp_patchpoint, ASM_REG_O7
+ );
+ *instr++ = ASM_ORLO(ASM_REG_O7, (uintptr_t)fbp->fbp_patchpoint,
+ ASM_REG_O7);
+ } else
+ *instr++ = ASM_ORSIMM13(ASM_REG_G0,
+ (uintptr_t)fbp->fbp_patchpoint,
+ ASM_REG_O7);
+
+ *instr++ = ASM_RETL;
+ *instr++ = ASM_NOP;
+
+ fbp->fbp_patchval = ASM_CALL(fbp->fbp_patchpoint, trampoline);
+ fbp->fbp_savedval = *fbp->fbp_patchpoint;
+}
+
+void fbt_provide_probe_arch(fbt_probe_t *fbp, int type, int stype)
+{
+ switch (type) {
+ case FBT_ENTRY:
+ add_entry_tramp(fbp, stype);
+ return;
+ case FBT_RETURN:
+ pr_info("%s: %s: FBT_RETURN not supported yet\n",
+ __func__, fbp->fbp_name);
+ return;
+ default:
+ pr_info("%s: %s: Unknown FBT type %d\n",
+ __func__, fbp->fbp_name, type);
+ return;
+ }
+}
+
+void fbt_enable_arch(fbt_probe_t *fbp, dtrace_id_t id, void *arg)
+{
+ *fbp->fbp_patchpoint = fbp->fbp_patchval;
+}
+
+void fbt_disable_arch(fbt_probe_t *fbp, dtrace_id_t id, void *arg)
+{
+ *fbp->fbp_patchpoint = fbp->fbp_savedval;
+}
+
+int fbt_dev_init_arch(void)
+{
+ return 0;
+}
+
+void fbt_dev_exit_arch(void)
+{
+}
--- /dev/null
+/*
+ * FILE: fbt_x86_64.c
+ * DESCRIPTION: Function Boundary Tracing: architecture-specific implementation
+ *
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * Copyright 2010-2014 Oracle, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <linux/dtrace_fbt.h>
+#include <asm/dtrace_util.h>
+
+#include "dtrace.h"
+#include "dtrace_dev.h"
+#include "fbt_impl.h"
+
+#define FBT_PATCHVAL 0xf0
+
+static uint8_t fbt_invop(struct pt_regs *regs)
+{
+ fbt_probe_t *fbp = fbt_probetab[FBT_ADDR2NDX(regs->ip)];
+
+ for (; fbp != NULL; fbp = fbp->fbp_hashnext) {
+ if ((uintptr_t)fbp->fbp_patchpoint == regs->ip) {
+ this_cpu_core->cpu_dtrace_regs = regs;
+
+ dtrace_probe(fbp->fbp_id, regs->di, regs->si,
+ regs->dx, regs->cx, regs->r8);
+
+ this_cpu_core->cpu_dtrace_regs = NULL;
+
+ return fbp->fbp_rval;
+ }
+ }
+
+ return 0;
+}
+
+void fbt_provide_probe_arch(fbt_probe_t *fbp, int type, int stype)
+{
+ fbp->fbp_patchval = FBT_PATCHVAL;
+ fbp->fbp_savedval = *fbp->fbp_patchpoint;
+ fbp->fbp_rval = type == FBT_ENTRY ? DTRACE_INVOP_MOV_RSP_RBP
+ : DTRACE_INVOP_RET;
+}
+
+void fbt_enable_arch(fbt_probe_t *fbp, dtrace_id_t id, void *arg)
+{
+ dtrace_invop_enable((uint8_t *)fbp->fbp_patchpoint);
+}
+
+void fbt_disable_arch(fbt_probe_t *fbp, dtrace_id_t id, void *arg)
+{
+ dtrace_invop_disable((uint8_t *)fbp->fbp_patchpoint,
+ fbp->fbp_savedval);
+}
+
+int fbt_dev_init_arch(void)
+{
+ return dtrace_invop_add(fbt_invop);
+}
+
+void fbt_dev_exit_arch(void)
+{
+ dtrace_invop_remove(fbt_invop);
+}
#define _SPARC64_ISA_ARCH_H
/*
- * FILE: isa_arch.h
- * DESCRIPTION: Dynamic Tracing: sparc64 ISA-specific definitions
+ * FILE: isa_arch.c
+ * DESCRIPTION: Dynamic Tracing: sparc64 ISA-specific definitions
*
* CDDL HEADER START
*
* Use is subject to license terms.
*/
+
/* Register indices */
-#define REG_G0 0
-#define REG_G1 (REG_G0 + 1)
-#define REG_G2 (REG_G0 + 2)
-#define REG_G3 (REG_G0 + 3)
-#define REG_G4 (REG_G0 + 4)
-#define REG_G5 (REG_G0 + 5)
-#define REG_G6 (REG_G0 + 6)
-#define REG_G7 (REG_G0 + 7)
-
-#define REG_O0 (REG_G7 + 1) /* 8 */
-#define REG_O1 (REG_O0 + 1)
-#define REG_O2 (REG_O0 + 2)
-#define REG_O3 (REG_O0 + 3)
-#define REG_O4 (REG_O0 + 4)
-#define REG_O5 (REG_O0 + 5)
-#define REG_O6 (REG_O0 + 6)
-#define REG_O7 (REG_O0 + 7)
-
-#define REG_L0 (REG_O7 + 1) /* 16 */
-#define REG_L1 (REG_L0 + 1)
-#define REG_L2 (REG_L0 + 2)
-#define REG_L3 (REG_L0 + 3)
-#define REG_L4 (REG_L0 + 4)
-#define REG_L5 (REG_L0 + 5)
-#define REG_L6 (REG_L0 + 6)
-#define REG_L7 (REG_L0 + 7)
-
-#define REG_I0 (REG_L7 + 1) /* 24 */
-#define REG_I1 (REG_I0 + 1)
-#define REG_I2 (REG_I0 + 2)
-#define REG_I3 (REG_I0 + 3)
-#define REG_I4 (REG_I0 + 4)
-#define REG_I5 (REG_I0 + 5)
-#define REG_I6 (REG_I0 + 6)
-#define REG_I7 (REG_I0 + 7)
-
-#define REG_CCR (REG_I7 + 1) /* 32 */
-
-#define REG_PC (REG_CCR + 1) /* 33 */
-#define REG_nPC (REG_PC + 1) /* 34 */
-#define REG_Y (REG_nPC + 1) /* 35 */
-
-#define REG_ASI (REG_Y + 1) /* 36 */
-#define REG_FPRS (REG_ASI + 1) /* 37 */
+#define ASM_REG_G0 0
+#define ASM_REG_G1 (ASM_REG_G0 + 1)
+#define ASM_REG_G2 (ASM_REG_G0 + 2)
+#define ASM_REG_G3 (ASM_REG_G0 + 3)
+#define ASM_REG_G4 (ASM_REG_G0 + 4)
+#define ASM_REG_G5 (ASM_REG_G0 + 5)
+#define ASM_REG_G6 (ASM_REG_G0 + 6)
+#define ASM_REG_G7 (ASM_REG_G0 + 7)
+
+#define ASM_REG_O0 (ASM_REG_G7 + 1) /* 8 */
+#define ASM_REG_O1 (ASM_REG_O0 + 1)
+#define ASM_REG_O2 (ASM_REG_O0 + 2)
+#define ASM_REG_O3 (ASM_REG_O0 + 3)
+#define ASM_REG_O4 (ASM_REG_O0 + 4)
+#define ASM_REG_O5 (ASM_REG_O0 + 5)
+#define ASM_REG_O6 (ASM_REG_O0 + 6)
+#define ASM_REG_O7 (ASM_REG_O0 + 7)
+
+#define ASM_REG_L0 (ASM_REG_O7 + 1) /* 16 */
+#define ASM_REG_L1 (ASM_REG_L0 + 1)
+#define ASM_REG_L2 (ASM_REG_L0 + 2)
+#define ASM_REG_L3 (ASM_REG_L0 + 3)
+#define ASM_REG_L4 (ASM_REG_L0 + 4)
+#define ASM_REG_L5 (ASM_REG_L0 + 5)
+#define ASM_REG_L6 (ASM_REG_L0 + 6)
+#define ASM_REG_L7 (ASM_REG_L0 + 7)
+
+#define ASM_REG_I0 (ASM_REG_L7 + 1) /* 24 */
+#define ASM_REG_I1 (ASM_REG_I0 + 1)
+#define ASM_REG_I2 (ASM_REG_I0 + 2)
+#define ASM_REG_I3 (ASM_REG_I0 + 3)
+#define ASM_REG_I4 (ASM_REG_I0 + 4)
+#define ASM_REG_I5 (ASM_REG_I0 + 5)
+#define ASM_REG_I6 (ASM_REG_I0 + 6)
+#define ASM_REG_I7 (ASM_REG_I0 + 7)
+
+#define REG_CCR (ASM_REG_I7 + 1) /* 32 */
+#define REG_PC (REG_CCR + 1) /* 33 */
+#define REG_nPC (REG_PC + 1) /* 34 */
+#define REG_Y (REG_nPC + 1) /* 35 */
+#define REG_ASI (REG_Y + 1) /* 36 */
+#define REG_FPRS (REG_ASI + 1) /* 37 */
+
+#define ASM_REG_PC 5
+
+#define ASM_REG_ISGLOBAL(r) ((r) >= ASM_REG_G0 && (r) <= ASM_REG_G7)
+#define ASM_REG_ISOUTPUT(r) ((r) >= ASM_REG_O0 && (r) <= ASM_REG_O7)
+#define ASM_REG_ISLOCAL(r) ((r) >= ASM_REH_L0 && (r) <= ASM_REG_L7)
+#define ASM_REG_ISINPUT(r) ((r) >= ASM_REG_I0 && (r) <= ASM_REG_I7)
+#define ASM_REG_ISVOLATILE(r) \
+ ((ASM_REG_ISGLOBAL(r) || ASM_REG_ISOUTPUT(r)) && (r) != ASM_REG_G0)
+#define ASM_REG_NLOCALS 8
+
+#define ASM_REG_MARKLOCAL(locals, r) \
+ if (ASM_REG_ISLOCAL(r)) \
+ (locals)[(r) - ASM_REG_L0] = 1;
+
+#define ASM_REG_INITLOCALS(local, locals) \
+ for ((local) = 0; (local) < ASM_REG_NLOCALS; (local)++) \
+ (locals)[(local)] = 0; \
+ (local) = ASM_REG_L0
+
+#define ASM_REG_ALLOCLOCAL(local, locals) \
+ while ((locals)[(local) - ASM_REG_L0]) \
+ (local)++; \
+ (locals)[(local) - ASM_REG_L0] = 1;
+
+#define ASM_OP_MASK 0xc0000000
+#define ASM_OP_SHIFT 30
+#define ASM_OP(val) ((val) & ASM_OP_MASK)
+
+#define ASM_SIMM13_MASK 0x1fff
+#define ASM_SIMM13_MAX ((int32_t)0xfff)
+#define ASM_IMM22_MASK 0x3fffff
+#define ASM_IMM22_SHIFT 10
+#define ASM_IMM10_MASK 0x3ff
+
+#define ASM_DISP30_MASK 0x3fffffff
+#define ASM_DISP30(from, to) \
+ (((long)(to) - (long)(from)) >= 0 \
+ ? ((((uintptr_t)(to) - (uintptr_t)(from)) >> 2) & ASM_DISP30_MASK) \
+ : ((((long)(to) - (long)(from)) >> 2) & ASM_DISP30_MASK))
+
+#define ASM_DISP22_MASK 0x3fffff
+#define ASM_DISP22(from, to) \
+ ((((uintptr_t)(to) - (uintptr_t)(from)) >> 2) & ASM_DISP22_MASK)
+
+#define ASM_DISP19_MASK 0x7ffff
+#define ASM_DISP19(from, to) \
+ ((((uintptr_t)(to) - (uintptr_t)(from)) >> 2) & ASM_DISP19_MASK)
+
+#define ASM_DISP16_HISHIFT 20
+#define ASM_DISP16_HIMASK (0x3 << ASM_DISP16_HISHIFT)
+#define ASM_DISP16_LOMASK (0x3fff)
+#define ASM_DISP16_MASK (ASM_DISP16_HIMASK | ASM_DISP16_LOMASK)
+#define ASM_DISP16(val) \
+ ((((val) & ASM_DISP16_HIMASK) >> 6) | ((val) & ASM_DISP16_LOMASK))
+
+#define ASM_DISP14_MASK 0x3fff
+#define ASM_DISP14(from, to) \
+ (((uintptr_t)(to) - (uintptr_t)(from) >> 2) & ASM_DISP14_MASK)
+
+#define ASM_OP0 (((uint32_t)0) << ASM_OP_SHIFT)
+#define ASM_OP1 (((uint32_t)1) << ASM_OP_SHIFT)
+#define ASM_OP2 (((uint32_t)2) << ASM_OP_SHIFT)
+#define ASM_ILLTRAP 0
+
+#define ASM_ANNUL_SHIFT 29
+#define ASM_ANNUL (1 << ASM_ANNUL_SHIFT)
+
+#define ASM_FMT3_OP3_SHIFT 19
+#define ASM_FMT3_OP_MASK 0xc1f80000
+#define ASM_FMT3_OP(val) ((val) & ASM_FMT3_OP_MASK)
+
+#define ASM_FMT3_RD_SHIFT 25
+#define ASM_FMT3_RD_MASK (0x1f << ASM_FMT3_RD_SHIFT)
+#define ASM_FMT3_RD(val) \
+ (((val) & ASM_FMT3_RD_MASK) >> ASM_FMT3_RD_SHIFT)
+
+#define ASM_FMT3_RS1_SHIFT 14
+#define ASM_FMT3_RS1_MASK (0x1f << ASM_FMT3_RS1_SHIFT)
+#define ASM_FMT3_RS1(val) \
+ (((val) & ASM_FMT3_RS1_MASK) >> ASM_FMT3_RS1_SHIFT)
+#define ASM_FMT3_RS1_SET(val, rs1) \
+ (val) = ((val) & ~ASM_FMT3_RS1_MASK) | ((rs1) << ASM_FMT3_RS1_SHIFT)
+
+#define ASM_FMT3_RS2_SHIFT 0
+#define ASM_FMT3_RS2_MASK (0x1f << ASM_FMT3_RS2_SHIFT)
+#define ASM_FMT3_RS2(val) \
+ (((val) & ASM_FMT3_RS2_MASK) >> ASM_FMT3_RS2_SHIFT)
+#define ASM_FMT3_RS2_SET(val, rs2) \
+ (val) = ((val) & ~ASM_FMT3_RS2_MASK) | ((rs2) << ASM_FMT3_RS2_SHIFT)
+
+#define ASM_FMT3_IMM_SHIFT 13
+#define ASM_FMT3_IMM (1 << ASM_FMT3_IMM_SHIFT)
+#define ASM_FMT3_SIMM13_MASK ASM_SIMM13_MASK
+
+#define ASM_FMT3_ISIMM(val) ((val) & ASM_FMT3_IMM)
+#define ASM_FMT3_SIMM13(val) ((val) & ASM_FMT3_SIMM13_MASK)
+
+#define ASM_FMT2_OP2_SHIFT 22
+#define ASM_FMT2_OP2_MASK (0x7 << ASM_FMT2_OP2_SHIFT)
+#define ASM_FMT2_RD_SHIFT 25
+
+#define ASM_FMT1_OP(val) ((val) & ASM_OP_MASK)
+#define ASM_FMT1_DISP30(val) ((val) & ASM_DISP30_MASK)
+
+#define ASM_FMT2_OP2_BPCC (0x01 << ASM_FMT2_OP2_SHIFT)
+#define ASM_FMT2_OP2_BCC (0x02 << ASM_FMT2_OP2_SHIFT)
+#define ASM_FMT2_OP2_BPR (0x03 << ASM_FMT2_OP2_SHIFT)
+#define ASM_FMT2_OP2_SETHI (0x04 << ASM_FMT2_OP2_SHIFT)
+
+#define ASM_FMT2_COND_SHIFT 25
+#define ASM_FMT2_COND_BA (0x8 << ASM_FMT2_COND_SHIFT)
+#define ASM_FMT2_COND_BL (0x3 << ASM_FMT2_COND_SHIFT)
+#define ASM_FMT2_COND_BGE (0xb << ASM_FMT2_COND_SHIFT)
+
+#define ASM_OP_RESTORE (ASM_OP2 | (0x3d << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_SAVE (ASM_OP2 | (0x3c << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_JMPL (ASM_OP2 | (0x38 << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_RETURN (ASM_OP2 | (0x39 << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_CALL ASM_OP1
+#define ASM_OP_SETHI (ASM_OP0 | ASM_FMT2_OP2_SETHI)
+#define ASM_OP_ADD (ASM_OP2 | (0x00 << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_OR (ASM_OP2 | (0x02 << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_SUB (ASM_OP2 | (0x04 << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_CC (ASM_OP2 | (0x10 << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_UDIV (ASM_OP2 | (0x0e << ASM_FMT3_OP3_SHIFT))
+#define ASM_OP_BA (ASM_OP0 | ASM_FMT2_OP2_BCC | ASM_FMT2_COND_BA)
+#define ASM_OP_BL (ASM_OP0 | ASM_FMT2_OP2_BCC | ASM_FMT2_COND_BL)
+#define ASM_OP_BGE (ASM_OP0 | ASM_FMT2_OP2_BCC | ASM_FMT2_COND_BGE)
+#define ASM_OP_BAPCC (ASM_OP0 | ASM_FMT2_OP2_BPCC | ASM_FMT2_COND_BA)
+#define ASM_OP_RD (ASM_OP2 | (0x28 << ASM_FMT3_OP3_SHIFT))
+
+#define ASM_ORLO(rs, val, rd) \
+ (ASM_OP_OR | ((rs) << ASM_FMT3_RS1_SHIFT) | \
+ ((rd) << ASM_FMT3_RD_SHIFT) | ASM_FMT3_IMM | ((val) & ASM_IMM10_MASK))
+
+#define ASM_ORSIMM13(rs, val, rd) \
+ (ASM_OP_OR | ((rs) << ASM_FMT3_RS1_SHIFT) | \
+ ((rd) << ASM_FMT3_RD_SHIFT) | ASM_FMT3_IMM | \
+ ((val) & ASM_SIMM13_MASK))
+
+#define ASM_ADDSIMM13(rs, val, rd) \
+ (ASM_OP_ADD | ((rs) << ASM_FMT3_RS1_SHIFT) | \
+ ((rd) << ASM_FMT3_RD_SHIFT) | ASM_FMT3_IMM | \
+ ((val) & ASM_SIMM13_MASK))
+
+#define ASM_UDIVSIMM13(rs, val, rd) \
+ (ASM_OP_UDIV | ((rs) << ASM_FMT3_RS1_SHIFT) | \
+ ((rd) << ASM_FMT3_RD_SHIFT) | ASM_FMT3_IMM | \
+ ((val) & ASM_SIMM13_MASK))
+
+#define ASM_ADD(rs1, rs2, rd) \
+ (ASM_OP_ADD | ((rs1) << ASM_FMT3_RS1_SHIFT) | \
+ ((rs2) << ASM_FMT3_RS2_SHIFT) | ((rd) << ASM_FMT3_RD_SHIFT))
+
+#define ASM_CMP(rs1, rs2) \
+ (ASM_OP_SUB | ASM_OP_CC | ((rs1) << ASM_FMT3_RS1_SHIFT) | \
+ ((rs2) << ASM_FMT3_RS2_SHIFT) | (ASM_REG_G0 << ASM_FMT3_RD_SHIFT))
+
+#define ASM_MOV(rs, rd) \
+ (ASM_OP_OR | (ASM_REG_G0 << ASM_FMT3_RS1_SHIFT) | \
+ ((rs) << ASM_FMT3_RS2_SHIFT) | ((rd) << ASM_FMT3_RD_SHIFT))
+
+#define ASM_SETHI(val, reg) \
+ (ASM_OP_SETHI | (reg << ASM_FMT2_RD_SHIFT) | \
+ ((val >> ASM_IMM22_SHIFT) & ASM_IMM22_MASK))
+
+#define ASM_NOP ASM_SETHI(0, 0)
+
+#define ASM_CALL(orig, dest) (ASM_OP_CALL | ASM_DISP30(orig, dest))
+
+#define ASM_RET \
+ (ASM_OP_JMPL | (ASM_REG_I7 << ASM_FMT3_RS1_SHIFT) | \
+ (ASM_REG_G0 << ASM_FMT3_RD_SHIFT) | ASM_FMT3_IMM | \
+ (sizeof (asm_instr_t) << 1))
+
+#define ASM_RETL \
+ (ASM_OP_JMPL | (ASM_REG_O7 << ASM_FMT3_RS1_SHIFT) | \
+ (ASM_REG_G0 << ASM_FMT3_RD_SHIFT) | ASM_FMT3_IMM | \
+ (sizeof (asm_instr_t) << 1))
+
+#define ASM_SAVEIMM(rd, val, rs1) \
+ (ASM_OP_SAVE | ((rs1) << ASM_FMT3_RS1_SHIFT) | \
+ ((rd) << ASM_FMT3_RD_SHIFT) | ASM_FMT3_IMM | ((val) & ASM_SIMM13_MASK))
+
+#define ASM_RESTORE(rd, rs1, rs2) \
+ (ASM_OP_RESTORE | ((rs1) << ASM_FMT3_RS1_SHIFT) | \
+ ((rd) << ASM_FMT3_RD_SHIFT) | ((rs2) << ASM_FMT3_RS2_SHIFT))
+
+#define ASM_RETURN(rs1, val) \
+ (ASM_OP_RETURN | ((rs1) << ASM_FMT3_RS1_SHIFT) | \
+ ASM_FMT3_IMM | ((val) & ASM_SIMM13_MASK))
+
+#define ASM_BA(orig, dest) (ASM_OP_BA | ASM_DISP22(orig, dest))
+#define ASM_BAA(orig, dest) (ASM_BA(orig, dest) | ASM_ANNUL)
+#define ASM_BL(orig, dest) (ASM_OP_BL | ASM_DISP22(orig, dest))
+#define ASM_BGE(orig, dest) (ASM_OP_BGE | ASM_DISP22(orig, dest))
+#define ASM_BDEST(va, instr) ((uintptr_t)(va) + \
+ (((int32_t)(((instr) & ASM_DISP22_MASK) << 10)) >> 8))
+#define ASM_BPCCDEST(va, instr) ((uintptr_t)(va) + \
+ (((int32_t)(((instr) & ASM_DISP19_MASK) << 13)) >> 11))
+#define ASM_BPRDEST(va, instr) ((uintptr_t)(va) + \
+ (((int32_t)((ASM_DISP16(instr)) << 16)) >> 14))
+
+/*
+ * We're only going to treat a save as safe if
+ * (a) both rs1 and rd are %sp and
+ * (b) if the instruction has a simm, the value isn't 0.
+ */
+#define ASM_IS_SAVE(instr) \
+ (ASM_FMT3_OP(instr) == ASM_OP_SAVE && \
+ ASM_FMT3_RD(instr) == ASM_REG_O6 && \
+ ASM_FMT3_RS1(instr) == ASM_REG_O6 && \
+ !(ASM_FMT3_ISIMM(instr) && ASM_FMT3_SIMM13(instr) == 0))
+
+#define ASM_IS_BA(instr) (((instr) & ~ASM_DISP22_MASK) == ASM_OP_BA)
+#define ASM_IS_BAPCC(instr) (((instr) & ~ASM_DISP22_MASK) == ASM_OP_BAPCC)
+
+#define ASM_IS_RDPC(instr) ((ASM_FMT3_OP(instr) == ASM_OP_RD) && \
+ (ASM_FMT3_RD(instr) == ASM_REG_PC))
+
+#define ASM_IS_PCRELATIVE(instr) \
+ ((((instr) & ASM_OP_MASK) == ASM_OP0 && \
+ ((instr) & ASM_FMT2_OP2_MASK) != ASM_FMT2_OP2_SETHI) || \
+ ((instr) & ASM_OP_MASK) == ASM_OP1 || \
+ ASM_IS_RDPC(instr))
+
+#define ASM_IS_CTI(instr) \
+ ((((instr) & ASM_OP_MASK) == ASM_OP0 && \
+ ((instr) & ASM_FMT2_OP2_MASK) != ASM_FMT2_OP2_SETHI) || \
+ ((instr) & ASM_OP_MASK) == ASM_OP1 || \
+ (ASM_FMT3_OP(instr) == ASM_OP_JMPL) || \
+ (ASM_FMT3_OP(instr) == ASM_OP_RETURN))
+
+#define ASM_IS_NOP(instr) ((instr) == ASM_NOP)
+
+#define ASM_IS_CALL(instr) (((instr) & ASM_OP_MASK) == ASM_OP_CALL)
+
+#define ASM_MOD_INPUTS(instr) (ASM_OP(instr) == ASM_OP2 && \
+ ASM_REG_ISINPUT(ASM_FMT3_RD(instr)))
+#define ASM_MOD_OUTPUTS(instr) (ASM_OP(instr) == ASM_OP2 && \
+ ASM_REG_ISOUTPUT(ASM_FMT3_RD(instr)))
/*
* Our own personal SPARC V9 stack layout structure, because the one in
* <kernel-source-tree>/arch/sparc/include/uapi/asm/ptrace.h is wrong.
*/
struct sparc_v9_frame {
- unsigned long locals[8];
- unsigned long ins[6];
- struct sparc_v9_frame *fp;
- unsigned long callers_pc;
- unsigned long xargs[6];
- unsigned long xxargs[1];
+ unsigned long locals[8];
+ unsigned long ins[6];
+ struct sparc_v9_frame *fp;
+ unsigned long callers_pc;
+ unsigned long xargs[6];
+ unsigned long xxargs[1];
};
-
#endif /* _SPARC64_ISA_ARCH_H */
* - pdata: pointer to a dtrace_module struct (for DTrace)
*/
typedef struct dtrace_module {
+ int enabled_cnt;
size_t sdt_probe_cnt;
- int sdt_enabled;
asm_instr_t *sdt_tab;
size_t fbt_probe_cnt;
+ asm_instr_t *fbt_tab;
} dtrace_module_t;
#endif /* _SPARC64_MOD_ARCH_H */
* - pdata: pointer to a dtrace_module struct (for DTrace)
*/
typedef struct dtrace_module {
+ int enabled_cnt;
size_t sdt_probe_cnt;
- int sdt_enabled;
size_t fbt_probe_cnt;
} dtrace_module_t;