]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/dtrace/profile_prvd.c
xnu-2782.1.97.tar.gz
[apple/xnu.git] / bsd / dev / dtrace / profile_prvd.c
index 14895f8d983e8fd09e8f0263148be40930cfaf0f..eb5ada1bb33c66847d822c8d94e6da09021085e2 100644 (file)
  * CDDL HEADER END
  */
 /*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-/* #pragma ident       "@(#)profile.c  1.6     06/03/24 SMI" */
+/* #pragma ident       "@(#)profile.c  1.7     07/01/10 SMI" */
 
-#if !defined(__APPLE__)
-#include <sys/errno.h>
-#include <sys/stat.h>
-#include <sys/modctl.h>
-#include <sys/conf.h>
-#include <sys/systm.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/cpuvar.h>
-#include <sys/kmem.h>
-#include <sys/strsubr.h>
-#include <sys/dtrace.h>
-#include <sys/cyclic.h>
-#include <sys/atomic.h>
-#else
 #ifdef KERNEL
 #ifndef _KERNEL
 #define _KERNEL /* Solaris vs. Darwin */
 #endif
 #endif
 
-#define MACH__POSIX_C_SOURCE_PRIVATE 1 /* pulls in suitable savearea from mach/ppc/thread_status.h */
 #include <kern/cpu_data.h>
 #include <kern/thread.h>
+#include <kern/assert.h>
 #include <mach/thread_status.h>
 
 #include <sys/param.h>
 
 #include <sys/dtrace_glue.h>
 
-#if defined(__ppc__) || defined(__ppc64__)
-extern struct savearea *find_kern_regs(thread_t);
-#elif defined(__i386__) || defined(__x86_64__)
-extern x86_saved_state32_t *find_kern_regs(thread_t);
+#include <machine/pal_routines.h>
+
+#if defined(__x86_64__)
+extern x86_saved_state_t *find_kern_regs(thread_t);
 #else
 #error Unknown architecture
 #endif
@@ -77,26 +62,23 @@ extern x86_saved_state32_t *find_kern_regs(thread_t);
 #define ASSERT(x) do {} while(0)
 
 extern void profile_init(void);
-#endif /* __APPLE__ */
 
 static dev_info_t *profile_devi;
 static dtrace_provider_id_t profile_id;
 
 /*
- * Regardless of platform, there are five artificial frames in the case of the
+ * Regardless of platform, the stack frames look like this in the case of the
  * profile provider:
  *
  *     profile_fire
  *     cyclic_expire
  *     cyclic_fire
  *     [ cbe ]
- *     [ locore ]
+ *     [ interrupt code ]
  *
- * On amd64, there are two frames associated with locore:  one in locore, and
- * another in common interrupt dispatch code.  (i386 has not been modified to
- * use this common layer.)  Further, on i386, the interrupted instruction
- * appears as its own stack frame.  All of this means that we need to add one
- * frame for amd64, and then take one away for both amd64 and i386.
+ * On x86, there are five frames from the generic interrupt code; further, the
+ * interrupted instruction appears as its own stack frame, giving us a total of
+ * 10.
  *
  * On SPARC, the picture is further complicated because the compiler
  * optimizes away tail-calls -- so the following frames are optimized away:
@@ -108,41 +90,18 @@ static dtrace_provider_id_t profile_id;
  * frame cannot be tail-call eliminated, yielding four frames in this case.
  *
  * All of the above constraints lead to the mess below.  Yes, the profile
- * provider should ideally figure this out on-the-fly by hiting one of its own
+ * provider should ideally figure this out on-the-fly by hitting one of its own
  * probes and then walking its own stack trace.  This is complicated, however,
  * and the static definition doesn't seem to be overly brittle.  Still, we
  * allow for a manual override in case we get it completely wrong.
  */
