X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/43866e378188c25dd1e2208016ab3cbeb086ae6c..5d5c5d0d5b79ade9a973d55186ffda2638ba2b6e:/osfmk/kdp/ml/ppc/kdp_machdep.c diff --git a/osfmk/kdp/ml/ppc/kdp_machdep.c b/osfmk/kdp/ml/ppc/kdp_machdep.c index 456c5a764..79d74ad73 100644 --- a/osfmk/kdp/ml/ppc/kdp_machdep.c +++ b/osfmk/kdp/ml/ppc/kdp_machdep.c @@ -1,26 +1,31 @@ /* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. * - * @APPLE_LICENSE_HEADER_START@ + * @APPLE_LICENSE_OSREFERENCE_HEADER_START@ * - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * - * 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 - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this + * 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 + * compliance with the License. The rights granted to you under the + * License may not be used to create, or enable the creation or + * redistribution of, 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, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and + * + * 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, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * 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_LICENSE_HEADER_END@ + * + * @APPLE_LICENSE_OSREFERENCE_HEADER_END@ */ #include @@ -30,6 +35,13 @@ #include #include #include +#include + + +#include +#include +#include +#include #define KDP_TEST_HARNESS 0 #if KDP_TEST_HARNESS @@ -44,6 +56,21 @@ void kdp_trap( unsigned int, struct savearea *saved_state); int kdp_getc(void); boolean_t kdp_call_kdb(void); +extern pmap_t kdp_pmap; +extern uint32_t kdp_src_high32; + + +extern unsigned kdp_vm_read(caddr_t src, caddr_t dst, unsigned len); + +int +machine_trace_thread(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p); + +int +machine_trace_thread64(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p); + +unsigned +machine_read64(addr64_t srcaddr, caddr_t dstaddr, uint32_t len); + void kdp_exception( unsigned char *pkt, @@ -120,6 +147,57 @@ kdp_getintegerstate( bzero((char *)state,sizeof (struct ppc_thread_state)) ; + state->srr0 = (unsigned int)saved_state->save_srr0; + state->srr1 = (unsigned int)saved_state->save_srr1; + state->r0 = (unsigned int)saved_state->save_r0; + state->r1 = (unsigned int)saved_state->save_r1; + state->r2 = (unsigned int)saved_state->save_r2; + state->r3 = (unsigned int)saved_state->save_r3; + state->r4 = (unsigned int)saved_state->save_r4; + state->r5 = (unsigned int)saved_state->save_r5; + state->r6 = (unsigned int)saved_state->save_r6; + state->r7 = (unsigned int)saved_state->save_r7; + state->r8 = (unsigned int)saved_state->save_r8; + state->r9 = (unsigned int)saved_state->save_r9; + state->r10 = (unsigned int)saved_state->save_r10; + state->r11 = (unsigned int)saved_state->save_r11; + state->r12 = (unsigned int)saved_state->save_r12; + state->r13 = (unsigned int)saved_state->save_r13; + state->r14 = (unsigned int)saved_state->save_r14; + state->r15 = (unsigned int)saved_state->save_r15; + state->r16 = (unsigned int)saved_state->save_r16; + state->r17 = (unsigned int)saved_state->save_r17; + state->r18 = (unsigned int)saved_state->save_r18; + state->r19 = (unsigned int)saved_state->save_r19; + state->r20 = (unsigned int)saved_state->save_r20; + state->r21 = (unsigned int)saved_state->save_r21; + state->r22 = (unsigned int)saved_state->save_r22; + state->r23 = (unsigned int)saved_state->save_r23; + state->r24 = (unsigned int)saved_state->save_r24; + state->r25 = (unsigned int)saved_state->save_r25; + state->r26 = (unsigned int)saved_state->save_r26; + state->r27 = (unsigned int)saved_state->save_r27; + state->r28 = (unsigned int)saved_state->save_r28; + state->r29 = (unsigned int)saved_state->save_r29; + state->r30 = (unsigned int)saved_state->save_r30; + state->r31 = (unsigned int)saved_state->save_r31; + state->cr = (unsigned int)saved_state->save_cr; + state->xer = (unsigned int)saved_state->save_xer; + state->lr = (unsigned int)saved_state->save_lr; + state->ctr = (unsigned int)saved_state->save_ctr; +} + +static void +kdp_getintegerstate64( + struct ppc_thread_state64 *state +) +{ + struct savearea *saved_state; + + saved_state = kdp.saved_state; + + bzero((char *)state,sizeof (struct ppc_thread_state64)) ; + state->srr0 = saved_state->save_srr0; state->srr1 = saved_state->save_srr1; state->r0 = saved_state->save_r0; @@ -175,13 +253,19 @@ kdp_machine_read_regs( kdp_getintegerstate((struct ppc_thread_state *)data); *size = PPC_THREAD_STATE_COUNT * sizeof(int); return KDPERR_NO_ERROR; - + + case PPC_THREAD_STATE64: + dprintf(("kdp_readregs THREAD_STATE\n")); + kdp_getintegerstate64((struct ppc_thread_state64 *)data); + *size = PPC_THREAD_STATE64_COUNT * sizeof(int); + return KDPERR_NO_ERROR; + case PPC_FLOAT_STATE: dprintf(("kdp_readregs THREAD_FPSTATE\n")); bzero((char *)data ,sizeof(struct ppc_float_state)); *size = PPC_FLOAT_STATE_COUNT * sizeof(int); return KDPERR_NO_ERROR; - + default: dprintf(("kdp_readregs bad flavor %d\n")); return KDPERR_BADFLAVOR; @@ -237,6 +321,55 @@ kdp_setintegerstate( saved_state->save_ctr = state->ctr; } +static void +kdp_setintegerstate64( + struct ppc_thread_state64 *state +) +{ + struct savearea *saved_state; + + saved_state = kdp.saved_state; + + saved_state->save_srr0 = state->srr0; + saved_state->save_srr1 = state->srr1; + saved_state->save_r0 = state->r0; + saved_state->save_r1 = state->r1; + saved_state->save_r2 = state->r2; + saved_state->save_r3 = state->r3; + saved_state->save_r4 = state->r4; + saved_state->save_r5 = state->r5; + saved_state->save_r6 = state->r6; + saved_state->save_r7 = state->r7; + saved_state->save_r8 = state->r8; + saved_state->save_r9 = state->r9; + saved_state->save_r10 = state->r10; + saved_state->save_r11 = state->r11; + saved_state->save_r12 = state->r12; + saved_state->save_r13 = state->r13; + saved_state->save_r14 = state->r14; + saved_state->save_r15 = state->r15; + saved_state->save_r16 = state->r16; + saved_state->save_r17 = state->r17; + saved_state->save_r18 = state->r18; + saved_state->save_r19 = state->r19; + saved_state->save_r20 = state->r20; + saved_state->save_r21 = state->r21; + saved_state->save_r22 = state->r22; + saved_state->save_r23 = state->r23; + saved_state->save_r24 = state->r24; + saved_state->save_r25 = state->r25; + saved_state->save_r26 = state->r26; + saved_state->save_r27 = state->r27; + saved_state->save_r28 = state->r28; + saved_state->save_r29 = state->r29; + saved_state->save_r30 = state->r30; + saved_state->save_r31 = state->r31; + saved_state->save_cr = state->cr; + saved_state->save_xer = state->xer; + saved_state->save_lr = state->lr; + saved_state->save_ctr = state->ctr; +} + kdp_error_t kdp_machine_write_regs( unsigned int cpu, @@ -255,11 +388,19 @@ kdp_machine_write_regs( DumpTheSave((struct savearea *)data); /* (TEST/DEBUG) */ #endif return KDPERR_NO_ERROR; - + + case PPC_THREAD_STATE64: + dprintf(("kdp_writeregs THREAD_STATE64\n")); + kdp_setintegerstate64((struct ppc_thread_state64 *)data); + +#if KDP_TEST_HARNESS + DumpTheSave((struct savearea *)data); /* (TEST/DEBUG) */ +#endif + return KDPERR_NO_ERROR; case PPC_FLOAT_STATE: dprintf(("kdp_writeregs THREAD_FPSTATE\n")); return KDPERR_NO_ERROR; - + default: dprintf(("kdp_writeregs bad flavor %d\n")); return KDPERR_BADFLAVOR; @@ -271,21 +412,20 @@ kdp_machine_hostinfo( kdp_hostinfo_t *hostinfo ) { - machine_slot_t m; int i; hostinfo->cpus_mask = 0; hostinfo->cpu_type = 0; for (i = 0; i < machine_info.max_cpus; i++) { - m = &machine_slot[i]; - if (!m->is_cpu) + if ((PerProcTable[i].ppe_vaddr == (struct per_proc_info *)NULL) || + !(PerProcTable[i].ppe_vaddr->running)) continue; hostinfo->cpus_mask |= (1 << i); if (hostinfo->cpu_type == 0) { - hostinfo->cpu_type = m->cpu_type; - hostinfo->cpu_subtype = m->cpu_subtype; + hostinfo->cpu_type = slot_type(i); + hostinfo->cpu_subtype = slot_subtype(i); } } } @@ -303,7 +443,12 @@ kdp_panic( void kdp_reboot(void) { - halt_all_cpus(TRUE);; + printf("Attempting system restart..."); + /* Call the platform specific restart*/ + if (PE_halt_restart) + (*PE_halt_restart)(kPERestartCPU); + /* If we do reach this, give up */ + halt_all_cpus(TRUE); } int @@ -421,7 +566,7 @@ kdp_trap( ) { unsigned int *fp; - unsigned int register sp; + unsigned int sp; struct savearea *state; if (kdp_noisy) { @@ -449,7 +594,7 @@ kdp_trap( if (kdp_noisy) printf("kdp_trap: kdp_raise_exception() ret\n"); - if (*((int *)saved_state->save_srr0) == 0x7c800008) + if ((unsigned int)(saved_state->save_srr0) == 0x7c800008) saved_state->save_srr0 += 4; /* BKPT_SIZE */ if(saved_state->save_srr1 & (MASK(MSR_SE) | MASK(MSR_BE))) { /* Are we just stepping or continuing */ @@ -497,7 +642,6 @@ kdp_print_backtrace( { extern void kdp_print_registers(struct savearea *); extern void print_backtrace(struct savearea *); - extern unsigned int debug_mode, disableDebugOuput; disableDebugOuput = FALSE; debug_mode = TRUE; @@ -509,7 +653,155 @@ kdp_print_backtrace( while(1); } -unsigned int kdp_ml_get_breakinsn() +unsigned int kdp_ml_get_breakinsn(void) { return 0x7fe00008; } +#define LR_OFFSET 8 +#define LR_OFFSET64 16 + +int +machine_trace_thread(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p) +{ + uint32_t *tracebuf = (uint32_t *)tracepos; + uint32_t fence = 0; + uint32_t stackptr = 0; + uint32_t stacklimit = 0xb0000000; + int framecount = 0; + uint32_t init_srr0 = 0; + uint32_t prevsp = 0; + uint32_t framesize = 2 * sizeof(vm_offset_t); + + if (user_p) { + /* Examine the user savearea */ + init_srr0 = thread->machine.upcb->save_srr0; + stackptr = thread->machine.upcb->save_r1; + /* This bound isn't useful, but it doesn't hinder us */ + stacklimit = 0xffffffff; + kdp_pmap = thread->task->map->pmap; + } + else { + stackptr = thread->machine.pcb->save_r1; + init_srr0 = thread->machine.pcb->save_srr0; + } + /* Fill in the "current" program counter */ + *tracebuf++ = init_srr0; + + for (framecount = 0; framecount < nframes; framecount++) { +/* Bounds check */ + if ((tracebound - ((uint32_t) tracebuf)) < (4 * framesize)) { + tracebuf--; + break; + } + + *tracebuf++ = stackptr; +/* Invalid frame, or hit fence */ + if (!stackptr || (stackptr == fence)) { + break; + } +/* Stack grows downward */ + if (stackptr < prevsp) { + break; + } +/* Unaligned frame */ + if (stackptr & 0x000000F) { + break; + } + if (stackptr > stacklimit) { + break; + } +/* Assume there's a saved link register, and read it */ + if (kdp_vm_read((caddr_t) (stackptr + LR_OFFSET), (caddr_t) tracebuf, sizeof(caddr_t)) != sizeof(caddr_t)) { + break; + } + + tracebuf++; + prevsp = stackptr; +/* Next frame */ + if (kdp_vm_read((caddr_t) stackptr, (caddr_t) &stackptr, sizeof(caddr_t)) != sizeof(caddr_t)) { + *tracebuf++ = 0; + break; + } + } +/* Reset the target pmap */ + kdp_pmap = 0; + return ((uint32_t) tracebuf - tracepos); +} + +/* Routine to encapsulate the 64-bit address read hack*/ +unsigned +machine_read64(addr64_t srcaddr, caddr_t dstaddr, uint32_t len) +{ + uint32_t kdp_vm_read_low32; + unsigned retval; + + kdp_src_high32 = srcaddr >> 32; + kdp_vm_read_low32 = srcaddr & 0x00000000FFFFFFFFUL; + retval = kdp_vm_read((caddr_t)kdp_vm_read_low32, dstaddr, len); + kdp_src_high32 = 0; + return retval; +} + +int +machine_trace_thread64(thread_t thread, uint32_t tracepos, uint32_t tracebound, int nframes, boolean_t user_p) +{ + uint64_t *tracebuf = (uint64_t *)tracepos; + uint32_t fence = 0; + addr64_t stackptr = 0; + uint64_t stacklimit = 0xb0000000; + int framecount = 0; + addr64_t init_srr0 = 0; + addr64_t prevsp = 0; + unsigned framesize = 2 * sizeof(addr64_t); + + if (user_p) { + init_srr0 = thread->machine.upcb->save_srr0; + stackptr = thread->machine.upcb->save_r1; + stacklimit = 0xffffffffffffffffULL; + kdp_pmap = thread->task->map->pmap; + } + else { + stackptr = thread->machine.pcb->save_r1; + init_srr0 = thread->machine.pcb->save_srr0; + } + + *tracebuf++ = init_srr0; + + for (framecount = 0; framecount < nframes; framecount++) { + + if ((tracebound - ((uint32_t) tracebuf)) < (4 * framesize)) { + tracebuf--; + break; + } + + *tracebuf++ = stackptr; + + if (!stackptr || (stackptr == fence)){ + break; + } + if (stackptr < prevsp) { + break; + } + if (stackptr & 0x000000F) { + break; + } + if (stackptr > stacklimit) { + break; + } + + if (machine_read64(stackptr+LR_OFFSET64, (caddr_t) tracebuf, sizeof(addr64_t)) != sizeof(addr64_t)) { + break; + } + tracebuf++; + + prevsp = stackptr; + if (machine_read64(stackptr, (caddr_t) &stackptr, sizeof(addr64_t)) != sizeof(addr64_t)) { + *tracebuf++ = 0; + break; + } + } + + kdp_pmap = 0; + + return ((uint32_t) tracebuf - tracepos); +}