|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * Copyright (c) 1997 Apple Computer, Inc. All rights reserved. ! 24: * Copyright (c) 1994 NeXT Computer, Inc. All rights reserved. ! 25: * ! 26: * machdep/ppc/kdp_machdep.c ! 27: * ! 28: * Machine-dependent code for Remote Debugging Protocol ! 29: * ! 30: * March, 1997 Created. Umesh Vaishampayan [[email protected]] ! 31: * ! 32: */ ! 33: ! 34: #include <mach/mach_types.h> ! 35: #include <mach/machine.h> ! 36: #include <mach/exception_types.h> ! 37: #include <i386/trap.h> ! 38: #include <kdp/kdp_internal.h> ! 39: ! 40: #define KDP_TEST_HARNESS 0 ! 41: #if KDP_TEST_HARNESS ! 42: #define dprintf(x) printf x ! 43: #else ! 44: #define dprintf(x) ! 45: #endif ! 46: ! 47: void print_saved_state(void *); ! 48: void kdp_call(void); ! 49: void kdp_i386_trap(unsigned int, struct i386_saved_state *, kern_return_t, vm_offset_t); ! 50: int kdp_getc(void); ! 51: ! 52: void ! 53: kdp_exception( ! 54: unsigned char *pkt, ! 55: int *len, ! 56: unsigned short *remote_port, ! 57: unsigned int exception, ! 58: unsigned int code, ! 59: unsigned int subcode ! 60: ) ! 61: { ! 62: kdp_exception_t *rq = (kdp_exception_t *)pkt; ! 63: ! 64: rq->hdr.request = KDP_EXCEPTION; ! 65: rq->hdr.is_reply = 0; ! 66: rq->hdr.seq = kdp.exception_seq; ! 67: rq->hdr.key = 0; ! 68: rq->hdr.len = sizeof (*rq); ! 69: ! 70: rq->n_exc_info = 1; ! 71: rq->exc_info[0].cpu = 0; ! 72: rq->exc_info[0].exception = exception; ! 73: rq->exc_info[0].code = code; ! 74: rq->exc_info[0].subcode = subcode; ! 75: ! 76: rq->hdr.len += rq->n_exc_info * sizeof (kdp_exc_info_t); ! 77: ! 78: bcopy((char *)rq, (char *)pkt, rq->hdr.len); ! 79: ! 80: kdp.exception_ack_needed = TRUE; ! 81: ! 82: *remote_port = kdp.exception_port; ! 83: *len = rq->hdr.len; ! 84: } ! 85: ! 86: boolean_t ! 87: kdp_exception_ack( ! 88: unsigned char *pkt, ! 89: int len ! 90: ) ! 91: { ! 92: kdp_exception_ack_t *rq = (kdp_exception_ack_t *)pkt; ! 93: ! 94: if (len < sizeof (*rq)) ! 95: return(FALSE); ! 96: ! 97: if (!rq->hdr.is_reply || rq->hdr.request != KDP_EXCEPTION) ! 98: return(FALSE); ! 99: ! 100: dprintf(("kdp_exception_ack seq %x %x\n", rq->hdr.seq, kdp.exception_seq)); ! 101: ! 102: if (rq->hdr.seq == kdp.exception_seq) { ! 103: kdp.exception_ack_needed = FALSE; ! 104: kdp.exception_seq++; ! 105: } ! 106: return(TRUE); ! 107: } ! 108: ! 109: void ! 110: kdp_getstate( ! 111: i386_thread_state_t *state ! 112: ) ! 113: { ! 114: struct i386_saved_state *saved_state; ! 115: ! 116: saved_state = (struct i386_saved_state *)kdp.saved_state; ! 117: ! 118: *state = (i386_thread_state_t) { 0 }; ! 119: state->eax = saved_state->eax; ! 120: state->ebx = saved_state->ebx; ! 121: state->ecx = saved_state->ecx; ! 122: state->edx = saved_state->edx; ! 123: state->edi = saved_state->edi; ! 124: state->esi = saved_state->esi; ! 125: state->ebp = saved_state->ebp; ! 126: ! 127: if ((saved_state->cs & 0x3) == 0){ /* Kernel State */ ! 128: state->esp = (unsigned int) &saved_state->uesp; ! 129: state->ss = KERNEL_DS; ! 130: } else { ! 131: state->esp = saved_state->uesp; ! 132: state->ss = saved_state->ss; ! 133: } ! 134: ! 135: state->eflags = saved_state->efl; ! 136: state->eip = saved_state->eip; ! 137: state->cs = saved_state->cs; ! 138: state->ds = saved_state->ds; ! 139: state->es = saved_state->es; ! 140: state->fs = saved_state->fs; ! 141: state->gs = saved_state->gs; ! 142: } ! 143: ! 144: ! 145: void ! 146: kdp_setstate( ! 147: i386_thread_state_t *state ! 148: ) ! 149: { ! 150: struct i386_saved_state *saved_state; ! 151: ! 152: saved_state = (struct i386_saved_state *)kdp.saved_state; ! 153: ! 154: saved_state->eax = state->eax; ! 155: saved_state->ebx = state->ebx; ! 156: saved_state->ecx = state->ecx; ! 157: saved_state->edx = state->edx; ! 158: saved_state->edi = state->edi; ! 159: saved_state->esi = state->esi; ! 160: saved_state->ebp = state->ebp; ! 161: saved_state->efl = state->eflags; ! 162: #if 0 ! 163: saved_state->frame.eflags &= ~( EFL_VM | EFL_NT | EFL_IOPL | EFL_CLR ); ! 164: saved_state->frame.eflags |= ( EFL_IF | EFL_SET ); ! 165: #endif ! 166: saved_state->eip = state->eip; ! 167: saved_state->fs = state->fs; ! 168: saved_state->gs = state->gs; ! 169: } ! 170: ! 171: ! 172: kdp_error_t ! 173: kdp_machine_read_regs( ! 174: unsigned int cpu, ! 175: unsigned int flavor, ! 176: char *data, ! 177: int *size ! 178: ) ! 179: { ! 180: switch (flavor) { ! 181: ! 182: case i386_THREAD_STATE: ! 183: dprintf(("kdp_readregs THREAD_STATE\n")); ! 184: kdp_getstate((i386_thread_state_t *)data); ! 185: *size = sizeof (i386_thread_state_t); ! 186: return KDPERR_NO_ERROR; ! 187: ! 188: case i386_THREAD_FPSTATE: ! 189: dprintf(("kdp_readregs THREAD_FPSTATE\n")); ! 190: *(i386_thread_fpstate_t *)data = (i386_thread_fpstate_t) { 0 }; ! 191: *size = sizeof (i386_thread_fpstate_t); ! 192: return KDPERR_NO_ERROR; ! 193: ! 194: default: ! 195: dprintf(("kdp_readregs bad flavor %d\n")); ! 196: return KDPERR_BADFLAVOR; ! 197: } ! 198: } ! 199: ! 200: kdp_error_t ! 201: kdp_machine_write_regs( ! 202: unsigned int cpu, ! 203: unsigned int flavor, ! 204: char *data, ! 205: int *size ! 206: ) ! 207: { ! 208: switch (flavor) { ! 209: ! 210: case i386_THREAD_STATE: ! 211: dprintf(("kdp_writeregs THREAD_STATE\n")); ! 212: kdp_setstate((i386_thread_state_t *)data); ! 213: return KDPERR_NO_ERROR; ! 214: ! 215: case i386_THREAD_FPSTATE: ! 216: dprintf(("kdp_writeregs THREAD_FPSTATE\n")); ! 217: return KDPERR_NO_ERROR; ! 218: ! 219: default: ! 220: dprintf(("kdp_writeregs bad flavor %d\n")); ! 221: return KDPERR_BADFLAVOR; ! 222: } ! 223: } ! 224: ! 225: ! 226: ! 227: void ! 228: kdp_machine_hostinfo( ! 229: kdp_hostinfo_t *hostinfo ! 230: ) ! 231: { ! 232: machine_slot_t m; ! 233: int i; ! 234: ! 235: hostinfo->cpus_mask = 0; ! 236: ! 237: for (i = 0; i < machine_info.max_cpus; i++) { ! 238: m = &machine_slot[i]; ! 239: if (!m->is_cpu) ! 240: continue; ! 241: ! 242: hostinfo->cpus_mask |= (1 << i); ! 243: } ! 244: ! 245: /* FIXME?? */ ! 246: hostinfo->cpu_type = CPU_TYPE_I386; ! 247: hostinfo->cpu_subtype = CPU_SUBTYPE_486; ! 248: } ! 249: ! 250: void ! 251: kdp_panic( ! 252: const char *msg ! 253: ) ! 254: { ! 255: printf("kdp panic: %s\n", msg); ! 256: __asm__ volatile("hlt"); ! 257: } ! 258: ! 259: ! 260: void ! 261: kdp_reboot(void) ! 262: { ! 263: kdreboot(); ! 264: } ! 265: ! 266: int ! 267: kdp_intr_disbl(void) ! 268: { ! 269: return splhigh(); ! 270: } ! 271: ! 272: void ! 273: kdp_intr_enbl(int s) ! 274: { ! 275: splx(s); ! 276: } ! 277: ! 278: int ! 279: kdp_getc() ! 280: { ! 281: return cnmaygetc(); ! 282: } ! 283: ! 284: void ! 285: kdp_us_spin(int usec) ! 286: { ! 287: extern void delay(int); ! 288: ! 289: delay(usec/100); ! 290: } ! 291: ! 292: void print_saved_state(void *state) ! 293: { ! 294: struct i386_saved_state *saved_state; ! 295: ! 296: saved_state = state; ! 297: ! 298: printf("pc = 0x%x\n", saved_state->eip); ! 299: printf("cr3= 0x%x\n", saved_state->cr2); ! 300: printf("rp = TODO FIXME\n"); ! 301: printf("sp = 0x%x\n", saved_state->esp); ! 302: ! 303: } ! 304: ! 305: void ! 306: kdp_sync_cache() ! 307: { ! 308: return; /* No op here. */ ! 309: } ! 310: ! 311: void ! 312: kdp_call() ! 313: { ! 314: __asm__ volatile ("int $3"); /* Let the processor do the work */ ! 315: } ! 316: ! 317: ! 318: typedef struct _cframe_t { ! 319: struct _cframe_t *prev; ! 320: unsigned caller; ! 321: unsigned args[0]; ! 322: } cframe_t; ! 323: ! 324: ! 325: #define MAX_FRAME_DELTA 65536 ! 326: ! 327: void ! 328: kdp_i386_backtrace(void *_frame, int nframes) ! 329: { ! 330: cframe_t *frame = (cframe_t *)_frame; ! 331: int i; ! 332: ! 333: for (i=0; i<nframes; i++) { ! 334: if ((vm_offset_t)frame < VM_MIN_KERNEL_ADDRESS || ! 335: (vm_offset_t)frame > VM_MAX_KERNEL_ADDRESS) { ! 336: goto invalid; ! 337: } ! 338: printf("frame %x called by %x ", ! 339: frame, frame->caller); ! 340: printf("args %x %x %x %x\n", ! 341: frame->args[0], frame->args[1], ! 342: frame->args[2], frame->args[3]); ! 343: if ((frame->prev < frame) || /* wrong direction */ ! 344: ((frame->prev - frame) > MAX_FRAME_DELTA)) { ! 345: goto invalid; ! 346: } ! 347: frame = frame->prev; ! 348: } ! 349: return; ! 350: invalid: ! 351: printf("invalid frame pointer %x\n",frame->prev); ! 352: } ! 353: ! 354: void ! 355: kdp_i386_trap( ! 356: unsigned int trapno, ! 357: struct i386_saved_state *saved_state, ! 358: kern_return_t result, ! 359: vm_offset_t va ! 360: ) ! 361: { ! 362: unsigned int exception, subcode = 0, code; ! 363: ! 364: if (trapno != T_INT3 && trapno != T_DEBUG) ! 365: printf("unexpected kernel trap %x eip %x\n", trapno, saved_state->eip); ! 366: ! 367: switch (trapno) { ! 368: ! 369: case T_DIVIDE_ERROR: ! 370: exception = EXC_ARITHMETIC; ! 371: code = EXC_I386_DIVERR; ! 372: break; ! 373: ! 374: case T_OVERFLOW: ! 375: exception = EXC_SOFTWARE; ! 376: code = EXC_I386_INTOFLT; ! 377: break; ! 378: ! 379: case T_OUT_OF_BOUNDS: ! 380: exception = EXC_ARITHMETIC; ! 381: code = EXC_I386_BOUNDFLT; ! 382: break; ! 383: ! 384: case T_INVALID_OPCODE: ! 385: exception = EXC_BAD_INSTRUCTION; ! 386: code = EXC_I386_INVOPFLT; ! 387: break; ! 388: ! 389: case T_SEGMENT_NOT_PRESENT: ! 390: exception = EXC_BAD_INSTRUCTION; ! 391: code = EXC_I386_SEGNPFLT; ! 392: subcode = saved_state->err; ! 393: break; ! 394: ! 395: case T_STACK_FAULT: ! 396: exception = EXC_BAD_INSTRUCTION; ! 397: code = EXC_I386_STKFLT; ! 398: subcode = saved_state->err; ! 399: break; ! 400: ! 401: case T_GENERAL_PROTECTION: ! 402: exception = EXC_BAD_INSTRUCTION; ! 403: code = EXC_I386_GPFLT; ! 404: subcode = saved_state->err; ! 405: break; ! 406: ! 407: case T_PAGE_FAULT: ! 408: exception = EXC_BAD_ACCESS; ! 409: code = result; ! 410: subcode = va; ! 411: break; ! 412: ! 413: case T_WATCHPOINT: ! 414: exception = EXC_SOFTWARE; ! 415: code = EXC_I386_ALIGNFLT; ! 416: break; ! 417: ! 418: case T_DEBUG: ! 419: case T_INT3: ! 420: exception = EXC_BREAKPOINT; ! 421: code = EXC_I386_BPTFLT; ! 422: break; ! 423: ! 424: default: ! 425: exception = EXC_BAD_INSTRUCTION; ! 426: code = trapno; ! 427: break; ! 428: } ! 429: ! 430: // kdp_i386_backtrace((void *) saved_state->ebp, 10); ! 431: ! 432: kdp_raise_exception(exception, code, subcode, saved_state); ! 433: } ! 434: ! 435: boolean_t ! 436: kdp_call_kdb( ! 437: void) ! 438: { ! 439: return(FALSE); ! 440: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.