-#if !defined(__APPLE__)
-
-#ifdef __x86_64__
-#define        PROF_ARTIFICIAL_FRAMES  7
-#else
-#ifdef __i386__
-#define        PROF_ARTIFICIAL_FRAMES  6
-#else
-#ifdef __sparc
-#ifdef DEBUG
-#define        PROF_ARTIFICIAL_FRAMES  4
-#else
-#define        PROF_ARTIFICIAL_FRAMES  3
-#endif
-#endif
-#endif
-#endif
 
-#else /* is Mac OS X */
-
-#if defined(__ppc__) || defined(__ppc64__)
-#define PROF_ARTIFICIAL_FRAMES 8
-#elif defined(__i386__) || defined(__x86_64__)
+#if defined(__x86_64__)
 #define PROF_ARTIFICIAL_FRAMES  9
 #else
 #error Unknown architecture
 #endif
 
-#endif /* __APPLE__ */
-
 #define        PROF_NAMELEN            15
 
 #define        PROF_PROFILE            0
@@ -201,51 +160,35 @@ profile_fire(void *arg)
        late = dtrace_gethrtime() - pcpu->profc_expected;
        pcpu->profc_expected += pcpu->profc_interval;
 
-#if !defined(__APPLE__)
-       dtrace_probe(prof->prof_id, CPU->cpu_profile_pc,
-           CPU->cpu_profile_upc, late, 0, 0);
-#else
-#if defined(__ppc__) || defined(__ppc64__)
-       struct savearea *sv = find_kern_regs(current_thread());
-
-       if (sv) {
-               if (USERMODE(sv->save_srr1)) {
-                       dtrace_probe(prof->prof_id, 0x0, sv->save_srr0, late, 0, 0);
-               } else {
-                       dtrace_probe(prof->prof_id, sv->save_srr0, 0x0, late, 0, 0);
-               }
-       } else {
-               dtrace_probe(prof->prof_id, 0xcafebabe,
-               0x0, late, 0, 0); /* XXX_BOGUS also see profile_usermode() below. */
-       }
-#elif defined(__i386__) || defined(__x86_64__)
-       x86_saved_state32_t *kern_regs = find_kern_regs(current_thread());
+#if defined(__x86_64__)
+       x86_saved_state_t *kern_regs = find_kern_regs(current_thread());
 
        if (NULL != kern_regs) {
                /* Kernel was interrupted. */
-               dtrace_probe(prof->prof_id, kern_regs->eip,  0x0, 0, 0, 0);
+               dtrace_probe(prof->prof_id, saved_state64(kern_regs)->isf.rip,  0x0, late, 0, 0);
+
        } else {
+               pal_register_cache_state(current_thread(), VALID);
                /* Possibly a user interrupt */
                x86_saved_state_t   *tagged_regs = (x86_saved_state_t *)find_user_regs(current_thread());
 
                if (NULL == tagged_regs) {
                        /* Too bad, so sad, no useful interrupt state. */
                        dtrace_probe(prof->prof_id, 0xcafebabe,
-                       0x0, 0, 0, 0); /* XXX_BOGUS also see profile_usermode() below. */
+                       0x0, late, 0, 0); /* XXX_BOGUS also see profile_usermode() below. */
                } else if (is_saved_state64(tagged_regs)) {
                        x86_saved_state64_t *regs = saved_state64(tagged_regs);
 
-                       dtrace_probe(prof->prof_id, 0x0, regs->isf.rip, 0, 0, 0);
+                       dtrace_probe(prof->prof_id, 0x0, regs->isf.rip, late, 0, 0);
                } else {
                        x86_saved_state32_t *regs = saved_state32(tagged_regs);
 
-                       dtrace_probe(prof->prof_id, 0x0, regs->eip, 0, 0, 0);
-               }       
+                       dtrace_probe(prof->prof_id, 0x0, regs->eip, late, 0, 0);
+               }
        }
 #else
 #error Unknown architecture
 #endif
-#endif /* __APPLE__ */
 }
 
 static void
