]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
dtrace: restructuring to support DTrace on multiple architectures
authorKris Van Hees <kris.van.hees@oracle.com>
Tue, 10 Feb 2015 16:33:19 +0000 (11:33 -0500)
committerKris Van Hees <kris.van.hees@oracle.com>
Mon, 20 Apr 2015 08:00:58 +0000 (04:00 -0400)
Restructure the DTrace modules code to facilitate supporting ultiple
architectures (rather than just x86_64).

- The assembler implementation of support functions is now in a file
  named dtrace_asm_<arch>.S and arch-specific aspects are found in
  dtrace_isa_<arch>.c.  The SDT provider requires an arch-specific
  portion of code as well (in sdt_<arch>.c).

- The number of frames to skip for specific probes has been updated
  to be more accurate (mistakes in this area were found during code
  review).

- The mechanism for direct calling the test probe in dt_test_probe()
  has been updated to work around compiler warnings.

- Removed dtrace_modload and dtrace_modunload.  They were expected to
  be needed for multi-arch support but it turns out that was not the
  case.

- Add conditionals to not try to build anything that relates to providers
  not necessarily being supported on all platforms.

- Various fixes for varable datatype issues that were not noticed on
  x86 because they mapped to the same or similar numeric datatypes.

- Pass the dtrace_mstate_t struct to dtrace_getstackdepth() to support
  the limitation that memory allocation cannot be done from probe
  context.  The dtrace_getstackdepth() function uses the dtrace_mstate_t
  information to obtain a scratch area of memory to use as temporary
  storage for PCs in the processing of dtrace_stacktrace().

- Handle the fact that on x86, the user sp for the current task can be
  obtained using current_user_stack_pointer() whereas other platforms
  use user_stack_pointer(current_pt_regs).

- Support that fact that the current instruction pointer is not always
  an 'ip' member of the pt_regs struct.  Always obtain the value of
  the instruction pointer using the instruction_pointer(regs function.

- Support the use of asm/dtrace_syscall.h to list the system calls
  that are implemented using an assembler stub.

- Ensure that membar functions use the SMP-versions.

- Clean up byte order conditionals.

- Remove dead code.

- Ensure needed header files are explicitly included.

- Update copyright statements.

Orabug: 20262965

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Acked-by: Nick Alcock <nick.alcock@oracle.com>
24 files changed:
dtrace/Kbuild
dtrace/dt_test_dev.c
dtrace/dtrace_actdesc.c
dtrace/dtrace_asm_x86_64.S [moved from dtrace/dtrace_asm.S with 98% similarity]
dtrace/dtrace_dev.c
dtrace/dtrace_dif.c
dtrace/dtrace_dof.c
dtrace/dtrace_ecb.c
dtrace/dtrace_enable.c
dtrace/dtrace_fmt.c
dtrace/dtrace_hash.c
dtrace/dtrace_isa.c
dtrace/dtrace_isa_x86_64.c [new file with mode: 0644]
dtrace/dtrace_probe.c
dtrace/dtrace_util.c
dtrace/include/dtrace/dtrace_impl.h
dtrace/include/dtrace/dtrace_impl_defines.h
dtrace/include/x86_64/dtrace/sdt_arch.h [new file with mode: 0644]
dtrace/profile_dev.c
dtrace/sdt_dev.c
dtrace/sdt_impl.h
dtrace/sdt_mod.c
dtrace/sdt_x86_64.c [new file with mode: 0644]
dtrace/systrace_dev.c

index 89b78c669701f02b9f44f444f2bc8ef7ffdae2c9..a567bb8c9b69c97e03cde12722a80a5eae432481 100644 (file)
@@ -24,7 +24,8 @@
 # Copyright 2011 -- 2013 Oracle, Inc.  All rights reserved.
 # Use is subject to license terms.
 
-EXTRA_CFLAGS                   := -I$(src)/include -I$(src)/include/uapi
+EXTRA_CFLAGS                   := -I$(src)/include -I$(src)/include/uapi \
+                                  -I$(src)/include/$(ARCH)
 
 obj-$(CONFIG_DT_CORE)          += dtrace.o
 obj-$(CONFIG_DT_FASTTRAP)      += fasttrap.o
@@ -35,18 +36,18 @@ obj-$(CONFIG_DT_DT_TEST)    += dt_test.o
 obj-$(CONFIG_DT_DT_PERF)       += dt_perf.o
 
 dtrace-y                       := dtrace_mod.o dtrace_dev.o \
-                                  dtrace_asm.o dtrace_isa.o \
+                                  dtrace_asm_$(ARCH).o dtrace_isa_$(ARCH).o \
                                   dtrace_actdesc.o dtrace_anon.o \
                                   dtrace_buffer.o dtrace_dif.o dtrace_dof.o \
                                   dtrace_ecb.o dtrace_enable.o \
-                                  dtrace_fmt.o dtrace_hash.o \
+                                  dtrace_fmt.o dtrace_hash.o dtrace_isa.o \
                                   dtrace_match.o dtrace_priv.o \
                                   dtrace_probe.o dtrace_probe_ctx.o \
                                   dtrace_ptofapi.o dtrace_predicate.o \
                                   dtrace_spec.o dtrace_state.o dtrace_util.o
 fasttrap-y                     := fasttrap_mod.o fasttrap_dev.o
 profile-y                      := profile_mod.o profile_dev.o
-sdt-y                          := sdt_mod.o sdt_dev.o
+sdt-y                          := sdt_mod.o sdt_dev.o sdt_$(ARCH).o
 systrace-y                     := systrace_mod.o systrace_dev.o
 dt_test-y                      := dt_test_mod.o dt_test_dev.o
 dt_perf-y                      := dt_perf_mod.o dt_perf_dev.o
index 30a4131caa8422ccacbde9fa8a4febc79b271cc3..33cec8e396b7647df0b62d2cbabc9cc23f532aa6 100644 (file)
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2011-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -43,7 +43,7 @@ void dt_test_provide(void *arg, const dtrace_probedesc_t *desc)
                return;
 
        pid = dtrace_probe_create(dt_test_id,
-                                 "dt_test", NULL, "test", 0, NULL);
+                                 "dt_test", NULL, "test", 1, NULL);
 }
 
 int _dt_test_enable(void *arg, dtrace_id_t id, void *parg)
@@ -62,22 +62,33 @@ void dt_test_destroy(void *arg, dtrace_id_t id, void *parg)
 {
 }
 
