|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: #include <debug.h> ! 26: #include <cpus.h> ! 27: #include <kern/thread.h> ! 28: #include <mach/exception.h> ! 29: #include <kern/syscall_sw.h> ! 30: #include <machdep/ppc/cpu_data.h> ! 31: #include <mach/thread_status.h> ! 32: #include <vm/vm_fault.h> ! 33: #include <vm/vm_kern.h> /* For kernel_map */ ! 34: #include <mach/vm_param.h> ! 35: #include <machdep/ppc/trap.h> ! 36: #include <machdep/ppc/exception.h> ! 37: #include <machdep/ppc/proc_reg.h> /* for SR_xxx definitions */ ! 38: #include <machdep/ppc/pmap.h> ! 39: #include <machine/label_t.h> ! 40: ! 41: #include <sys/param.h> ! 42: #include <sys/proc.h> ! 43: #include <sys/resourcevar.h> ! 44: ! 45: #include <machdep/ppc/ast.h> ! 46: extern void fpu_save(void); ! 47: #define NULL 0 ! 48: ! 49: #if DEBUG ! 50: #define TRAP_ALL -1 ! 51: #define TRAP_ALIGNMENT 0x01 ! 52: #define TRAP_DATA 0x02 ! 53: #define TRAP_INSTRUCTION 0x04 ! 54: #define TRAP_AST 0x08 ! 55: #define TRAP_TRACE 0x10 ! 56: #define TRAP_PROGRAM 0x20 ! 57: #define TRAP_EXCEPTION 0x40 ! 58: #define TRAP_UNRESOLVED 0x80 ! 59: #define TRAP_SYSCALL 0x100 /* all syscalls */ ! 60: #define TRAP_HW 0x200 /* all in hw_exception.s */ ! 61: #define TRAP_MACH_SYSCALL 0x400 ! 62: #define TRAP_SERVER_SYSCALL 0x800 ! 63: ! 64: int trapdebug=0; ! 65: ! 66: #define TRAP_DEBUG(LEVEL, A) {if ((trapdebug & LEVEL)==LEVEL){kprintf A;}} ! 67: #else ! 68: #define TRAP_DEBUG(LEVEL, A) ! 69: #endif ! 70: ! 71: /* ! 72: * XXX don't pass VM_PROT_EXECUTE to vm_fault(), execute permission is implied ! 73: * in either R or RW (note: the pmap module knows this). This is done for the ! 74: * benefit of programs that execute out of their data space (ala lisp). ! 75: * If we didn't do this in that scenerio, the ITLB miss code would call us ! 76: * and we would call vm_fault() with RX permission. However, the space was ! 77: * probably vm_allocate()ed with just RW and vm_fault would fail. The "right" ! 78: * solution to me is to have the un*x server always allocate data with RWX for ! 79: * compatibility with existing binaries. ! 80: */ ! 81: ! 82: #define PROT_EXEC (VM_PROT_READ) ! 83: #define PROT_RO (VM_PROT_READ) ! 84: #define PROT_RW (VM_PROT_READ|VM_PROT_WRITE) ! 85: ! 86: #define IS_KLOADED(pc) ((vm_offset_t)pc > VM_MIN_KERNEL_LOADED_ADDRESS) ! 87: ! 88: /* A useful macro to update the ppc_exception_state in the PCB ! 89: * before calling doexception ! 90: */ ! 91: #define UPDATE_PPC_EXCEPTION_STATE { \ ! 92: thread_t th = current_thread(); \ ! 93: struct ppc_exception_state *es = &th->pcb->es; \ ! 94: es->dar = dar; \ ! 95: es->dsisr = dsisr; \ ! 96: es->exception = trapno / EXC_VECTOR_SIZE; /* back to powerpc */ \ ! 97: } ! 98: ! 99: static void unresolved_kernel_trap(int trapno, ! 100: struct ppc_saved_state *ssp, ! 101: unsigned int dsisr, ! 102: unsigned int dar, ! 103: char *message); ! 104: ! 105: struct ppc_saved_state *trap(int trapno, ! 106: struct ppc_saved_state *ssp, ! 107: unsigned int dsisr, ! 108: unsigned int dar) ! 109: { ! 110: int exception=0; ! 111: int code; ! 112: int subcode; ! 113: vm_map_t map; ! 114: unsigned int sp; ! 115: unsigned int space,space2; ! 116: unsigned int offset; ! 117: thread_t th = current_thread(); ! 118: int error; ! 119: struct proc *p = th->task->proc; ! 120: struct timeval syst; ! 121: ! 122: TRAP_DEBUG(TRAP_ALL,("NMGS TRAP %d srr0=0x%08x, srr1=0x%08x\n", ! 123: trapno/4,ssp->srr0,ssp->srr1)); ! 124: ! 125: /* Handle kernel traps first */ ! 126: ! 127: if (!USER_MODE(ssp->srr1)) { ! 128: /* ! 129: * Trap came from system task, ie kernel or collocated server ! 130: */ ! 131: switch (trapno) { ! 132: /* ! 133: * These trap types should never be seen by trap() ! 134: * in kernel mode, anyway. ! 135: * Some are interrupts that should be seen by ! 136: * interrupt() others just don't happen because they ! 137: * are handled elsewhere. Some could happen but are ! 138: * considered to be fatal in kernel mode. ! 139: */ ! 140: case EXC_DECREMENTER: ! 141: case EXC_INVALID: ! 142: case EXC_RESET: ! 143: case EXC_MACHINE_CHECK: ! 144: case EXC_SYSTEM_MANAGEMENT: ! 145: case EXC_INTERRUPT: ! 146: case EXC_FP_UNAVAILABLE: ! 147: case EXC_IO_ERROR: ! 148: default: ! 149: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 150: break; ! 151: ! 152: case EXC_TRACE: ! 153: #if DEBUG ! 154: enter_debugger(trapno, dsisr, dar, ssp, 0); ! 155: #else ! 156: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 157: #endif ! 158: break; ! 159: ! 160: case EXC_RUNMODE_TRACE: ! 161: case EXC_INSTRUCTION_BKPT: ! 162: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 163: break; ! 164: ! 165: case EXC_PROGRAM: ! 166: if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) { ! 167: #if DEBUG ! 168: enter_debugger(trapno, dsisr, dar, ssp, 0); ! 169: #else ! 170: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 171: #endif /* DEBUG */ ! 172: } else { ! 173: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 174: } ! 175: break; ! 176: case EXC_ALIGNMENT: ! 177: TRAP_DEBUG(TRAP_ALIGNMENT, ! 178: ("NMGS KERNEL ALIGNMENT_ACCESS, " ! 179: "DAR=0x%08x, DSISR = 0x%08X\n", ! 180: dar, dsisr, ! 181: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 182: if (alignment(dsisr, dar, ssp)) { ! 183: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 184: } ! 185: break; ! 186: case EXC_DATA_ACCESS: ! 187: TRAP_DEBUG(TRAP_DATA, ! 188: ("NMGS KERNEL DATA_ACCESS, DAR=0x%08x," ! 189: "DSISR = 0x%08X\n", dar, dsisr, ! 190: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 191: ! 192: if (dsisr & MASK(DSISR_WATCH)) { ! 193: printf("dabr "); ! 194: #if DEBUG ! 195: enter_debugger(trapno, dsisr,dar,ssp, 1); ! 196: #else ! 197: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 198: #endif ! 199: break; ! 200: } ! 201: /* simple case : not SR_COPYIN segment, from kernel */ ! 202: if ((dar >> 28) != SR_COPYIN) { ! 203: /* if from kloaded task, use task mapping */ ! 204: #if notdef_next /* NeXT kernloaded modules use the kernel map */ ! 205: if(IS_KLOADED(ssp->srr0)) ! 206: map = th->task->map; ! 207: else ! 208: #endif /* notdef_next */ ! 209: map = kernel_map; ! 210: ! 211: offset = dar; ! 212: TRAP_DEBUG(TRAP_DATA, ! 213: ("SYSTEM FAULT FROM 0x%08x\n", ! 214: offset)); ! 215: code = vm_fault(map, ! 216: trunc_page(offset), ! 217: dsisr & MASK(DSISR_WRITE) ? ! 218: PROT_RW : PROT_RO, ! 219: FALSE, ! 220: &error); ! 221: if (code != KERN_SUCCESS) { ! 222: #if DEBUG ! 223: if (th->recover) { ! 224: label_t *l = (label_t *)th->recover; ! 225: th->recover = (vm_offset_t)NULL; ! 226: longjmp(l,1); ! 227: } else { ! 228: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 229: } ! 230: #else ! 231: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 232: #endif ! 233: } ! 234: break; ! 235: } ! 236: ! 237: /* If we get here, the fault was due to a copyin/out */ ! 238: ! 239: map = th->task->map; ! 240: ! 241: /* Mask out SR_COPYIN and mask in original segment */ ! 242: ! 243: offset = (dar & 0x0fffffff) | ! 244: ((mfsrin(dar) & 0xF) << 28); ! 245: ! 246: TRAP_DEBUG(TRAP_DATA, ! 247: ("sr=0x%08x, dar=0x%08x, sp=0x%x\n", ! 248: mfsrin(dar), dar,map->pmap->space)); ! 249: assert(((mfsrin(dar) & 0x0FFFFFFF) >> 4) == ! 250: map->pmap->space); ! 251: TRAP_DEBUG(TRAP_DATA, ! 252: ("KERNEL FAULT FROM 0x%x,0x%08x\n", ! 253: map->pmap->space, offset)); ! 254: ! 255: code = vm_fault(map, ! 256: trunc_page(offset), ! 257: dsisr & MASK(DSISR_WRITE) ? ! 258: PROT_RW : PROT_RO, ! 259: FALSE, ! 260: &error); ! 261: ! 262: /* If we failed, there should be a recovery ! 263: * spot to rfi to. ! 264: */ ! 265: if (code != KERN_SUCCESS) { ! 266: TRAP_DEBUG(TRAP_DATA, ! 267: ("FAULT FAILED- srr0=0x%08x," ! 268: "pcb-srr0=0x%08x\n", ! 269: ssp->srr0, ! 270: th->pcb->ss.srr0)); ! 271: ! 272: if (th->recover) { ! 273: label_t *l = (label_t *)th->recover; ! 274: th->recover = (vm_offset_t)NULL; ! 275: longjmp(l, 1); ! 276: } else { ! 277: unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point"); ! 278: } ! 279: } ! 280: break; ! 281: ! 282: case EXC_INSTRUCTION_ACCESS: ! 283: /* Colocated tasks aren't necessarily wired and ! 284: * may page fault ! 285: */ ! 286: TRAP_DEBUG(TRAP_INSTRUCTION, ! 287: ("NMGS KERNEL INSTRUCTION ACCESS," ! 288: "DSISR = 0x%B\n", dsisr, ! 289: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 290: ! 291: #if DEBUG ! 292: enter_debugger(trapno, dsisr,dar,ssp, 1); ! 293: #else ! 294: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 295: #endif ! 296: #if 0 ! 297: /* Make sure it's not the kernel itself faulting */ ! 298: assert ((ssp->srr0 >= VM_MIN_KERNEL_LOADED_ADDRESS) && ! 299: (ssp->srr0 < VM_MAX_KERNEL_LOADED_ADDRESS)); ! 300: ! 301: /* Same as for data access, except fault type ! 302: * is PROT_EXEC and addr comes from srr0 ! 303: */ ! 304: map = th->task->map; ! 305: space = PPC_SID_KERNEL; ! 306: ! 307: code = vm_fault(map, trunc_page(ssp->srr0), ! 308: PROT_EXEC, FALSE, ! 309: &error); ! 310: if (code != KERN_SUCCESS) { ! 311: TRAP_DEBUG(TRAP_INSTRUCTION, ! 312: ("INSTR FAULT FAILED!\n")); ! 313: exception = EXC_BAD_ACCESS; ! 314: subcode = ssp->srr0; ! 315: } ! 316: #endif ! 317: break; ! 318: ! 319: case EXC_AST: ! 320: TRAP_DEBUG(TRAP_AST, ! 321: ("EXC_AST FROM KERNEL MODE\n")); ! 322: check_for_ast(); ! 323: break; ! 324: } ! 325: } else { ! 326: /* ! 327: * Trap came from user task ! 328: */ ! 329: ! 330: if (p) ! 331: syst = p->p_stats->p_ru.ru_stime; ! 332: ! 333: ! 334: switch (trapno) { ! 335: /* ! 336: * These trap types should never be seen by trap() ! 337: * Some are interrupts that should be seen by ! 338: * interrupt() others just don't happen because they ! 339: * are handled elsewhere. ! 340: */ ! 341: case EXC_DECREMENTER: ! 342: case EXC_INVALID: ! 343: case EXC_MACHINE_CHECK: ! 344: case EXC_INTERRUPT: ! 345: case EXC_FP_UNAVAILABLE: ! 346: case EXC_SYSTEM_MANAGEMENT: ! 347: case EXC_IO_ERROR: ! 348: ! 349: default: ! 350: panic("Unexpected exception type, %d 0x%x", trapno, trapno); ! 351: break; ! 352: ! 353: case EXC_RESET: ! 354: powermac_reboot(); /* never returns */ ! 355: ! 356: case EXC_ALIGNMENT: ! 357: TRAP_DEBUG(TRAP_ALIGNMENT, ! 358: ("NMGS USER ALIGNMENT_ACCESS, " ! 359: "DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr, ! 360: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 361: if (alignment(dsisr, dar, ssp)) { ! 362: code = EXC_PPC_UNALIGNED; ! 363: exception = EXC_BAD_ACCESS; ! 364: subcode = dar; ! 365: } ! 366: break; ! 367: ! 368: case EXC_TRACE: /* Real PPC chips */ ! 369: case EXC_INSTRUCTION_BKPT: /* 603 PPC chips */ ! 370: case EXC_RUNMODE_TRACE: /* 601 PPC chips */ ! 371: TRAP_DEBUG(TRAP_TRACE,("NMGS TRACE TRAP\n")); ! 372: exception = EXC_BREAKPOINT; ! 373: code = EXC_PPC_TRACE; ! 374: subcode = ssp->srr0; ! 375: break; ! 376: ! 377: case EXC_PROGRAM: ! 378: TRAP_DEBUG(TRAP_PROGRAM, ! 379: ("NMGS PROGRAM TRAP\n")); ! 380: if (ssp->srr1 & MASK(SRR1_PRG_FE)) { ! 381: TRAP_DEBUG(TRAP_PROGRAM, ! 382: ("FP EXCEPTION\n")); ! 383: fpu_save(); ! 384: fpu_disable(); ! 385: UPDATE_PPC_EXCEPTION_STATE; ! 386: exception = EXC_ARITHMETIC; ! 387: code = EXC_ARITHMETIC; ! 388: subcode = per_proc_info[cpu_number()]. ! 389: fpu_pcb->fs.fpscr; ! 390: } else if (ssp->srr1 & MASK(SRR1_PRG_ILL_INS)) { ! 391: TRAP_DEBUG(TRAP_PROGRAM, ! 392: ("ILLEGAL INSTRUCTION\n")); ! 393: ! 394: UPDATE_PPC_EXCEPTION_STATE ! 395: exception = EXC_BAD_INSTRUCTION; ! 396: code = EXC_PPC_UNIPL_INST; ! 397: subcode = ssp->srr0; ! 398: } else if (ssp->srr1 & MASK(SRR1_PRG_PRV_INS)) { ! 399: TRAP_DEBUG(TRAP_PROGRAM, ! 400: ("PRIVILEGED INSTRUCTION\n")); ! 401: ! 402: UPDATE_PPC_EXCEPTION_STATE; ! 403: exception = EXC_BAD_INSTRUCTION; ! 404: code = EXC_PPC_PRIVINST; ! 405: subcode = ssp->srr0; ! 406: } else if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) { ! 407: #if MACH_KGDB ! 408: /* Give kernel debugger a chance to ! 409: * claim the breakpoint before passing ! 410: * it up as an exception ! 411: */ ! 412: if (kgdb_user_breakpoint(ssp)) { ! 413: call_kgdb_with_ctx(EXC_PROGRAM, ! 414: 0, ! 415: ssp); ! 416: break; ! 417: } ! 418: #endif /* MACH_KGDB */ ! 419: ! 420: UPDATE_PPC_EXCEPTION_STATE; ! 421: exception = EXC_BREAKPOINT; ! 422: code = EXC_PPC_BREAKPOINT; ! 423: subcode = ssp->srr0; ! 424: } ! 425: break; ! 426: ! 427: case EXC_DATA_ACCESS: ! 428: TRAP_DEBUG(TRAP_DATA, ! 429: ("NMGS USER DATA_ACCESS, DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 430: ! 431: if (dsisr & MASK(DSISR_WATCH)) { ! 432: printf("dabr "); ! 433: #if DEBUG ! 434: enter_debugger(trapno, dsisr,dar,ssp, 1); ! 435: #else ! 436: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 437: #endif ! 438: break; ! 439: } ! 440: map = th->task->map; ! 441: space = map->pmap->space; ! 442: assert(space != 0); ! 443: #if DEBUG ! 444: mfsr(space2, SR_UNUSED_BY_KERN); ! 445: space2 = (space2 >> 4) & 0x00FFFFFF; ! 446: ! 447: /* Do a check that at least SR_UNUSED_BY_KERN ! 448: * is in the correct user space. ! 449: * TODO NMGS may not be true as ints are on?. ! 450: */ ! 451: assert(space2 == space); ! 452: #if 0 ! 453: TRAP_DEBUG(TRAP_DATA,("map = 0x%08x, space=0x%08x, addr=0x%08x\n",map, space, trunc_page(dar)); ! 454: #endif ! 455: #endif /* DEBUG */ ! 456: ! 457: code = vm_fault(map, trunc_page(dar), ! 458: dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO, ! 459: FALSE, ! 460: &error); ! 461: if (code != KERN_SUCCESS) { ! 462: TRAP_DEBUG(TRAP_DATA,("FAULT FAILED!\n")); ! 463: UPDATE_PPC_EXCEPTION_STATE; ! 464: exception = EXC_BAD_ACCESS; ! 465: subcode = dar; ! 466: } ! 467: break; ! 468: ! 469: case EXC_INSTRUCTION_ACCESS: ! 470: TRAP_DEBUG(TRAP_INSTRUCTION,("NMGS USER INSTRUCTION ACCESS, DSISR = 0x%B\n", dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 471: ! 472: /* Same as for data access, except fault type ! 473: * is PROT_EXEC and addr comes from srr0 ! 474: */ ! 475: map = th->task->map; ! 476: space = map->pmap->space; ! 477: assert(space != 0); ! 478: #if DEBUG ! 479: mfsr(space2, SR_UNUSED_BY_KERN); ! 480: space2 = (space2 >> 4) & 0x00FFFFFF; ! 481: ! 482: /* Do a check that at least SR_UNUSED_BY_KERN ! 483: * is in the correct user space. ! 484: * TODO NMGS is this always true now ints are on? ! 485: */ ! 486: assert(space2 == space); ! 487: #endif /* DEBUG */ ! 488: ! 489: code = vm_fault(map, trunc_page(ssp->srr0), ! 490: PROT_EXEC, FALSE, ! 491: &error); ! 492: if (code != KERN_SUCCESS) { ! 493: TRAP_DEBUG(TRAP_INSTRUCTION, ! 494: ("INSTR FAULT FAILED!\n")); ! 495: UPDATE_PPC_EXCEPTION_STATE; ! 496: exception = EXC_BAD_ACCESS; ! 497: subcode = ssp->srr0; ! 498: } ! 499: break; ! 500: ! 501: case EXC_AST: ! 502: TRAP_DEBUG(TRAP_AST,("EXC_AST FROM USER MODE\n")); ! 503: check_for_ast(); ! 504: break; ! 505: ! 506: } ! 507: } ! 508: ! 509: if (exception) { ! 510: TRAP_DEBUG(TRAP_EXCEPTION, ! 511: ("doexception (0x%x, 0x%x, 0x%x, 0x%x, pc = 0x%x in %s)\n", ! 512: exception,code,subcode, th, th->pcb->ss.srr0, ! 513: &th->task->proc->p_comm)); ! 514: doexception(exception, code, subcode, th); ! 515: return ssp; ! 516: } ! 517: ! 518: if (USER_MODE(ssp->srr1)) { ! 519: if (p && (p->p_flag & P_PROFIL)) { ! 520: int ticks; ! 521: struct timeval *tv = &p->p_stats->p_ru.ru_stime; ! 522: ! 523: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + ! 524: (tv->tv_usec - syst.tv_usec) / 1000) / ! 525: (tick / 1000); ! 526: if (ticks) ! 527: addupc_task(p, ssp->srr0, ticks); ! 528: } ! 529: } ! 530: return ssp; ! 531: } ! 532: ! 533: #if MACH_ASSERT ! 534: /* This routine is called from assembly before each and every system call ! 535: * iff MACH_ASSERT is defined. It must preserve r3. ! 536: */ ! 537: ! 538: extern int syscall_trace(int, struct ppc_saved_state *); ! 539: ! 540: int syscall_trace(int retval, struct ppc_saved_state *ssp) ! 541: { ! 542: int i, argc; ! 543: ! 544: if (trapdebug & TRAP_SYSCALL) ! 545: trapdebug |= (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL); ! 546: ! 547: if (!(trapdebug & (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL))) ! 548: return retval; ! 549: if (ssp->r0 & 0x80000000) { ! 550: /* Mach trap */ ! 551: if (!(trapdebug & TRAP_MACH_SYSCALL)) ! 552: return retval; ! 553: ! 554: printf("0x%08x : %30s (", ! 555: ssp->srr0, mach_trap_table[-(ssp->r0)].mach_trap_name); ! 556: argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count; ! 557: for (i = 0; i < argc; i++) ! 558: printf("%08x ",*(&ssp->r3 + i)); ! 559: printf(")\n"); ! 560: } else { ! 561: if (!(trapdebug & TRAP_SERVER_SYSCALL)) ! 562: return retval; ! 563: printf("0x%08x : RHAPSODY %3d (", ssp->srr0, ssp->r0); ! 564: argc = 4; /* print 4 of 'em! */ ! 565: for (i = 0; i < argc; i++) ! 566: printf("%08x ",*(&ssp->r3 + i)); ! 567: printf(")\n"); ! 568: } ! 569: return retval; ! 570: } ! 571: #endif /* MACH_ASSERT */ ! 572: ! 573: /* ! 574: * called from syscall if there is an error ! 575: */ ! 576: ! 577: int syscall_error( ! 578: int exception, ! 579: int code, ! 580: int subcode, ! 581: struct ppc_saved_state *ssp) ! 582: { ! 583: register thread_t thread; ! 584: ! 585: thread = current_thread(); ! 586: ! 587: if (thread == 0) ! 588: panic("syscall error in boot phase"); ! 589: ! 590: if (!USER_MODE(ssp->srr1)) ! 591: panic("system call called from kernel"); ! 592: ! 593: doexception(exception, code, subcode, thread); ! 594: ! 595: return 0; ! 596: } ! 597: ! 598: /* Pass up a server syscall/exception */ ! 599: void ! 600: doexception( ! 601: int exc, ! 602: int code, ! 603: int sub, ! 604: thread_t th) ! 605: { ! 606: exception(exc, code, sub); ! 607: } ! 608: ! 609: char *trap_type[] = { ! 610: "0x0000 INVALID EXCEPTION", ! 611: "0x0100 System reset", ! 612: "0x0200 Machine check", ! 613: "0x0300 Data access", ! 614: "0x0400 Instruction access", ! 615: "0x0500 External interrupt", ! 616: "0x0600 Alignment", ! 617: "0x0700 Program", ! 618: "0x0800 Floating point", ! 619: "0x0900 Decrementer", ! 620: "0x0A00 I/O controller interface", ! 621: "0x0B00 INVALID EXCEPTION", ! 622: "0x0C00 System call exception", ! 623: "0x0D00 Trace", ! 624: "0x0E00 FP assist", ! 625: "0x0F00 Performance monitoring", ! 626: "0x1000 Instruction PTE miss", ! 627: "0x1100 Data load PTE miss", ! 628: "0x1200 Data store PTE miss", ! 629: "0x1300 Instruction Breakpoint", ! 630: "0x1400 System Management", ! 631: "0x1500 INVALID EXCEPTION", ! 632: "0x1600 INVALID EXCEPTION", ! 633: "0x1700 INVALID EXCEPTION", ! 634: "0x1800 INVALID EXCEPTION", ! 635: "0x1900 INVALID EXCEPTION", ! 636: "0x1A00 INVALID EXCEPTION", ! 637: "0x1B00 INVALID EXCEPTION", ! 638: "0x1C00 INVALID EXCEPTION", ! 639: "0x1D00 INVALID EXCEPTION", ! 640: "0x1E00 INVALID EXCEPTION", ! 641: "0x1F00 INVALID EXCEPTION", ! 642: "0x2000 Run Mode/Trace" ! 643: "0x2100 INVALID EXCEPTION", ! 644: "0x2200 INVALID EXCEPTION", ! 645: "0x2300 INVALID EXCEPTION", ! 646: "0x2400 INVALID EXCEPTION", ! 647: "0x2500 INVALID EXCEPTION", ! 648: "0x2600 INVALID EXCEPTION", ! 649: "0x2700 INVALID EXCEPTION", ! 650: "0x2800 INVALID EXCEPTION", ! 651: "0x2900 INVALID EXCEPTION", ! 652: "0x2A00 INVALID EXCEPTION", ! 653: "0x2B00 INVALID EXCEPTION", ! 654: "0x2C00 INVALID EXCEPTION", ! 655: "0x2D00 INVALID EXCEPTION", ! 656: "0x2E00 INVALID EXCEPTION", ! 657: "0x2F00 INVALID EXCEPTION", ! 658: }; ! 659: ! 660: void unresolved_kernel_trap(int trapno, ! 661: struct ppc_saved_state *ssp, ! 662: unsigned int dsisr, ! 663: unsigned int dar, ! 664: char *message) ! 665: { ! 666: char *trap_name; ! 667: ! 668: #if notdef_next ! 669: if(IS_KLOADED(ssp->srr0)) { ! 670: int exception; ! 671: ! 672: TRAP_DEBUG(TRAP_UNRESOLVED, ! 673: ("unresolved trap %d in kernel loaded task %d\n",trapno)); ! 674: TRAP_DEBUG(TRAP_UNRESOLVED, ! 675: ("%s: sending exception message\n", message)); ! 676: switch(trapno) { ! 677: case EXC_INVALID: ! 678: case EXC_RESET: ! 679: case EXC_MACHINE_CHECK: ! 680: case EXC_INTERRUPT: ! 681: case EXC_DECREMENTER: ! 682: case EXC_IO_ERROR: ! 683: case EXC_SYSTEM_CALL: ! 684: case EXC_RUNMODE_TRACE: ! 685: default: ! 686: exception = EXC_BREAKPOINT; ! 687: break; ! 688: case EXC_ALIGNMENT: ! 689: case EXC_INSTRUCTION_ACCESS: ! 690: case EXC_DATA_ACCESS: ! 691: exception = EXC_BAD_ACCESS; ! 692: break; ! 693: case EXC_PROGRAM: ! 694: exception = EXC_BAD_INSTRUCTION; ! 695: break; ! 696: case EXC_FP_UNAVAILABLE: ! 697: /* TODO NMGS - should this generate EXC_ARITHMETIC?*/ ! 698: exception = EXC_ARITHMETIC; ! 699: break; ! 700: } ! 701: UPDATE_PPC_EXCEPTION_STATE; ! 702: doexception(exception, 0, 0, current_thread()); ! 703: return; ! 704: } ! 705: #if DEBUG ! 706: regDump(ssp); ! 707: #endif /* DEBUG */ ! 708: #endif /* notdef_next */ ! 709: ! 710: if ((unsigned)trapno <= EXC_MAX) ! 711: trap_name = trap_type[trapno / EXC_VECTOR_SIZE]; ! 712: else ! 713: trap_name = "???? unrecognised exception"; ! 714: if (message == NULL) ! 715: message = trap_name; ! 716: ! 717: /* no KGDB so display a backtrace */ ! 718: printf("\n\nUnresolved kernel trap: %s DSISR=0x%08x DAR=0x%08x\n", ! 719: trap_name, dsisr, dar); ! 720: ! 721: #ifdef DEBUG ! 722: enter_debugger(trapno, dsisr, dar, ssp, 1); ! 723: #else ! 724: { ! 725: unsigned int* stackptr; ! 726: int i; ! 727: printf("generating stack backtrace prior to panic:\n\n"); ! 728: ! 729: printf("backtrace: 0x%08x ", ssp->srr0); ! 730: ! 731: stackptr = (unsigned int *)(ssp->r1); ! 732: ! 733: for (i = 0; i < 8; i++) { ! 734: ! 735: /* Avoid causing page fault */ ! 736: if (pmap_extract(kernel_pmap, (vm_offset_t)stackptr) == 0) ! 737: break; ! 738: ! 739: stackptr = (unsigned int*)*stackptr; ! 740: /* ! 741: * TODO NMGS - use FM_LR_SAVE constant, but asm.h defines ! 742: * too much (such as r1, used above) ! 743: */ ! 744: ! 745: /* Avoid causing page fault */ ! 746: if (pmap_extract(kernel_pmap, (vm_offset_t)stackptr+2) == 0) ! 747: break; ! 748: ! 749: printf("0x%08x ",*(stackptr + 2)); ! 750: } ! 751: printf("\n\n"); ! 752: } ! 753: #endif ! 754: ! 755: panic(message); ! 756: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.