From 95ac9fb9fce51443f9ff6da1c5aa4b1b5dbdab5a Mon Sep 17 00:00:00 2001 From: Kris Van Hees Date: Sat, 17 Dec 2016 18:08:44 -0500 Subject: [PATCH] dtrace: function boundary tracing (FBT) implementation This commit provides the actual implementation of the FBT provider. Signed-off-by: Kris Van Hees Orabug: 21220305 Orabug: 24829326 --- dtrace/Kbuild | 2 + dtrace/dtrace_isa_sparc64.c | 39 ++- dtrace/fasttrap_dev.c | 9 +- dtrace/fasttrap_sparc64.c | 2 +- dtrace/fbt_dev.c | 260 +++++++++++++++++ dtrace/fbt_impl.h | 45 +++ dtrace/fbt_mod.c | 62 ++++ dtrace/fbt_sparc64.c | 157 ++++++++++ dtrace/fbt_x86_64.c | 84 ++++++ dtrace/include/sparc64/dtrace/isa_arch.h | 346 +++++++++++++++++++---- dtrace/include/sparc64/dtrace/mod_arch.h | 3 +- dtrace/include/x86_64/dtrace/mod_arch.h | 2 +- 12 files changed, 932 insertions(+), 79 deletions(-) create mode 100644 dtrace/fbt_dev.c create mode 100644 dtrace/fbt_impl.h create mode 100644 dtrace/fbt_mod.c create mode 100644 dtrace/fbt_sparc64.c create mode 100644 dtrace/fbt_x86_64.c diff --git a/dtrace/Kbuild b/dtrace/Kbuild index 32a0ecf64a10..785bc2335c23 100644 --- a/dtrace/Kbuild +++ b/dtrace/Kbuild @@ -29,6 +29,7 @@ EXTRA_CFLAGS := -I$(src)/include -I$(src)/include/uapi \ 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 @@ -47,6 +48,7 @@ dtrace-y := dtrace_mod.o dtrace_dev.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 diff --git a/dtrace/dtrace_isa_sparc64.c b/dtrace/dtrace_isa_sparc64.c index 903216e89361..8901fb103776 100644 --- a/dtrace/dtrace_isa_sparc64.c +++ b/dtrace/dtrace_isa_sparc64.c @@ -34,10 +34,8 @@ 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 @@ -47,10 +45,10 @@ uint64_t dtrace_getarg(int argno, int aframes) #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. */ @@ -94,19 +92,19 @@ ulong_t dtrace_getreg(struct task_struct *task, uint_t reg) { 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; @@ -120,10 +118,14 @@ ulong_t dtrace_getreg(struct task_struct *task, uint_t reg) 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); @@ -154,11 +156,18 @@ ulong_t dtrace_getreg(struct task_struct *task, uint_t reg) 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)); } diff --git a/dtrace/fasttrap_dev.c b/dtrace/fasttrap_dev.c index e5fafcde9e7c..3d8b9b0bae3e 100644 --- a/dtrace/fasttrap_dev.c +++ b/dtrace/fasttrap_dev.c @@ -753,13 +753,6 @@ static int fasttrap_uint32_cmp(const void *ap, const void *bp) 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) { @@ -1068,7 +1061,7 @@ static fasttrap_provider_t *fasttrap_provider_lookup(pid_t pid, 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; diff --git a/dtrace/fasttrap_sparc64.c b/dtrace/fasttrap_sparc64.c index 2a52933bd013..732e7a2c42b5 100644 --- a/dtrace/fasttrap_sparc64.c +++ b/dtrace/fasttrap_sparc64.c @@ -116,6 +116,6 @@ void fasttrap_pid_probe_arch(fasttrap_probe_t *ftp, struct pt_regs *regs) void fasttrap_set_enabled(struct pt_regs *regs) { - regs->u_regs[REG_O0] = 1; + regs->u_regs[ASM_REG_O0] = 1; } diff --git a/dtrace/fbt_dev.c b/dtrace/fbt_dev.c new file mode 100644 index 000000000000..b0cc6838b508 --- /dev/null +++ b/dtrace/fbt_dev.c @@ -0,0 +1,260 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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; +} diff --git a/dtrace/fbt_impl.h b/dtrace/fbt_impl.h new file mode 100644 index 000000000000..c86355a37e77 --- /dev/null +++ b/dtrace/fbt_impl.h @@ -0,0 +1,45 @@ +#ifndef _FBT_H_ +#define _FBT_H_ + +#include + +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_ */ diff --git a/dtrace/fbt_mod.c b/dtrace/fbt_mod.c new file mode 100644 index 000000000000..fd04cf8df902 --- /dev/null +++ b/dtrace/fbt_mod.c @@ -0,0 +1,62 @@ +/* + * 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 + +#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) diff --git a/dtrace/fbt_sparc64.c b/dtrace/fbt_sparc64.c new file mode 100644 index 000000000000..437536135822 --- /dev/null +++ b/dtrace/fbt_sparc64.c @@ -0,0 +1,157 @@ +/* + * 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 +#include +#include + +#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) +{ +} diff --git a/dtrace/fbt_x86_64.c b/dtrace/fbt_x86_64.c new file mode 100644 index 000000000000..9a873c7cec2b --- /dev/null +++ b/dtrace/fbt_x86_64.c @@ -0,0 +1,84 @@ +/* + * 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 +#include + +#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); +} diff --git a/dtrace/include/sparc64/dtrace/isa_arch.h b/dtrace/include/sparc64/dtrace/isa_arch.h index 5bd2ca3b3af0..1ad496f3c126 100644 --- a/dtrace/include/sparc64/dtrace/isa_arch.h +++ b/dtrace/include/sparc64/dtrace/isa_arch.h @@ -2,8 +2,8 @@ #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 * @@ -28,64 +28,304 @@ * 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 * /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 */ diff --git a/dtrace/include/sparc64/dtrace/mod_arch.h b/dtrace/include/sparc64/dtrace/mod_arch.h index b665012c48ba..b61fc3e04683 100644 --- a/dtrace/include/sparc64/dtrace/mod_arch.h +++ b/dtrace/include/sparc64/dtrace/mod_arch.h @@ -36,10 +36,11 @@ * - 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 */ diff --git a/dtrace/include/x86_64/dtrace/mod_arch.h b/dtrace/include/x86_64/dtrace/mod_arch.h index 583baca0d65f..2aa222011f13 100644 --- a/dtrace/include/x86_64/dtrace/mod_arch.h +++ b/dtrace/include/x86_64/dtrace/mod_arch.h @@ -36,8 +36,8 @@ * - 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; -- 2.50.1