-static long dt_test_ioctl(struct file *file,
-                        unsigned int cmd, unsigned long arg)
+/*
+ * Direct calling into dtrace_probe() when passing more than 5 parameters to
+ * the probe requires a stub function.  Otherwise we may not be able to get
+ * to the value of all arguments correctly.
+ */
+void dt_test_probe(uintptr_t arg0, uintptr_t arg1, uintptr_t arg2,
+                  uintptr_t arg3, uintptr_t arg4, uintptr_t arg5,
+                  uintptr_t arg6, uintptr_t arg7, uintptr_t arg8,
+                  uintptr_t arg9)
 {
        /*
         * Yes, this is not nice.
-        * Not at all.
+        * Not at all...
         * But we're doing it anyway...
         */
-       void (*dt_test_probe)(dtrace_id_t, uintptr_t, uintptr_t, uintptr_t,
-                             uintptr_t, uintptr_t, uintptr_t, uintptr_t,
-                             uintptr_t, uintptr_t, uintptr_t);
+       void (*probe_fn)() = (void *)&dtrace_probe;
 
+       probe_fn(pid, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
+                arg9);
+}
+
+static long dt_test_ioctl(struct file *file,
+                        unsigned int cmd, unsigned long arg)
+{
        if (enabled) {
-               dt_test_probe = (void *)&dtrace_probe;
-               dt_test_probe(pid, cmd, arg, 2ULL, 3ULL, 4ULL, 5ULL,
-                                            6ULL, 7ULL, 8ULL, 9ULL);
+               dt_test_probe(cmd, arg, 2ULL, 3ULL, 4ULL, 5ULL, 6ULL, 7ULL,
+                                       8ULL, 9ULL);
 
                return 0;
        }
index be58b37a55a4987f3776a0153a47a190d23395a2..75a96eddf26a2a2a39389360df68f6fa0cf4a467 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include "dtrace.h"
 
similarity index 98%
rename from dtrace/dtrace_asm.S
rename to dtrace/dtrace_asm_x86_64.S
index 3aeb2c53ebb320d4cc3f1d10ef469a1f06591d16..e84190d364f13a32685df7096341809e72917278 100644 (file)
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
index 081d329fbf845005becfc6d3b88f6e2b8e76ba47..039d0a1e8b2c4f1ae45f1bee3c7367fe578af6c8 100644 (file)
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012, 2013 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -33,6 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 
 #include "ctf_api.h"
@@ -85,9 +86,6 @@ static dtrace_pattr_t         dtrace_provider_attr = {
 
 DEFINE_MUTEX(dtrace_lock);
 
-void (*dtrace_modload)(struct module *);
-void (*dtrace_modunload)(struct module *);
-
 void dtrace_nullop(void)
 {
 }
@@ -1387,12 +1385,10 @@ int dtrace_dev_init(void)
 
        register_module_notifier(&dtrace_modmgmt);
 
-#ifdef FIXME
-       dtrace_modload = dtrace_module_loaded;
-       dtrace_modunload = dtrace_module_unloaded;
-#endif
+#if defined(CONFIG_DT_FASTTRAP) || defined(CONFIG_DT_FASTTRAP_MODULE)
        dtrace_helpers_cleanup = dtrace_helpers_destroy;
        dtrace_helpers_fork = dtrace_helpers_duplicate;
+#endif
 #ifdef FIXME
        dtrace_cpu_init = dtrace_cpu_setup_initial;
        dtrace_cpustart_init = dtrace_suspend;
@@ -1464,7 +1460,7 @@ int dtrace_dev_init(void)
                                NULL, "END", 0, NULL);
        dtrace_probeid_error = dtrace_probe_create(
                                (dtrace_provider_id_t)dtrace_provider, NULL,
-                               NULL, "ERROR", 0, NULL);
+                               NULL, "ERROR", 1, NULL);
 
        dtrace_anon_property();
 
@@ -1515,12 +1511,10 @@ void dtrace_dev_exit(void)
 
        unregister_module_notifier(&dtrace_modmgmt);
 
-#ifdef FIXME
-       dtrace_modload = NULL;
-       dtrace_modunload = NULL;
-#endif
+#if defined(CONFIG_DT_FASTTRAP) || defined(CONFIG_DT_FASTTRAP_MODULE)
        dtrace_helpers_cleanup = NULL;
        dtrace_helpers_fork = NULL;
+#endif
 #ifdef FIXME
        dtrace_cpu_init = NULL;
        dtrace_cpustart_init = NULL;
index 928e9ed94014884285b23ec6b248a43471d91e63..b759f5c14d6ed7965e19487bea8e344be0e2f40a 100644 (file)
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012, 2013 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -32,7 +32,9 @@
 #include <linux/kdev_t.h>
 #include <linux/slab.h>
 #include <linux/socket.h>
+#include <linux/vmalloc.h>
 #include <net/ipv6.h>
+#include <asm/byteorder.h>
 
 #include <linux/mount.h>
 