@@ -253,30 +196,14 @@ profile_tick(void *arg)
 {
        profile_probe_t *prof = arg;
 
-#if !defined(__APPLE__)
-       dtrace_probe(prof->prof_id, CPU->cpu_profile_pc,
-           CPU->cpu_profile_upc, 0, 0, 0);
-#else
-#if defined(__ppc__) || defined(__ppc64__)
-       struct savearea *sv = find_kern_regs(current_thread());
-
-       if (sv) {
-               if (USERMODE(sv->save_srr1)) {
-                       dtrace_probe(prof->prof_id, 0x0, sv->save_srr0, 0, 0, 0);
-               } else {
-                       dtrace_probe(prof->prof_id, sv->save_srr0, 0x0, 0, 0, 0);
-               }
-       } else {
-               dtrace_probe(prof->prof_id, 0xcafebabe,
-               0x0, 0, 0, 0); /* XXX_BOGUS also see profile_usermode() below. */
-       }
-#elif defined(__i386__) || defined(__x86_64__)
-       x86_saved_state32_t *kern_regs = find_kern_regs(current_thread());
+#if defined(__x86_64__)
+       x86_saved_state_t *kern_regs = find_kern_regs(current_thread());
 
        if (NULL != kern_regs) {
                /* Kernel was interrupted. */
-               dtrace_probe(prof->prof_id, kern_regs->eip,  0x0, 0, 0, 0);
+               dtrace_probe(prof->prof_id, saved_state64(kern_regs)->isf.rip,  0x0, 0, 0, 0);
        } else {
+               pal_register_cache_state(current_thread(), VALID);
                /* Possibly a user interrupt */
                x86_saved_state_t   *tagged_regs = (x86_saved_state_t *)find_user_regs(current_thread());
 
@@ -292,12 +219,11 @@ profile_tick(void *arg)
                        x86_saved_state32_t *regs = saved_state32(tagged_regs);
 
                        dtrace_probe(prof->prof_id, 0x0, regs->eip, 0, 0, 0);
-               }       
+               }
        }
 #else
 #error Unknown architecture
 #endif
-#endif /* __APPLE__ */
 }
 
 static void
@@ -317,14 +243,11 @@ profile_create(hrtime_t interval, const char *name, int kind)
                return;
        }
 
-#if !defined(__APPLE__)
-       prof = kmem_zalloc(sizeof (profile_probe_t), KM_SLEEP);
-#else
        if (PROF_TICK == kind)
                prof = kmem_zalloc(sizeof (profile_probe_t), KM_SLEEP);
        else
                prof = kmem_zalloc(sizeof (profile_probe_t) + NCPU*sizeof(profile_probe_percpu_t), KM_SLEEP);
-#endif /* __APPLE__ */
+
        (void) strlcpy(prof->prof_name, name, sizeof(prof->prof_name));
        prof->prof_interval = interval;
        prof->prof_cyclic = CYCLIC_NONE;
