X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/36401178fd6817c043cc00b0c00c7f723e58efae..4b17d6b6e417f714551ec129064745ea9919780e:/bsd/dev/dtrace/profile_prvd.c diff --git a/bsd/dev/dtrace/profile_prvd.c b/bsd/dev/dtrace/profile_prvd.c index 14895f8d9..36e213ce1 100644 --- a/bsd/dev/dtrace/profile_prvd.c +++ b/bsd/dev/dtrace/profile_prvd.c @@ -19,11 +19,11 @@ * 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 @@ -49,6 +49,7 @@ #define MACH__POSIX_C_SOURCE_PRIVATE 1 /* pulls in suitable savearea from mach/ppc/thread_status.h */ #include #include +#include #include #include @@ -65,10 +66,10 @@ #include -#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 + +#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