@@ -1506,7 +1508,8 @@ static dtrace_dynvar_t *dtrace_dynvar(dtrace_dstate_t *dstate, uint_t nkeys,
        dtrace_dstate_percpu_t  *dcpu = &dstate->dtds_percpu[me];
        size_t                  bucket, ksize;
        size_t                  chunksize = dstate->dtds_chunksize;
-       uintptr_t               kdata, lock, nstate;
+       uintptr_t               kdata, lock;
+       dtrace_dstate_state_t   nstate;
        uint_t                  i;
 
         ASSERT(nkeys != 0);
@@ -1816,8 +1819,8 @@ retry:
                                 */
                                switch (dstate->dtds_state) {
                                case DTRACE_DSTATE_CLEAN: {
-                                       uintptr_t       *sp =
-                                                       (uintptr_t *)
+                                       dtrace_dstate_state_t   *sp =
+                                               (dtrace_dstate_state_t *)
                                                        &dstate->dtds_state;
 
                                        if (++cpu >= NR_CPUS)
@@ -2030,7 +2033,7 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                if (ndx >=
                    sizeof(mstate->dtms_arg) / sizeof(mstate->dtms_arg[0])) {
                        int                     aframes =
-                                       mstate->dtms_probe->dtpr_aframes + 3;
+                                       mstate->dtms_probe->dtpr_aframes + 2;
                        dtrace_provider_t       *pv;
                        uint64_t                val;
 
@@ -2115,9 +2118,10 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                if (!dtrace_priv_kernel(state))
                        return 0;
                if (!(mstate->dtms_present & DTRACE_MSTATE_STACKDEPTH)) {
-                       int     aframes = mstate->dtms_probe->dtpr_aframes + 3;
+                       int     aframes = mstate->dtms_probe->dtpr_aframes + 2;
 
-                       mstate->dtms_stackdepth = dtrace_getstackdepth(aframes);
+                       mstate->dtms_stackdepth = dtrace_getstackdepth(
+                                                       mstate, aframes);
                        mstate->dtms_present |= DTRACE_MSTATE_STACKDEPTH;
                }
 
@@ -2148,7 +2152,7 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                        return 0;
 
                if (!(mstate->dtms_present & DTRACE_MSTATE_CALLER)) {
-                       int     aframes = mstate->dtms_probe->dtpr_aframes + 3;
+                       int     aframes = mstate->dtms_probe->dtpr_aframes + 2;
 
                        if (!DTRACE_ANCHORED(mstate->dtms_probe)) {
                                /*
@@ -2902,7 +2906,7 @@ static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
                uintptr_t       tokaddr = tupregs[1].dttk_value;
                uint64_t        size = state->dts_options[DTRACEOPT_STRSIZE];
                uintptr_t       limit, toklimit = tokaddr + size;
-               uint8_t         c, tokmap[32];  /* 256 / 8 */
+               uint8_t         c = 0, tokmap[32];      /* 256 / 8 */
                char            *dest = (char *)mstate->dtms_scratch_ptr;
                int             i;
 
@@ -3352,7 +3356,7 @@ static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
 
        case DIF_SUBR_HTONS:
        case DIF_SUBR_NTOHS:
-#ifndef __LITTLE_ENDIAN
+#ifdef __BIG_ENDIAN
                regs[rd] = (uint16_t)tupregs[0].dttk_value;
 #else
                regs[rd] = DT_BSWAP_16((uint16_t)tupregs[0].dttk_value);
@@ -3362,7 +3366,7 @@ static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
 
        case DIF_SUBR_HTONL:
        case DIF_SUBR_NTOHL:
-#ifndef __LITTLE_ENDIAN
+#ifdef __BIG_ENDIAN
                regs[rd] = (uint32_t)tupregs[0].dttk_value;
 #else
                regs[rd] = DT_BSWAP_32((uint32_t)tupregs[0].dttk_value);
@@ -3372,7 +3376,7 @@ static void dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
 
        case DIF_SUBR_HTONLL:
        case DIF_SUBR_NTOHLL:
-#ifndef __LITTLE_ENDIAN
+#ifdef __BIG_ENDIAN
                regs[rd] = (uint64_t)tupregs[0].dttk_value;
 #else
                regs[rd] = DT_BSWAP_64((uint64_t)tupregs[0].dttk_value);
index ea9cfd1cebb0d620f6e61f88a3bb2a18368fede6..8b9094103f0337fcba44c0f57f902701c14ea453 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012, 2013 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/vmalloc.h>
 #include <asm/uaccess.h>
 
 #include "dtrace.h"
index 388108c592e38107616d36dc2c3e62ebf5710181..c7ad8c976a100b8d11d08ed37856274904b4aa4e 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include "dtrace.h"
 
index 117c3793b33f1c2030924ae7ec0649e38bb5664b..7fe1ad10be414cccdf378837d1ca303426de2272 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/kernel.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include "dtrace.h"
 
index 408a5ab59f3ec6263c1a2d37020f990ab97fd0b1..939333b5846baf357df01bbf444f73dcd3fdf871 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include "dtrace.h"
 
index 8c07769c4dcb9c649ba2cbb86b2f943e5c3a6fa2..0ae9dac957d79cfbf09a68aa731a771b068faf3d 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include "dtrace.h"
 
index 18ead9c6ec08bbe07504a60ad728e844e81abc63..1e9b2c8d096de2d6e0721939c21c8d4a4ccf7bf5 100644 (file)
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/uaccess.h>
+#include <asm/cacheflush.h>
 #include <asm/stacktrace.h>
 
 #include "dtrace.h"
 
-/* FIXME */
-uintptr_t _userlimit = 0x00007fffffffffffLL;
-uintptr_t kernelbase = 0xffff880000000000LL;
-
 EXPORT_SYMBOL(dtrace_getfp);
 
 DEFINE_MUTEX(cpu_lock);
 EXPORT_SYMBOL(cpu_lock);
 
-extern void    dtrace_copy(uintptr_t, uintptr_t, size_t);
-extern void    dtrace_copystr(uintptr_t, uintptr_t, size_t,
-                              volatile uint16_t *);
-
-static int dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
-{
-#ifdef FIXME
-       ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
-#else
-       if (kaddr < kernelbase || kaddr + size < kaddr) {
-               DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-               this_cpu_core->cpuc_dtrace_illval = kaddr;
-               return 0;
-       }
-#endif
-
-       if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
-               DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
-               this_cpu_core->cpuc_dtrace_illval = uaddr;
-               return 0;
-       }
-
-       return 1;
-}
-
-void dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-                  volatile uint16_t *flags)
-{
-       if (dtrace_copycheck(uaddr, kaddr, size))
-               dtrace_copy(uaddr, kaddr, size);
-}
-
-void dtrace_copyout(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-                   volatile uint16_t *flags)
-{
-       if (dtrace_copycheck(uaddr, kaddr, size))
-               dtrace_copy(kaddr, uaddr, size);
-}
-
-void dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-                     volatile uint16_t *flags)
-{
-       if (dtrace_copycheck(uaddr, kaddr, size))
-               dtrace_copystr(uaddr, kaddr, size, flags);
-}
-
-void dtrace_copyoutstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
-                      volatile uint16_t *flags)
-{
-       if (dtrace_copycheck(uaddr, kaddr, size))
-               dtrace_copystr(kaddr, uaddr, size, flags);
-}
-
-#define DTRACE_FUWORD(bits) \
-       uint##bits##_t dtrace_fuword##bits(void *uaddr)                       \
-       {                                                                     \
-               extern uint##bits##_t   dtrace_fuword##bits##_nocheck(void *);\
-                                                                             \
-               if ((uintptr_t)uaddr > _userlimit) {                          \
-                       DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);               \
-                       this_cpu_core->cpuc_dtrace_illval = (uintptr_t)uaddr; \
-                       return 0;                                             \
-               }                                                             \
-                                                                             \
-               return dtrace_fuword##bits##_nocheck(uaddr);                  \
-       }
-
-DTRACE_FUWORD(8)
-DTRACE_FUWORD(16)
-DTRACE_FUWORD(32)
-DTRACE_FUWORD(64)
-
-uint64_t dtrace_getarg(int argno, int aframes)
-{
-       unsigned long   bp;
-       uint64_t        *st;
-       uint64_t        val;
-       int             i;
-
-       asm volatile("movq %%rbp,%0" : "=m"(bp));
-
-       for (i = 0; i < aframes; i++)
-               bp = *((unsigned long *)bp);
-
-       ASSERT(argno >= 5);
-
-       /*
-        * The first 5 arguments (arg0 through arg4) are passed in registers
-        * to dtrace_probe().  The remaining arguments (arg5 through arg9) are
-        * passed on the stack.
-        *
-        * Stack layout:
-        * bp[0] = pushed bp from caller
-        * bp[1] = return address
-        * bp[2] = 6th argument (arg5 -> argno = 5)
-        * bp[3] = 7th argument (arg6 -> argno = 6)
-        * ...
-        */
-       DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-       st = (uint64_t *)bp;
-       val = st[2 + (argno - 5)];
-       DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-
-       return val;
-}
-
 int dtrace_getipl(void)
 {
        return in_interrupt();
 }
 
-ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
-{
-       struct pt_regs  *rp = task_pt_regs(task);
-
-       int     regmap[] = {
-                               REG_RBX,        /*  0 -> EBX */
-                               REG_RCX,        /*  1 -> ECX */
-                               REG_RDX,        /*  2 -> EDX */
-                               REG_RSI,        /*  3 -> ESI */
-                               REG_RDI,        /*  4 -> EDI */
-                               REG_RBP,        /*  5 -> EBP */
-                               REG_RAX,        /*  6 -> EAX */
-                               REG_DS,         /*  7 -> DS */
-                               REG_ES,         /*  8 -> ES */
-                               REG_FS,         /*  9 -> FS */
-                               REG_GS,         /* 10 -> GS */
-                               REG_TRAPNO,     /* 11 -> TRAPNO */
-                               REG_RIP,        /* 12 -> EIP */
-                               REG_CS,         /* 13 -> CS */
-                               REG_RFL,        /* 14 -> EFL */
-                               REG_RSP,        /* 15 -> UESP */
-                               REG_SS,         /* 16 -> SS */
-                          };
-       if (reg > REG_TRAPNO) {
-               /*
-                * Convert register alias index into register mapping index.
-                */
-               reg -= REG_TRAPNO + 1;
-
-               if (reg >= sizeof(regmap) / sizeof(int)) {
-                       DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-                       return 0;
-               }
-
-               reg = regmap[reg];
-       }
-
-       /*
-        * Most common case: direct index into pt_regs structure.
-        */
-       if (reg <= REG_SS)
-               return (&rp->r15)[reg];
-
-       switch (reg) {
-       case REG_DS:
-               return task->thread.ds;
-       case REG_ES:
-               return task->thread.es;
-       case REG_FS:
-               return task->thread.fs;
-       case REG_GS:
-               return task->thread.gs;
-       case REG_TRAPNO:
-               return task->thread.trap_nr;
-       default:
-               DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-               return 0;
-       }
-}
-
 static void dtrace_sync_func(void)
 {
 }
 
-void dtrace_sync(void)
-{
-       dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL);
-}
-
 void dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
 {
        if (cpu == DTRACE_CPUALL) {
@@ -231,6 +57,11 @@ void dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
                smp_call_function_single(cpu, func, arg, 1);
 }
 
+void dtrace_sync(void)
+{
+       dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL);
+}
+
 void dtrace_toxic_ranges(void (*func)(uintptr_t, uintptr_t))
 {
        /* FIXME */
@@ -248,7 +79,7 @@ void dtrace_getpcstack(uint64_t *pcstack, int pcstack_limit, int aframes,
                                        pcstack,
                                        NULL,
                                        pcstack_limit,
-                                       0,
+                                       aframes,
                                        STACKTRACE_KERNEL
                                     };
 
@@ -330,7 +161,11 @@ unsigned long dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack,
                goto out;
        atomic_inc(&mm->mm_users);
 
+#ifdef CONFIG_X86_64
        tos = current_user_stack_pointer();
+#else
+       tos = user_stack_pointer(current_pt_regs());
+#endif
        stack_vma = find_user_vma(p, mm, NULL, (unsigned long) tos, 0);
        if (!stack_vma ||
            stack_vma->vm_start > (unsigned long) tos)
@@ -417,22 +252,32 @@ void dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
        dtrace_getufpstack(pcstack, NULL, pcstack_limit);
 }
 