@@ -338,21 +261,22 @@ profile_create(hrtime_t interval, const char *name, int kind)
 static void
 profile_provide(void *arg, const dtrace_probedesc_t *desc)
 {
+#pragma unused(arg) /* __APPLE__ */
        int i, j, rate, kind;
        hrtime_t val = 0, mult = 1, len;
        const char *name, *suffix = NULL;
 
        const struct {
-               char *prefix;
+               const char *prefix;
                int kind;
        } types[] = {
                { PROF_PREFIX_PROFILE, PROF_PROFILE },
                { PROF_PREFIX_TICK, PROF_TICK },
-               { NULL, NULL }
+               { NULL, 0 }
        };
 
        const struct {
-               char *name;
+               const char *name;
                hrtime_t mult;
        } suffixes[] = {
                { "ns",         NANOSEC / NANOSEC },
@@ -370,12 +294,8 @@ profile_provide(void *arg, const dtrace_probedesc_t *desc)
                { "d",          NANOSEC * (hrtime_t)(24 * 60 * 60) },
                { "day",        NANOSEC * (hrtime_t)(24 * 60 * 60) },
                { "hz",         0 },
-#if !defined(__APPLE__)
-               { NULL }
-#else
                { NULL, 0 }
-#endif /* __APPLE__ */
-       };
+       };              
 
        if (desc == NULL) {
                char n[PROF_NAMELEN];
@@ -383,7 +303,7 @@ profile_provide(void *arg, const dtrace_probedesc_t *desc)
                /*
                 * If no description was provided, provide all of our probes.
                 */
-               for (i = 0; i < sizeof (profile_rates) / sizeof (int); i++) {
+               for (i = 0; i < (int)(sizeof (profile_rates) / sizeof (int)); i++) {
                        if ((rate = profile_rates[i]) == 0)
                                continue;
 
@@ -392,7 +312,7 @@ profile_provide(void *arg, const dtrace_probedesc_t *desc)
                        profile_create(NANOSEC / rate, n, PROF_PROFILE);
                }
 
-               for (i = 0; i < sizeof (profile_ticks) / sizeof (int); i++) {
+               for (i = 0; i < (int)(sizeof (profile_ticks) / sizeof (int)); i++) {
                        if ((rate = profile_ticks[i]) == 0)
                                continue;
 
@@ -449,7 +369,8 @@ profile_provide(void *arg, const dtrace_probedesc_t *desc)
         * Look-up the suffix to determine the multiplier.
         */
        for (i = 0, mult = 0; suffixes[i].name != NULL; i++) {
-               if (strcasecmp(suffixes[i].name, suffix) == 0) {
+               /* APPLE NOTE: Darwin employs size bounded string operations */
+               if (strncasecmp(suffixes[i].name, suffix, strlen(suffixes[i].name) + 1) == 0) {
                        mult = suffixes[i].mult;
                        break;
                }
@@ -474,17 +395,15 @@ profile_provide(void *arg, const dtrace_probedesc_t *desc)
 static void
 profile_destroy(void *arg, dtrace_id_t id, void *parg)
 {
+#pragma unused(arg,id) /* __APPLE__ */
        profile_probe_t *prof = parg;
 
        ASSERT(prof->prof_cyclic == CYCLIC_NONE);
-#if !defined(__APPLE__)
-       kmem_free(prof, sizeof (profile_probe_t));
-#else
+
        if (prof->prof_kind == PROF_TICK)
                kmem_free(prof, sizeof (profile_probe_t));
        else
                kmem_free(prof, sizeof (profile_probe_t) + NCPU*sizeof(profile_probe_percpu_t));
-#endif /* __APPLE__ */
 
        ASSERT(profile_total >= 1);
        atomic_add_32(&profile_total, -1);
@@ -492,16 +411,13 @@ profile_destroy(void *arg, dtrace_id_t id, void *parg)
 
 /*ARGSUSED*/
 static void
-profile_online(void *arg, cpu_t *cpu, cyc_handler_t *hdlr, cyc_time_t *when)
+profile_online(void *arg, dtrace_cpu_t *cpu, cyc_handler_t *hdlr, cyc_time_t *when)
 {
+#pragma unused(cpu) /* __APPLE__ */
        profile_probe_t *prof = arg;
        profile_probe_percpu_t *pcpu;
 
-#if !defined(__APPLE__)
-       pcpu = kmem_zalloc(sizeof (profile_probe_percpu_t), KM_SLEEP);
-#else
        pcpu = ((profile_probe_percpu_t *)(&(prof[1]))) + cpu_number();
-#endif /* __APPLE__ */
        pcpu->profc_probe = prof;
 
        hdlr->cyh_func = profile_fire;
@@ -509,11 +425,7 @@ profile_online(void *arg, cpu_t *cpu, cyc_handler_t *hdlr, cyc_time_t *when)
        hdlr->cyh_level = CY_HIGH_LEVEL;
 
        when->cyt_interval = prof->prof_interval;
-#if !defined(__APPLE__)
        when->cyt_when = dtrace_gethrtime() + when->cyt_interval;
-#else
-       when->cyt_when = 0;
-#endif /* __APPLE__ */
 
        pcpu->profc_expected = when->cyt_when;
        pcpu->profc_interval = when->cyt_interval;
@@ -521,20 +433,19 @@ profile_online(void *arg, cpu_t *cpu, cyc_handler_t *hdlr, cyc_time_t *when)
 
 /*ARGSUSED*/
 static void
-profile_offline(void *arg, cpu_t *cpu, void *oarg)
+profile_offline(void *arg, dtrace_cpu_t *cpu, void *oarg)
 {
        profile_probe_percpu_t *pcpu = oarg;
 
        ASSERT(pcpu->profc_probe == arg);
-#if !defined(__APPLE__)
-       kmem_free(pcpu, sizeof (profile_probe_percpu_t));
-#endif /* __APPLE__ */
+#pragma unused(pcpu,arg,cpu) /* __APPLE__ */
 }
 
 /*ARGSUSED*/
-static void
+static int
 profile_enable(void *arg, dtrace_id_t id, void *parg)
 {
+#pragma unused(arg,id) /* __APPLE__ */
        profile_probe_t *prof = parg;
        cyc_omni_handler_t omni;
        cyc_handler_t hdlr;
@@ -561,19 +472,13 @@ profile_enable(void *arg, dtrace_id_t id, void *parg)
                omni.cyo_arg = prof;
        }
 
-#if !defined(__APPLE__)
-       if (prof->prof_kind == PROF_TICK) {
-               prof->prof_cyclic = cyclic_add(&hdlr, &when);
-       } else {
-               prof->prof_cyclic = cyclic_add_omni(&omni);
-       }
-#else
        if (prof->prof_kind == PROF_TICK) {
                prof->prof_cyclic = cyclic_timer_add(&hdlr, &when);
        } else {
                prof->prof_cyclic = (cyclic_id_t)cyclic_add_omni(&omni); /* cast puns cyclic_id_list_t with cyclic_id_t */
        }
-#endif /* __APPLE__ */
+
+       return(0);
 }
 
 /*ARGSUSED*/
@@ -585,33 +490,24 @@ profile_disable(void *arg, dtrace_id_t id, void *parg)
        ASSERT(prof->prof_cyclic != CYCLIC_NONE);
        ASSERT(MUTEX_HELD(&cpu_lock));
 
-#if !defined(__APPLE__)
-       cyclic_remove(prof->prof_cyclic);
-#else
+#pragma unused(arg,id)
        if (prof->prof_kind == PROF_TICK) {
                cyclic_timer_remove(prof->prof_cyclic);
        } else {
                cyclic_remove_omni((cyclic_id_list_t)prof->prof_cyclic); /* cast puns cyclic_id_list_t with cyclic_id_t */
        }
-#endif /* __APPLE__ */
        prof->prof_cyclic = CYCLIC_NONE;
 }
 
-#if !defined(__APPLE__)
-/*ARGSUSED*/
-static int
-profile_usermode(void *arg, dtrace_id_t id, void *parg)
-{
-       return (CPU->cpu_profile_pc == 0);
-}
-#else
+/*
+ * APPLE NOTE:  profile_usermode call not supported.
+ */
 static int
 profile_usermode(void *arg, dtrace_id_t id, void *parg)
 {
 #pragma unused(arg,id,parg)
        return 1; /* XXX_BOGUS */
 }
-#endif /* __APPLE__ */
 
 static dtrace_pattr_t profile_attr = {
 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
@@ -647,7 +543,7 @@ profile_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
        }
 
        if (ddi_create_minor_node(devi, "profile", S_IFCHR, 0,
-           DDI_PSEUDO, NULL) == DDI_FAILURE ||
+           DDI_PSEUDO, 0) == DDI_FAILURE ||
            dtrace_register("profile", &profile_attr,
            DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER, NULL,
            &profile_pops, NULL, &profile_id) != 0) {
@@ -655,18 +551,16 @@ profile_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
                return (DDI_FAILURE);
        }
 
-#if !defined(__APPLE__)
-       profile_max = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
-           "profile-max-probes", PROFILE_MAX_DEFAULT);
-#else
        profile_max = PROFILE_MAX_DEFAULT;
-#endif /* __APPLE__ */
 
        ddi_report_dev(devi);
        profile_devi = devi;
        return (DDI_SUCCESS);
 }
 
+/*
+ * APPLE NOTE:  profile_detach not implemented
+ */
 #if !defined(__APPLE__)
 static int
 profile_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
@@ -686,100 +580,8 @@ profile_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
        ddi_remove_minor_node(devi, NULL);
        return (DDI_SUCCESS);
 }
+#endif /* __APPLE__ */
 
-/*ARGSUSED*/
-static int
-profile_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
-       int error;
-
-       switch (infocmd) {
-       case DDI_INFO_DEVT2DEVINFO:
-               *result = (void *)profile_devi;
-               error = DDI_SUCCESS;
-               break;
-       case DDI_INFO_DEVT2INSTANCE:
-               *result = (void *)0;
-               error = DDI_SUCCESS;
-               break;
-       default:
-               error = DDI_FAILURE;
-       }
-       return (error);
-}
-
-/*ARGSUSED*/
-static int
-profile_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
-{
-       return (0);
-}
-
-static struct cb_ops profile_cb_ops = {
-       profile_open,           /* open */
-       nodev,                  /* close */
-       nulldev,                /* strategy */
-       nulldev,                /* print */
-       nodev,                  /* dump */
-       nodev,                  /* read */
-       nodev,                  /* write */
-       nodev,                  /* ioctl */
-       nodev,                  /* devmap */
-       nodev,                  /* mmap */
-       nodev,                  /* segmap */
-       nochpoll,               /* poll */
-       ddi_prop_op,            /* cb_prop_op */
-       0,                      /* streamtab  */
-       D_NEW | D_MP            /* Driver compatibility flag */
-};
-
-static struct dev_ops profile_ops = {
-       DEVO_REV,               /* devo_rev, */
-       0,                      /* refcnt  */
-       profile_info,           /* get_dev_info */
-       nulldev,                /* identify */
-       nulldev,                /* probe */
-       profile_attach,         /* attach */
-       profile_detach,         /* detach */
-       nodev,                  /* reset */
-       &profile_cb_ops,        /* driver operations */
-       NULL,                   /* bus operations */
-       nodev                   /* dev power */
-};
-
-/*
- * Module linkage information for the kernel.
- */
-static struct modldrv modldrv = {
-       &mod_driverops,         /* module type (this is a pseudo driver) */
-       "Profile Interrupt Tracing",    /* name of module */
-       &profile_ops,           /* driver ops */
-};
-
-static struct modlinkage modlinkage = {
-       MODREV_1,
-       (void *)&modldrv,
-       NULL
-};
-
-int
-_init(void)
-{
-       return (mod_install(&modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
-       return (mod_info(&modlinkage, modinfop));
-}
-
-int
-_fini(void)
-{
-       return (mod_remove(&modlinkage));
-}
-#else
 d_open_t _profile_open;
 
 int _profile_open(dev_t dev, int flags, int devtype, struct proc *p)
@@ -826,11 +628,10 @@ void profile_init( void )
                        return;
                }
 
-               profile_attach( (dev_info_t     *)majdevno, DDI_ATTACH );
+               profile_attach( (dev_info_t     *)(uintptr_t)majdevno, DDI_ATTACH );
 
                gProfileInited = 1;
        } else
                panic("profile_init: called twice!\n");
 }
 #undef PROFILE_MAJOR
-#endif /* __APPLE__ */