]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/dev/dtrace/profile_prvd.c
xnu-2050.24.15.tar.gz
[apple/xnu.git] / bsd / dev / dtrace / profile_prvd.c
index 14895f8d983e8fd09e8f0263148be40930cfaf0f..36e213ce1040e333ce0d5a1b1f4faf4d3a3ea302 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>
@@ -49,6 +49,7 @@
 #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(__i386__) || defined(__x86_64__)
+extern x86_saved_state_t *find_kern_regs(thread_t);
 #else
 #error Unknown architecture
 #endif
@@ -83,20 +84,18 @@ 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,34 +107,28 @@ 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
+#ifdef __x86
+#define        PROF_ARTIFICIAL_FRAMES  10
 #else
 #ifdef __sparc
-#ifdef DEBUG
+#if 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(__i386__) || defined(__x86_64__)
 #define PROF_ARTIFICIAL_FRAMES  9
 #else
 #error Unknown architecture
@@ -205,26 +198,20 @@ profile_fire(void *arg)
        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(__i386__) || 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);
+#if defined(__i386__)
+               dtrace_probe(prof->prof_id, saved_state32(kern_regs)->eip,  0x0, 0, 0, 0);
+#elif defined(__x86_64__)
+               dtrace_probe(prof->prof_id, saved_state64(kern_regs)->isf.rip,  0x0, 0, 0, 0);
+#else
+#error Unknown arch
+#endif
        } 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());
 
@@ -240,7 +227,7 @@ profile_fire(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
@@ -257,26 +244,20 @@ profile_tick(void *arg)
        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(__i386__) || 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);
+#if defined(__i386__)
+               dtrace_probe(prof->prof_id, saved_state32(kern_regs)->eip,  0x0, 0, 0, 0);
+#elif defined(__x86_64__)
+               dtrace_probe(prof->prof_id, saved_state64(kern_regs)->isf.rip,  0x0, 0, 0, 0);
+#else
+#error Unknown arch
+#endif
        } 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,7 +273,7 @@ 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
@@ -338,10 +319,12 @@ 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;
 
+#if !defined(__APPLE__)
        const struct {
                char *prefix;
                int kind;
@@ -370,20 +353,53 @@ 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
+       const struct {
+               const char *prefix;
+               int kind;
+       } types[] = {
+               { PROF_PREFIX_PROFILE, PROF_PROFILE },
+               { PROF_PREFIX_TICK, PROF_TICK },
                { NULL, 0 }
-#endif /* __APPLE__ */
        };
 
+       const struct {
+               const char *name;
+               hrtime_t mult;
+       } suffixes[] = {
+               { "ns",         NANOSEC / NANOSEC },
+               { "nsec",       NANOSEC / NANOSEC },
+               { "us",         NANOSEC / MICROSEC },
+               { "usec",       NANOSEC / MICROSEC },
+               { "ms",         NANOSEC / MILLISEC },
+               { "msec",       NANOSEC / MILLISEC },
+               { "s",          NANOSEC / SEC },
+               { "sec",        NANOSEC / SEC },
+               { "m",          NANOSEC * (hrtime_t)60 },
+               { "min",        NANOSEC * (hrtime_t)60 },
+               { "h",          NANOSEC * (hrtime_t)(60 * 60) },
+               { "hour",       NANOSEC * (hrtime_t)(60 * 60) },
+               { "d",          NANOSEC * (hrtime_t)(24 * 60 * 60) },
+               { "day",        NANOSEC * (hrtime_t)(24 * 60 * 60) },
+               { "hz",         0 },
+               { NULL, 0 }
+       };              
+#endif /* __APPLE__ */
+
+
        if (desc == NULL) {
                char n[PROF_NAMELEN];
 
                /*
                 * If no description was provided, provide all of our probes.
                 */
+#if !defined(__APPLE__)
                for (i = 0; i < sizeof (profile_rates) / sizeof (int); i++) {
+#else
+               for (i = 0; i < (int)(sizeof (profile_rates) / sizeof (int)); i++) {
+#endif /* __APPLE__ */
                        if ((rate = profile_rates[i]) == 0)
                                continue;
 
@@ -392,7 +408,11 @@ profile_provide(void *arg, const dtrace_probedesc_t *desc)
                        profile_create(NANOSEC / rate, n, PROF_PROFILE);
                }
 
+#if !defined(__APPLE__)
                for (i = 0; i < sizeof (profile_ticks) / sizeof (int); i++) {
+#else
+               for (i = 0; i < (int)(sizeof (profile_ticks) / sizeof (int)); i++) {
+#endif /* __APPLE__ */
                        if ((rate = profile_ticks[i]) == 0)
                                continue;
 
@@ -449,10 +469,17 @@ 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 !defined(__APPLE__)
                if (strcasecmp(suffixes[i].name, suffix) == 0) {
                        mult = suffixes[i].mult;
                        break;
                }
+#else
+               if (strncasecmp(suffixes[i].name, suffix, strlen(suffixes[i].name) + 1) == 0) {
+                       mult = suffixes[i].mult;
+                       break;
+               }
+#endif /* __APPLE__ */
        }
 
        if (suffixes[i].name == NULL && *suffix != '\0')
@@ -474,6 +501,7 @@ 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);
@@ -492,8 +520,9 @@ 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;
 
@@ -521,20 +550,23 @@ 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));
+#else
+#pragma unused(pcpu,arg,cpu) /* __APPLE__ */
 #endif /* __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;
@@ -574,6 +606,7 @@ profile_enable(void *arg, dtrace_id_t id, void *parg)
                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*/
@@ -588,6 +621,7 @@ profile_disable(void *arg, dtrace_id_t id, void *parg)
 #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 {
@@ -646,6 +680,7 @@ profile_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
                return (DDI_FAILURE);
        }
 
+#if !defined(__APPLE__)
        if (ddi_create_minor_node(devi, "profile", S_IFCHR, 0,
            DDI_PSEUDO, NULL) == DDI_FAILURE ||
            dtrace_register("profile", &profile_attr,
@@ -654,11 +689,19 @@ profile_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
                ddi_remove_minor_node(devi, NULL);
                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
+       if (ddi_create_minor_node(devi, "profile", S_IFCHR, 0,
+           DDI_PSEUDO, 0) == DDI_FAILURE ||
+           dtrace_register("profile", &profile_attr,
+           DTRACE_PRIV_KERNEL | DTRACE_PRIV_USER, NULL,
+           &profile_pops, NULL, &profile_id) != 0) {
+               ddi_remove_minor_node(devi, NULL);
+               return (DDI_FAILURE);
+       }
+
        profile_max = PROFILE_MAX_DEFAULT;
 #endif /* __APPLE__ */
 
@@ -826,7 +869,7 @@ 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