-int dtrace_getstackdepth(int aframes)
+int dtrace_getstackdepth(dtrace_mstate_t *mstate, int aframes)
 {
+       uintptr_t               old = mstate->dtms_scratch_ptr;
+       size_t                  size;
        struct stacktrace_state st = {
                                        NULL,
                                        NULL,
                                        0,
-                                       0,
+                                       aframes,
                                        STACKTRACE_KERNEL
                                     };
 
+       st.pcs = (uint64_t *)P2ROUNDUP(mstate->dtms_scratch_ptr, 8);
+       size = (uintptr_t)st.pcs - mstate->dtms_scratch_ptr +
+                         aframes * sizeof(uint64_t);
+       if (mstate->dtms_scratch_ptr + size >
+           mstate->dtms_scratch_base + mstate->dtms_scratch_size) {
+               DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
+               return 0;
+       }
+
        dtrace_stacktrace(&st);
 
-       if (st.depth <= aframes)
-               return 0;
+       mstate->dtms_scratch_ptr = old;
 
-       return st.depth - aframes;
+       return st.depth;
 }
 
 int dtrace_getustackdepth(void)
diff --git a/dtrace/dtrace_isa_x86_64.c b/dtrace/dtrace_isa_x86_64.c
new file mode 100644 (file)
index 0000000..1920171
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * FILE:       dtrace_isa_x86_64.c
+ * DESCRIPTION:        Dynamic Tracing: x86_64 architecture specific support functions
+ *
+ * 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_cpu.h>
+
+#include "dtrace.h"
+
+/* Register indices */
+#define REG_TRAPNO     25
+#define REG_GS         24
+#define REG_FS         23
+#define REG_ES         22
+#define REG_DS         21
+#define REG_SS         20
+#define REG_RSP                19
+#define REG_RFL                18
+#define REG_CS         17
+#define REG_RIP                16
+#define REG_ERR                15
+#define REG_RDI                14
+#define REG_RSI                13
+#define REG_RDX                12
+#define REG_RCX                11
+#define REG_RAX                10
+#define REG_R8         9
+#define REG_R9         8
+#define REG_R10                7
+#define REG_R11                6
+#define REG_RBX                5
+#define REG_RBP                4
+#define REG_R12                3
+#define REG_R13                2
+#define REG_R14                1
+#define REG_R15                0
+
+extern void    dtrace_copy(uintptr_t, uintptr_t, size_t);
+extern void    dtrace_copystr(uintptr_t, uintptr_t, size_t,
+                              volatile uint16_t *);
+
+uintptr_t _userlimit = 0x00007fffffffffffLL;
+uintptr_t kernelbase = 0xffff880000000000LL;
+
+static int dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
+{
+#ifdef FIXME
+       ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
+#else
+       if (kaddr < kernelbase || kaddr + size < kaddr) {
+               DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+               this_cpu_core->cpuc_dtrace_illval = kaddr;
+               return 0;
+       }
+#endif
+
+       if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
+               DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+               this_cpu_core->cpuc_dtrace_illval = uaddr;
+               return 0;
+       }
+
+       return 1;
+}
+
+void dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+                  volatile uint16_t *flags)
+{
+       if (dtrace_copycheck(uaddr, kaddr, size))
+               dtrace_copy(uaddr, kaddr, size);
+}
+
+void dtrace_copyout(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+                   volatile uint16_t *flags)
+{
+       if (dtrace_copycheck(uaddr, kaddr, size))
+               dtrace_copy(kaddr, uaddr, size);
+}
+
+void dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+                     volatile uint16_t *flags)
+{
+       if (dtrace_copycheck(uaddr, kaddr, size))
+               dtrace_copystr(uaddr, kaddr, size, flags);
+}
+
+void dtrace_copyoutstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+                      volatile uint16_t *flags)
+{
+       if (dtrace_copycheck(uaddr, kaddr, size))
+               dtrace_copystr(kaddr, uaddr, size, flags);
+}
+
+#define DTRACE_FUWORD(bits) \
+       uint##bits##_t dtrace_fuword##bits(void *uaddr)                       \
+       {                                                                     \
+               extern uint##bits##_t   dtrace_fuword##bits##_nocheck(void *);\
+                                                                             \
+               if ((uintptr_t)uaddr > _userlimit) {                          \
+                       DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);               \
+                       this_cpu_core->cpuc_dtrace_illval = (uintptr_t)uaddr; \
+                       return 0;                                             \
+               }                                                             \
+                                                                             \
+               return dtrace_fuword##bits##_nocheck(uaddr);                  \
+       }
+
+DTRACE_FUWORD(8)
+DTRACE_FUWORD(16)
+DTRACE_FUWORD(32)
+DTRACE_FUWORD(64)
+
+uint64_t dtrace_getarg(int argno, int aframes)
+{
+       unsigned long   bp;
+       uint64_t        *st;
+       uint64_t        val;
+       int             i;
+
+       asm volatile("movq %%rbp,%0" : "=m"(bp));
+
+       for (i = 0; i < aframes; i++)
+               bp = *((unsigned long *)bp);
+
+       ASSERT(argno >= 5);
+
+       /*
+        * The first 5 arguments (arg0 through arg4) are passed in registers
+        * to dtrace_probe().  The remaining arguments (arg5 through arg9) are
+        * passed on the stack.
+        *
+        * Stack layout:
+        * bp[0] = pushed bp from caller
+        * bp[1] = return address
+        * bp[2] = 6th argument (arg5 -> argno = 5)
+        * bp[3] = 7th argument (arg6 -> argno = 6)
+        * ...
+        */
+       DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+       st = (uint64_t *)bp;
+       val = st[2 + (argno - 5)];
+       DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+
+       return val;
+}
+
+ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
+{
+       struct pt_regs  *rp = task_pt_regs(task);
+
+       int     regmap[] = {
+                               REG_RBX,        /*  0 -> EBX */
+                               REG_RCX,        /*  1 -> ECX */
+                               REG_RDX,        /*  2 -> EDX */
+                               REG_RSI,        /*  3 -> ESI */
+                               REG_RDI,        /*  4 -> EDI */
+                               REG_RBP,        /*  5 -> EBP */
+                               REG_RAX,        /*  6 -> EAX */
+                               REG_DS,         /*  7 -> DS */
+                               REG_ES,         /*  8 -> ES */
+                               REG_FS,         /*  9 -> FS */
+                               REG_GS,         /* 10 -> GS */
+                               REG_TRAPNO,     /* 11 -> TRAPNO */
+                               REG_RIP,        /* 12 -> EIP */
+                               REG_CS,         /* 13 -> CS */
+                               REG_RFL,        /* 14 -> EFL */
+                               REG_RSP,        /* 15 -> UESP */
+                               REG_SS,         /* 16 -> SS */
+                          };
+
+       if (reg > REG_TRAPNO) {
+               /*
+                * Convert register alias index into register mapping index.
+                */
+               reg -= REG_TRAPNO + 1;
+
+               if (reg >= sizeof(regmap) / sizeof(int)) {
+                       DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
+                       return 0;
+               }
+
+               reg = regmap[reg];
+       }
+
+       /*
+        * Most common case: direct index into pt_regs structure.
+        */
+       if (reg <= REG_SS)
+               return (&rp->r15)[reg];
+
+       switch (reg) {
+       case REG_DS:
+               return task->thread.ds;
+       case REG_ES:
+               return task->thread.es;
+       case REG_FS:
+               return task->thread.fs;
+       case REG_GS:
+               return task->thread.gs;
+       case REG_TRAPNO:
+               return task->thread.trap_nr;
+       default:
+               DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
+               return 0;
+       }
+}
index 5076765a1f2c15e4d015a4b5715fe765c47d66e0..e042e82fe4a8d2e153cb40bc45b4fbc916c5616c 100644 (file)
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012, 2013 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/idr.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/pgtable.h>
 #include <asm/cmpxchg.h>
 
 #include "dtrace.h"
