X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/d9a64523371fa019c4575bb400cbbc3a50ac9903..4ba76501152d51ccb5647018f3192c6096367d48:/bsd/dev/arm/dtrace_isa.c diff --git a/bsd/dev/arm/dtrace_isa.c b/bsd/dev/arm/dtrace_isa.c index 07397b4b8..1f8dbd2ef 100644 --- a/bsd/dev/arm/dtrace_isa.c +++ b/bsd/dev/arm/dtrace_isa.c @@ -1,8 +1,8 @@ /* - * Copyright (c) 2005-2008 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2005-2018 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,12 +22,10 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ -#define MACH__POSIX_C_SOURCE_PRIVATE 1 /* pulls in suitable savearea from - * mach/ppc/thread_status.h */ #include #include @@ -44,9 +42,9 @@ #include #include #include -#include +#include #include -#include /* for thread_wakeup() */ +#include /* for thread_wakeup() */ #include #include #include @@ -57,8 +55,8 @@ extern struct arm_saved_state *find_kern_regs(thread_t); extern dtrace_id_t dtrace_probeid_error; /* special ERROR probe */ typedef arm_saved_state_t savearea_t; -extern lck_attr_t *dtrace_lck_attr; -extern lck_grp_t *dtrace_lck_grp; +extern lck_attr_t *dtrace_lck_attr; +extern lck_grp_t *dtrace_lck_grp; int dtrace_arm_condition_true(int condition, int cpsr); @@ -69,9 +67,9 @@ inline void dtrace_membar_producer(void) { #if __ARM_SMP__ - __asm__ volatile("dmb ish" : : : "memory"); + __asm__ volatile ("dmb ish" : : : "memory"); #else - __asm__ volatile("nop" : : : "memory"); + __asm__ volatile ("nop" : : : "memory"); #endif } @@ -79,9 +77,9 @@ inline void dtrace_membar_consumer(void) { #if __ARM_SMP__ - __asm__ volatile("dmb ish" : : : "memory"); + __asm__ volatile ("dmb ish" : : : "memory"); #else - __asm__ volatile("nop" : : : "memory"); + __asm__ volatile ("nop" : : : "memory"); #endif } @@ -97,7 +95,7 @@ dtrace_getipl(void) * in osfmk/kern/cpu_data.h */ /* return get_interrupt_level(); */ - return (ml_at_interrupt_context() ? 1 : 0); + return ml_at_interrupt_context() ? 1 : 0; } #if __ARM_SMP__ @@ -119,11 +117,13 @@ xcRemote(void *foo) { xcArg_t *pArg = (xcArg_t *) foo; - if (pArg->cpu == CPU->cpu_id || pArg->cpu == DTRACE_CPUALL) - (pArg->f) (pArg->arg); + if (pArg->cpu == CPU->cpu_id || pArg->cpu == DTRACE_CPUALL) { + (pArg->f)(pArg->arg); + } - if (hw_atomic_sub(&dt_xc_sync, 1) == 0) + if (os_atomic_dec(&dt_xc_sync, relaxed) == 0) { thread_wakeup((event_t) &dt_xc_sync); + } } #endif @@ -178,12 +178,12 @@ dtrace_getreg(struct regs * savearea, uint_t reg) struct arm_saved_state *regs = (struct arm_saved_state *) savearea; if (regs == NULL) { DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); - return (0); + return 0; } /* beyond register limit? */ if (reg > ARM_SAVED_STATE32_COUNT - 1) { DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP); - return (0); + return 0; } return (uint64_t) ((unsigned int *) (&(regs->r)))[reg]; @@ -193,10 +193,10 @@ dtrace_getreg(struct regs * savearea, uint_t reg) static int dtrace_getustack_common(uint64_t * pcstack, int pcstack_limit, user_addr_t pc, - user_addr_t sp) + user_addr_t sp) { int ret = 0; - + ASSERT(pcstack == NULL || pcstack_limit > 0); while (pc != 0) { @@ -204,18 +204,20 @@ dtrace_getustack_common(uint64_t * pcstack, int pcstack_limit, user_addr_t pc, if (pcstack != NULL) { *pcstack++ = (uint64_t) pc; pcstack_limit--; - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { break; + } } - if (sp == 0) + if (sp == 0) { break; + } pc = dtrace_fuword32((sp + RETURN_OFFSET)); sp = dtrace_fuword32(sp); } - return (ret); + return ret; } void @@ -224,30 +226,35 @@ dtrace_getupcstack(uint64_t * pcstack, int pcstack_limit) thread_t thread = current_thread(); savearea_t *regs; user_addr_t pc, sp; - volatile uint16_t *flags = (volatile uint16_t *) & cpu_core[CPU->cpu_id].cpuc_dtrace_flags; + volatile uint16_t *flags = (volatile uint16_t *) &cpu_core[CPU->cpu_id].cpuc_dtrace_flags; int n; - if (*flags & CPU_DTRACE_FAULT) + if (*flags & CPU_DTRACE_FAULT) { return; + } - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { return; + } /* * If there's no user context we still need to zero the stack. */ - if (thread == NULL) + if (thread == NULL) { goto zero; + } regs = (savearea_t *) find_user_regs(thread); - if (regs == NULL) + if (regs == NULL) { goto zero; + } *pcstack++ = (uint64_t)dtrace_proc_selfpid(); pcstack_limit--; - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { return; + } pc = regs->pc; sp = regs->sp; @@ -255,8 +262,9 @@ dtrace_getupcstack(uint64_t * pcstack, int pcstack_limit) if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) { *pcstack++ = (uint64_t) pc; pcstack_limit--; - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { return; + } pc = regs->lr; } @@ -270,8 +278,9 @@ dtrace_getupcstack(uint64_t * pcstack, int pcstack_limit) pcstack_limit -= n; zero: - while (pcstack_limit-- > 0) + while (pcstack_limit-- > 0) { *pcstack++ = 0ULL; + } } int @@ -282,15 +291,18 @@ dtrace_getustackdepth(void) user_addr_t pc, sp; int n = 0; - if (thread == NULL) + if (thread == NULL) { return 0; + } - if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) - return (-1); + if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT)) { + return -1; + } regs = (savearea_t *) find_user_regs(thread); - if (regs == NULL) + if (regs == NULL) { return 0; + } pc = regs->pc; sp = regs->sp; @@ -300,7 +312,7 @@ dtrace_getustackdepth(void) pc = regs->lr; } - /* + /* * Note that unlike ppc, the arm code does not use * CPU_DTRACE_USTACK_FP. This is because arm always * traces from the sp, even in syscall/profile/fbt @@ -309,7 +321,7 @@ dtrace_getustackdepth(void) n += dtrace_getustack_common(NULL, 0, pc, regs->r[7]); - return (n); + return n; } void @@ -319,40 +331,45 @@ dtrace_getufpstack(uint64_t * pcstack, uint64_t * fpstack, int pcstack_limit) thread_t thread = current_thread(); savearea_t *regs; user_addr_t pc, sp; - - volatile uint16_t *flags = (volatile uint16_t *) & cpu_core[CPU->cpu_id].cpuc_dtrace_flags; + + volatile uint16_t *flags = (volatile uint16_t *) &cpu_core[CPU->cpu_id].cpuc_dtrace_flags; #if 0 uintptr_t oldcontext; size_t s1, s2; #endif - if (*flags & CPU_DTRACE_FAULT) + if (*flags & CPU_DTRACE_FAULT) { return; + } - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { return; + } - /* + /* * If there's no user context we still need to zero the stack. */ - if (thread == NULL) + if (thread == NULL) { goto zero; + } regs = (savearea_t *) find_user_regs(thread); - if (regs == NULL) + if (regs == NULL) { goto zero; - + } + *pcstack++ = (uint64_t)dtrace_proc_selfpid(); pcstack_limit--; - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { return; - + } + pc = regs->pc; sp = regs->sp; -#if 0 /* XXX signal stack crawl */ +#if 0 /* XXX signal stack crawl */ oldcontext = lwp->lwp_oldcontext; if (p->p_model == DATAMODEL_NATIVE) { @@ -368,8 +385,9 @@ dtrace_getufpstack(uint64_t * pcstack, uint64_t * fpstack, int pcstack_limit) *pcstack++ = (uint64_t) pc; *fpstack++ = 0; pcstack_limit--; - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { return; + } pc = dtrace_fuword32(sp); } @@ -377,10 +395,11 @@ dtrace_getufpstack(uint64_t * pcstack, uint64_t * fpstack, int pcstack_limit) *pcstack++ = (uint64_t) pc; *fpstack++ = sp; pcstack_limit--; - if (pcstack_limit <= 0) + if (pcstack_limit <= 0) { break; + } -#if 0 /* XXX signal stack crawl */ +#if 0 /* XXX signal stack crawl */ if (oldcontext == sp + s1 || oldcontext == sp + s2) { if (p->p_model == DATAMODEL_NATIVE) { ucontext_t *ucp = (ucontext_t *) oldcontext; @@ -421,13 +440,14 @@ dtrace_getufpstack(uint64_t * pcstack, uint64_t * fpstack, int pcstack_limit) } zero: - while (pcstack_limit-- > 0) + while (pcstack_limit-- > 0) { *pcstack++ = 0ULL; + } } void dtrace_getpcstack(pc_t * pcstack, int pcstack_limit, int aframes, - uint32_t * intrpc) + uint32_t * intrpc) { struct frame *fp = (struct frame *) __builtin_frame_address(0); struct frame *nextfp, *minfp, *stacktop; @@ -437,17 +457,19 @@ dtrace_getpcstack(pc_t * pcstack, int pcstack_limit, int aframes, uintptr_t pc; uintptr_t caller = CPU->cpu_dtrace_caller; - if ((on_intr = CPU_ON_INTR(CPU)) != 0) + if ((on_intr = CPU_ON_INTR(CPU)) != 0) { stacktop = (struct frame *) dtrace_get_cpu_int_stack_top(); - else + } else { stacktop = (struct frame *) (dtrace_get_kernel_stack(current_thread()) + kernel_stack_size); + } minfp = fp; aframes++; - if (intrpc != NULL && depth < pcstack_limit) + if (intrpc != NULL && depth < pcstack_limit) { pcstack[depth++] = (pc_t) intrpc; + } while (depth < pcstack_limit) { nextfp = *(struct frame **) fp; @@ -500,13 +522,15 @@ dtrace_getpcstack(pc_t * pcstack, int pcstack_limit, int aframes, caller = (uintptr_t)NULL; } } else { - if (depth < pcstack_limit) + if (depth < pcstack_limit) { pcstack[depth++] = (pc_t) pc; + } } if (last) { - while (depth < pcstack_limit) + while (depth < pcstack_limit) { pcstack[depth++] = (pc_t) NULL; + } return; } fp = nextfp; @@ -519,10 +543,11 @@ dtrace_instr_size(uint32_t instr, int thumb_mode) { if (thumb_mode) { uint16_t instr16 = *(uint16_t*) &instr; - if (((instr16 >> 11) & 0x1F) > 0x1C) + if (((instr16 >> 11) & 0x1F) > 0x1C) { return 4; - else + } else { return 2; + } } else { return 4; } @@ -534,7 +559,7 @@ dtrace_getarg(int arg, int aframes, dtrace_mstate_t *mstate, dtrace_vstate_t *vs #pragma unused(arg, aframes, mstate, vstate) #if 0 /* XXX ARMTODO */ - uint64_t val; + uint64_t val; uintptr_t *fp = (uintptr_t *)__builtin_frame_address(0); uintptr_t *stack; uintptr_t pc; @@ -545,23 +570,23 @@ dtrace_getarg(int arg, int aframes, dtrace_mstate_t *mstate, dtrace_vstate_t *vs pc = fp[1]; if (dtrace_invop_callsite_pre != NULL - && pc > (uintptr_t)dtrace_invop_callsite_pre - && pc <= (uintptr_t)dtrace_invop_callsite_post) { - /* - * If we pass through the invalid op handler, we will - * use the pointer that it passed to the stack as the - * second argument to dtrace_invop() as the pointer to - * the frame we're hunting for. - */ - - stack = (uintptr_t *)&fp[1]; /* Find marshalled arguments */ - fp = (struct frame *)stack[1]; /* Grab *second* argument */ - stack = (uintptr_t *)&fp[1]; /* Find marshalled arguments */ - DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); - val = (uint64_t)(stack[arg]); - DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); - return val; - } + && pc > (uintptr_t)dtrace_invop_callsite_pre + && pc <= (uintptr_t)dtrace_invop_callsite_post) { + /* + * If we pass through the invalid op handler, we will + * use the pointer that it passed to the stack as the + * second argument to dtrace_invop() as the pointer to + * the frame we're hunting for. + */ + + stack = (uintptr_t *)&fp[1]; /* Find marshalled arguments */ + fp = (struct frame *)stack[1]; /* Grab *second* argument */ + stack = (uintptr_t *)&fp[1]; /* Find marshalled arguments */ + DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); + val = (uint64_t)(stack[arg]); + DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); + return val; + } } /* @@ -573,14 +598,14 @@ dtrace_getarg(int arg, int aframes, dtrace_mstate_t *mstate, dtrace_vstate_t *vs DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); val = *(((uint64_t *)stack) + arg); /* dtrace_probe arguments arg0 .. arg4 are 64bits wide */ DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT); - return (val); + return val; #endif return 0xfeedfacedeafbeadLL; } void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, - int fltoffs, int fault, uint64_t illval) + int fltoffs, int fault, uint64_t illval) { /* XXX ARMTODO */ /* @@ -595,13 +620,14 @@ void dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit)) { /* XXX ARMTODO check copied from ppc/x86*/ - /* + /* * "base" is the smallest toxic address in the range, "limit" is the first * VALID address greater than "base". - */ + */ func(0x0, VM_MIN_KERNEL_ADDRESS); - if (VM_MAX_KERNEL_ADDRESS < ~(uintptr_t)0) - func(VM_MAX_KERNEL_ADDRESS + 1, ~(uintptr_t)0); + if (VM_MAX_KERNEL_ADDRESS < ~(uintptr_t)0) { + func(VM_MAX_KERNEL_ADDRESS + 1, ~(uintptr_t)0); + } } int @@ -613,29 +639,30 @@ dtrace_arm_condition_true(int cond, int cpsr) cf = (cpsr & PSR_CF) ? 1 : 0, vf = (cpsr & PSR_VF) ? 1 : 0; - switch(cond) { - case 0: taken = zf; break; - case 1: taken = !zf; break; - case 2: taken = cf; break; - case 3: taken = !cf; break; - case 4: taken = nf; break; - case 5: taken = !nf; break; - case 6: taken = vf; break; - case 7: taken = !vf; break; - case 8: taken = (cf && !zf); break; - case 9: taken = (!cf || zf); break; - case 10: taken = (nf == vf); break; - case 11: taken = (nf != vf); break; - case 12: taken = (!zf && (nf == vf)); break; - case 13: taken = (zf || (nf != vf)); break; - case 14: taken = 1; break; - case 15: taken = 1; break; /* always "true" for ARM, unpredictable for THUMB. */ + switch (cond) { + case 0: taken = zf; break; + case 1: taken = !zf; break; + case 2: taken = cf; break; + case 3: taken = !cf; break; + case 4: taken = nf; break; + case 5: taken = !nf; break; + case 6: taken = vf; break; + case 7: taken = !vf; break; + case 8: taken = (cf && !zf); break; + case 9: taken = (!cf || zf); break; + case 10: taken = (nf == vf); break; + case 11: taken = (nf != vf); break; + case 12: taken = (!zf && (nf == vf)); break; + case 13: taken = (zf || (nf != vf)); break; + case 14: taken = 1; break; + case 15: taken = 1; break; /* always "true" for ARM, unpredictable for THUMB. */ } return taken; } -void dtrace_flush_caches(void) +void +dtrace_flush_caches(void) { /* TODO There were some problems with flushing just the cache line that had been modified. * For now, we'll flush the entire cache, until we figure out how to flush just the patched block.