-#include "sdt_impl.h"
 
 ktime_t                                dtrace_chill_interval =
                                        KTIME_INIT(1, 0);
@@ -384,14 +385,8 @@ static void dtrace_action_raise(uint64_t sig)
         * raise() has a queue depth of 1 -- we ignore all subsequent
         * invocations of the raise() action.
         */
-#if 0
-
-       sigaddset(&current->pending.signal, sig);
-       set_thread_flag(TIF_SIGPENDING);
-#else
        if (current->dtrace_sig == 0)
                current->dtrace_sig = (uint8_t)sig;
-#endif
 }
 
 static void dtrace_action_stop(void)
@@ -1260,7 +1255,7 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
                        dtrace_probe_error(
                                state, ecb->dte_epid, ndx,
                                (mstate.dtms_present & DTRACE_MSTATE_FLTOFFS)
-                                       ?  mstate.dtms_fltoffs
+                                       ? mstate.dtms_fltoffs
                                        : -1,
                                DTRACE_FLAGS2FLT(*flags),
                                this_cpu_core->cpuc_dtrace_illval);
index bfbf3b46d88068c556646524a2bccb7fe02193a9..8063f01608f5c1185e9146baa9b56000ad32ae56 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/dtrace_cpu.h>
 #include <linux/vmalloc.h>
+#include <asm/pgtable.h>
 
 #include "dtrace.h"
 
index c1198cb3b4aacec6c93cadd67668796dcf5b29b4..01482893b14e73c8b6e43ce2e577d43a3e5195e9 100644 (file)
@@ -28,7 +28,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2009 -- 2013 Oracle, Inc.  All rights reserved.
+ * Copyright 2009-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -854,8 +854,8 @@ extern void dtrace_cred2priv(const cred_t *, uint32_t *, uid_t *);
 
 extern void ctf_forceload(void);
 
-#define dtrace_membar_producer()       wmb()
-#define dtrace_membar_consumer()       rmb()
+#define dtrace_membar_producer()       smp_wmb()
+#define dtrace_membar_consumer()       smp_rmb()
 
 typedef unsigned long  dtrace_icookie_t;
 
@@ -875,6 +875,7 @@ typedef void                (*dtrace_xcall_t)(void *);
 
 extern void dtrace_xcall(processorid_t, dtrace_xcall_t, void *);
 
+extern uintptr_t dtrace_fulword(void *);
 extern uint8_t dtrace_fuword8(void *);
 extern uint16_t dtrace_fuword16(void *);
 extern uint32_t dtrace_fuword32(void *);
@@ -888,7 +889,7 @@ extern void dtrace_getupcstack(uint64_t *, int);
 extern unsigned long dtrace_getufpstack(uint64_t *, uint64_t *, int);
 extern uintptr_t dtrace_getfp(void);
 extern uint64_t dtrace_getarg(int, int);
-extern int dtrace_getstackdepth(int);
+extern int dtrace_getstackdepth(dtrace_mstate_t *, int);
 extern int dtrace_getustackdepth(void);
 extern ulong_t dtrace_getreg(struct task_struct *, uint_t);
 extern void dtrace_copyin(uintptr_t, uintptr_t, size_t, volatile uint16_t *);
index 39327155f21dc3facb3e84850f3fbfe5854ef25e..c18586ac84fe0d8995715a63a7f472265bac117d 100644 (file)
@@ -28,7 +28,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2009 -- 2013 Oracle, Inc.  All rights reserved.
+ * Copyright 2009-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -36,7 +36,7 @@
 #include <linux/preempt.h>
 #include <asm/ptrace.h>
 
-typedef typeof(((struct pt_regs *)0)->ip)      pc_t;
+typedef typeof(instruction_pointer((struct pt_regs *)0))       pc_t;
 
 typedef enum dtrace_activity {
        DTRACE_ACTIVITY_INACTIVE = 0,
@@ -155,36 +155,6 @@ typedef enum dtrace_speculation_state {
 
 #define KERNELBASE     (uintptr_t)_text
 
-/*
- * regset.h information
- */
-#define REG_TRAPNO     25
-#define REG_GS         24
-#define REG_FS         23
-#define REG_ES         22
-#define REG_DS         21
-#define REG_SS         20
-#define REG_RSP                19
-#define REG_RFL                18
-#define REG_CS         17
-#define REG_RIP                16
-#define REG_ERR                15
-#define REG_RDI                14
-#define REG_RSI                13
-#define REG_RDX                12
-#define REG_RCX                11
-#define REG_RAX                10
-#define REG_R8         9
-#define REG_R9         8
-#define REG_R10                7
-#define REG_R11                6
-#define REG_RBX                5
-#define REG_RBP                4
-#define REG_R12                3
-#define REG_R13                2
-#define REG_R14                1
-#define REG_R15                0
-
 #if defined(__i386__) || defined(__x86_64__)
 # define DTRACE_INVOP_PUSHL_EBP        1
 # define DTRACE_INVOP_POPL_EBP 2
diff --git a/dtrace/include/x86_64/dtrace/sdt_arch.h b/dtrace/include/x86_64/dtrace/sdt_arch.h
new file mode 100644 (file)
index 0000000..0179400
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _X86_64_SDT_ARCH_H
+#define _X86_64_SDT_ARCH_H
+
+/*
+ * Statically Defined Tracing Implementation defines
+ *
+ * Note: The contents of this file are private to the implementation of the
+ * DTrace subsystem and are subject to change at any time without notice.
+ */
+
+/*
+ * 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 2009-2014 Oracle, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+#define SDT_AFRAMES    4
+
+#endif /* _X86_64_SDT_ARCH_H */
index 8805d91122020fde6349dd63550dbc94f664a4a5..73aba6fd9d04f83fd413ca4e7cfe25c42b802c62 100644 (file)
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -107,9 +107,9 @@ static void profile_tick_fn(uintptr_t arg)
                dtrace_getpcstack(stack, 8, 0, NULL);
                pc = stack[7];
        } else if (user_mode(regs))
-               upc = GET_IP(regs);
+               upc = instruction_pointer(regs);
        else
-               pc = GET_IP(regs);
+               pc = instruction_pointer(regs);
 
        dtrace_probe(prof->prof_id, pc, upc, 0, 0, 0);
 }
@@ -140,9 +140,9 @@ static void profile_prof_fn(uintptr_t arg)
                dtrace_getpcstack(stack, 8, 0, NULL);
                pc = stack[7];
        } else if (user_mode(regs))
-               upc = GET_IP(regs);
+               upc = instruction_pointer(regs);
        else
-               pc = GET_IP(regs);
+               pc = instruction_pointer(regs);
 
        dtrace_probe(prof->prof_id, pc, upc, ktime_to_ns(late), 0, 0);
 }
index e4b668ddbf8316c6a029a71ac364c59367a84037..c0bc989f59853a6668a406e7082d9c13fa977909 100644 (file)
@@ -21,7 +21,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
 #include <linux/sdt.h>
 #include <linux/slab.h>
 #include <linux/uaccess.h>
+#include <linux/vmalloc.h>
 
 #include "dtrace.h"
 #include "dtrace_dev.h"
 #include "sdt_impl.h"
 
-#define SDT_PATCHVAL           0xf0
-#define SDT_ADDR2NDX(addr)     ((((uintptr_t)(addr)) >> 4) & sdt_probetab_mask)
 #define SDT_PROBETAB_SIZE      0x1000          /* 4k entries -- 16K total */
 
-static sdt_probe_t     **sdt_probetab;
-static int             sdt_probetab_size;
-static int             sdt_probetab_mask;
+sdt_probe_t            **sdt_probetab;
+int                    sdt_probetab_size;
+int                    sdt_probetab_mask;
 
 static sdt_argdesc_t   sdt_args[] = {
        /*
@@ -103,26 +102,6 @@ static sdt_argdesc_t       sdt_args[] = {
        { NULL, }
 };
 
-static uint8_t sdt_invop(struct pt_regs *regs)
-{
-       sdt_probe_t     *sdt = sdt_probetab[SDT_ADDR2NDX(regs->ip)];
-
-       for (; sdt != NULL; sdt = sdt->sdp_hashnext) {
-               if ((uintptr_t)sdt->sdp_patchpoint == regs->ip) {
-                       this_cpu_core->cpu_dtrace_regs = regs;
-
-                       dtrace_probe(sdt->sdp_id, regs->di, regs->si,
-                                    regs->dx, regs->cx, regs->r8);
-
-                       this_cpu_core->cpu_dtrace_regs = NULL;
-
-                       return DTRACE_INVOP_NOP;
-               }
-       }
-
-       return 0;
-}
-
 void sdt_provide_module(void *arg, struct module *mp)
 {
        char                    *modname = mp->name;
@@ -152,6 +131,9 @@ void sdt_provide_module(void *arg, struct module *mp)
                        return;
        }
 
+       if (!sdt_provide_module_arch(arg, mp))
+               return;
+
        for (idx = 0, sdpd = mp->sdt_probes; idx < mp->num_dtrace_probes;
             idx++, sdpd++) {
                char                    *name = sdpd->sdpd_name, *nname;
@@ -212,7 +194,8 @@ void sdt_provide_module(void *arg, struct module *mp)
                        sdp->sdp_id = dtrace_probe_create(prov->dtmp_id,
                                                          modname,
                                                          sdpd->sdpd_func,
-                                                         nname, 3, sdp);
+                                                         nname, SDT_AFRAMES,
+                                                         sdp);
                        mp->sdt_nprobes++;
                }
 
@@ -220,9 +203,9 @@ void sdt_provide_module(void *arg, struct module *mp)
                                        SDT_ADDR2NDX(sdpd->sdpd_offset)];
                sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)] = sdp;
 
-               sdp->sdp_patchval = SDT_PATCHVAL;
-               sdp->sdp_patchpoint = (uint8_t *)sdpd->sdpd_offset;
-               sdp->sdp_savedval = *sdp->sdp_patchpoint;
+               sdp->sdp_patchpoint = (sdt_instr_t *)sdpd->sdpd_offset;
+
+               sdt_provide_probe_arch(sdp, mp, idx);
        }
 }
 
@@ -246,7 +229,7 @@ int _sdt_enable(void *arg, dtrace_id_t id, void *parg)
                module_put(sdp->sdp_module);
 
        while (sdp != NULL) {
-               dtrace_invop_enable(sdp->sdp_patchpoint);
+               sdt_enable_arch(sdp, id, arg);
                sdp = sdp->sdp_next;
        }
 
@@ -268,7 +251,7 @@ void _sdt_disable(void *arg, dtrace_id_t id, void *parg)
                module_put(sdp->sdp_module);
 
        while (sdp != NULL) {
-               dtrace_invop_disable(sdp->sdp_patchpoint, sdp->sdp_savedval);
+               sdt_disable_arch(sdp, id, arg);
                sdp = sdp->sdp_next;
        }
 }
@@ -309,42 +292,6 @@ void sdt_getargdesc(void *arg, dtrace_id_t id, void *parg,
        desc->dtargd_ndx = DTRACE_ARGNONE;
 }
 
-uint64_t sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
-                   int aframes)
-{
-       struct pt_regs  *regs = this_cpu_core->cpu_dtrace_regs;
-       uint64_t        *st;
-       uint64_t        val;
-
-       if (regs == NULL)
-               return 0;
-
-       switch (argno) {
-       case 0:
-               return regs->di;
-       case 1:
-               return regs->si;
-       case 2:
-               return regs->dx;
-       case 3:
-               return regs->cx;
-       case 4:
-               return regs->r8;
-       case 5:
-               return regs->r9;
-       }
-
-       ASSERT(argno > 5);
-
-       st = (uint64_t *)regs->sp;
-       DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-       __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 6],
-                                         sizeof(st[0]));
-       DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-
-       return val;
-}
-
 void sdt_destroy(void *arg, dtrace_id_t id, void *parg)
 {
        sdt_probe_t     *sdp = parg;
@@ -425,14 +372,15 @@ int sdt_dev_init(void)
        if (sdt_probetab == NULL)
                return -ENOMEM;
 
-       ret = dtrace_invop_add(sdt_invop);
+       sdt_dev_init_arch();
 
        return ret;
 }
 
 void sdt_dev_exit(void)
 {
-       dtrace_invop_remove(sdt_invop);
+       sdt_dev_exit_arch();
+
        vfree(sdt_probetab);
 
        misc_deregister(&sdt_dev);
index e26f795de507771eb26c1ed4f1b72f76f091f2b1..bcfe2533968f65238af91098d605e8778d4e7ca2 100644 (file)
@@ -2,6 +2,8 @@
 #define _SDT_IMPL_H_
 
 #include <linux/sdt.h>
+#include <asm/dtrace_sdt.h>
+#include <dtrace/sdt_arch.h>
 
 extern struct module           *dtrace_kmod;
 
@@ -29,7 +31,18 @@ typedef struct sdt_argdesc  {
        char                    *sda_xlate;
 } sdt_argdesc_t;
 
-extern dtrace_mprovider_t sdt_providers[];
+extern dtrace_mprovider_t      sdt_providers[];
+extern sdt_probe_t             **sdt_probetab;
+extern int                     sdt_probetab_size;
+extern int                     sdt_probetab_mask;
+
+#define SDT_ADDR2NDX(addr)     ((((uintptr_t)(addr)) >> 4) & \
+                                       sdt_probetab_mask)
+
+extern void sdt_provide_probe_arch(sdt_probe_t *, struct module *, int);
+extern int sdt_provide_module_arch(void *, struct module *);
+extern void sdt_enable_arch(sdt_probe_t *, dtrace_id_t, void *);
+extern void sdt_disable_arch(sdt_probe_t *, dtrace_id_t, void *);
 
 extern void sdt_provide_module(void *, struct module *);
 extern int _sdt_enable(void *, dtrace_id_t, void *);
@@ -41,4 +54,7 @@ extern void sdt_destroy(void *, dtrace_id_t, void *);
 extern int sdt_dev_init(void);
 extern void sdt_dev_exit(void);
 
+extern int sdt_dev_init_arch(void);
+extern void sdt_dev_exit_arch(void);
+
 #endif /* _SDT_IMPL_H_ */
index 643b1539929f16f7137cf95146c4e91da6a7f66e..f189edca980eaddf5923138de7ea9411d095ac27 100644 (file)
@@ -22,7 +22,7 @@
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011, 2012 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -119,7 +119,11 @@ static dtrace_pops_t sdt_pops = {
        NULL,
        NULL,
        sdt_getargdesc,
+#ifdef CONFIG_X86_64
        sdt_getarg,
+#else
+       NULL,
+#endif
        NULL,
        sdt_destroy,
 };
diff --git a/dtrace/sdt_x86_64.c b/dtrace/sdt_x86_64.c
new file mode 100644 (file)
index 0000000..1faac5b
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * FILE:       sdt_dev.c
+ * DESCRIPTION:        Statically Defined 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-2014 Oracle, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <linux/sdt.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+
+#include "dtrace.h"
+#include "dtrace_dev.h"
+#include "sdt_impl.h"
+
+#define SDT_PATCHVAL           0xf0
+
+static uint8_t sdt_invop(struct pt_regs *regs)
+{
+       sdt_probe_t     *sdt = sdt_probetab[SDT_ADDR2NDX(regs->ip)];
+
+       for (; sdt != NULL; sdt = sdt->sdp_hashnext) {
+               if ((uintptr_t)sdt->sdp_patchpoint == regs->ip) {
+                       this_cpu_core->cpu_dtrace_regs = regs;
+
+                       dtrace_probe(sdt->sdp_id, regs->di, regs->si,
+                                    regs->dx, regs->cx, regs->r8);
+
+                       this_cpu_core->cpu_dtrace_regs = NULL;
+
+                       return DTRACE_INVOP_NOP;
+               }
+       }
+
+       return 0;
+}
+
+void sdt_provide_probe_arch(sdt_probe_t *sdp, struct module *mp, int idx)
+{
+       sdp->sdp_patchval = SDT_PATCHVAL;
+       sdp->sdp_savedval = *sdp->sdp_patchpoint;
+}
+
+int sdt_provide_module_arch(void *arg, struct module *mp)
+{
+       return 1;
+}
+
+void sdt_enable_arch(sdt_probe_t *sdp, dtrace_id_t id, void *arg)
+{
+       dtrace_invop_enable((uint8_t *)sdp->sdp_patchpoint);
+}
+
+void sdt_disable_arch(sdt_probe_t *sdp, dtrace_id_t id, void *arg)
+{
+       dtrace_invop_disable((uint8_t *)sdp->sdp_patchpoint,
+                            sdp->sdp_savedval);
+}
+
+uint64_t sdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
+                   int aframes)
+{
+       struct pt_regs  *regs = this_cpu_core->cpu_dtrace_regs;
+       uint64_t        *st;
+       uint64_t        val;
+
+       if (regs == NULL)
+               return 0;
+
+       switch (argno) {
+       case 0:
+               return regs->di;
+       case 1:
+               return regs->si;
+       case 2:
+               return regs->dx;
+       case 3:
+               return regs->cx;
+       case 4:
+               return regs->r8;
+       case 5:
+               return regs->r9;
+       }
+
+       ASSERT(argno > 5);
+
+       st = (uint64_t *)regs->sp;
+       DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+       __copy_from_user_inatomic_nocache(&val, (void *)&st[argno - 6],
+                                         sizeof(st[0]));
+       DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+
+       return val;
+}
+
+int sdt_dev_init_arch(void)
+{
+       return dtrace_invop_add(sdt_invop);
+}
+
+void sdt_dev_exit_arch(void)
+{
+       dtrace_invop_remove(sdt_invop);
+}
index a4c6c3c2deecd0b2390b003833b6b6f30251c7f0..8727637a4b73d126d319d20739015e6351d6c917 100644 (file)
  *
  * CDDL HEADER END
  *
- * Copyright 2010, 2011 Oracle, Inc.  All rights reserved.
+ * Copyright 2010-2014 Oracle, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
+#include <linux/dtrace_syscall.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
 #include <asm/unistd.h>
@@ -33,7 +34,7 @@
 #include "dtrace_dev.h"
 #include "systrace.h"
 
-#define SYSTRACE_ARTIFICIAL_FRAMES     0
+#define SYSTRACE_ARTIFICIAL_FRAMES     1
 
 #define SYSTRACE_SHIFT                 16
 #define SYSTRACE_ENTRY(id)             ((1 << SYSTRACE_SHIFT) | (id))
@@ -93,64 +94,55 @@ static dt_sys_call_t get_intercept(int sysnum)
        switch (sysnum) {
        default:
                return systrace_info->syscall;
-       case __NR_clone:
-               return systrace_info->stubs[SCE_CLONE];
-       case __NR_fork:
-               return systrace_info->stubs[SCE_FORK];
-       case __NR_vfork:
-               return systrace_info->stubs[SCE_VFORK];
-       case __NR_iopl:
-               return systrace_info->stubs[SCE_IOPL];
-       case __NR_execve:
-               return systrace_info->stubs[SCE_EXECVE];
-       case __NR_rt_sigreturn:
-               return systrace_info->stubs[SCE_RT_SIGRETURN];
+#define DTRACE_SYSCALL_STUB(t, n) \
+       case __NR_##n: \
+               return systrace_info->stubs[SCE_##t];
+#include <asm/dtrace_syscall.h>
+#undef DTRACE_SYSCALL_STUB
        }
 }
 
 int _systrace_enable(void *arg, dtrace_id_t id, void *parg)
 {
-       int             sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-       int             enabled =
-               systrace_info->sysent[sysnum].stsy_entry != DTRACE_IDNONE ||
-               systrace_info->sysent[sysnum].stsy_return != DTRACE_IDNONE;
-       dt_sys_call_t   intercept = get_intercept(sysnum);
+       int                     sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
+       dtrace_syscalls_t       *sc = &systrace_info->sysent[sysnum];
+       int                     enabled = sc->stsy_entry != DTRACE_IDNONE ||
+                                         sc->stsy_return != DTRACE_IDNONE;
+       dt_sys_call_t           intercept = get_intercept(sysnum);
 
        if (!enabled) {
-               if (cmpxchg(systrace_info->sysent[sysnum].stsy_tblent,
-                           systrace_info->sysent[sysnum].stsy_underlying,
-                           intercept) !=
-                   systrace_info->sysent[sysnum].stsy_underlying)
-                       return 0;
+               if (cmpxchg((uint32_t *)sc->stsy_tblent,
+                           (uint32_t)sc->stsy_underlying,
+                           (uint32_t)intercept) !=
+                   (uint32_t)sc->stsy_underlying)
+                       return 1;
        } else
-               ASSERT((void *)*(systrace_info->sysent[sysnum].stsy_tblent) ==
-                      (void *)intercept);
+               ASSERT(*(uint32_t *)sc->stsy_tblent == (uint32_t)intercept);
 
        if (SYSTRACE_ISENTRY((uintptr_t)parg))
-               systrace_info->sysent[sysnum].stsy_entry = id;
+               sc->stsy_entry = id;
        else
-               systrace_info->sysent[sysnum].stsy_return = id;
+               sc->stsy_return = id;
 
        return 0;
 }
 
 void _systrace_disable(void *arg, dtrace_id_t id, void *parg)
 {
-       int             sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
-       int             enabled =
-               systrace_info->sysent[sysnum].stsy_entry != DTRACE_IDNONE ||
-               systrace_info->sysent[sysnum].stsy_return != DTRACE_IDNONE;
-       dt_sys_call_t   intercept = get_intercept(sysnum);
+       int                     sysnum = SYSTRACE_SYSNUM((uintptr_t)parg);
+       dtrace_syscalls_t       *sc = &systrace_info->sysent[sysnum];
+       int                     enabled = sc->stsy_entry != DTRACE_IDNONE ||
+                                         sc->stsy_return != DTRACE_IDNONE;
+       dt_sys_call_t           intercept = get_intercept(sysnum);
 
        if (enabled)
-               (void)cmpxchg(systrace_info->sysent[sysnum].stsy_tblent,
-                             intercept,
-                             systrace_info->sysent[sysnum].stsy_underlying);
+               (void)cmpxchg((uint32_t *)sc->stsy_tblent, (uint32_t)intercept,
+                             (uint32_t)sc->stsy_underlying);
 
        if (SYSTRACE_ISENTRY((uintptr_t)parg))
-               systrace_info->sysent[sysnum].stsy_entry = DTRACE_IDNONE;
+               sc->stsy_entry = DTRACE_IDNONE;
        else
-               systrace_info->sysent[sysnum].stsy_return = DTRACE_IDNONE;
+               sc->stsy_return = DTRACE_IDNONE;
 }
 
 void systrace_destroy(void *arg, dtrace_id_t id, void *parg)