|
|
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: * @OSF_COPYRIGHT@ ! 24: */ ! 25: ! 26: #include <mach_kdb.h> ! 27: #include <mach_kdp.h> ! 28: #include <debug.h> ! 29: #include <cpus.h> ! 30: #include <kern/thread.h> ! 31: #include <kern/exception.h> ! 32: #include <kern/syscall_sw.h> ! 33: #include <kern/cpu_data.h> ! 34: #include <kern/debug.h> ! 35: #include <mach/thread_status.h> ! 36: #include <vm/vm_fault.h> ! 37: #include <vm/vm_kern.h> /* For kernel_map */ ! 38: #include <ppc/misc_protos.h> ! 39: #include <ppc/trap.h> ! 40: #include <ppc/exception.h> ! 41: #include <ppc/proc_reg.h> /* for SR_xxx definitions */ ! 42: #include <ppc/pmap.h> ! 43: #include <ppc/mem.h> ! 44: #include <ppc/fpu_protos.h> ! 45: ! 46: #include <sys/kdebug.h> ! 47: ! 48: #if MACH_KDB ! 49: #include <ddb/db_watch.h> ! 50: #include <ddb/db_run.h> ! 51: #include <ddb/db_break.h> ! 52: #include <ddb/db_trap.h> ! 53: ! 54: boolean_t let_ddb_vm_fault = FALSE; ! 55: boolean_t debug_all_traps_with_kdb = FALSE; ! 56: extern struct db_watchpoint *db_watchpoint_list; ! 57: extern boolean_t db_watchpoints_inserted; ! 58: extern boolean_t db_breakpoints_inserted; ! 59: ! 60: ! 61: #endif /* MACH_KDB */ ! 62: ! 63: extern int debugger_active[NCPUS]; ! 64: ! 65: #if DEBUG || MACH_ASSERT ! 66: #define TRAP_ALL -1 ! 67: #define TRAP_ALIGNMENT 0x01 ! 68: #define TRAP_DATA 0x02 ! 69: #define TRAP_INSTRUCTION 0x04 ! 70: #define TRAP_AST 0x08 ! 71: #define TRAP_TRACE 0x10 ! 72: #define TRAP_PROGRAM 0x20 ! 73: #define TRAP_EXCEPTION 0x40 ! 74: #define TRAP_UNRESOLVED 0x80 ! 75: #define TRAP_SYSCALL 0x100 /* all syscalls */ ! 76: #define TRAP_HW 0x200 /* all in hw_exception.s */ ! 77: #define TRAP_MACH_SYSCALL 0x400 ! 78: #define TRAP_SERVER_SYSCALL 0x800 ! 79: ! 80: int trapdebug=0; /* TRAP_SERVER_SYSCALL;*/ ! 81: ! 82: #define TRAP_DEBUG(LEVEL, A) {if ((trapdebug & LEVEL)==LEVEL){printf A;}} ! 83: #else ! 84: #define TRAP_DEBUG(LEVEL, A) ! 85: #endif ! 86: ! 87: /* ! 88: * XXX don't pass VM_PROT_EXECUTE to vm_fault(), execute permission is implied ! 89: * in either R or RW (note: the pmap module knows this). This is done for the ! 90: * benefit of programs that execute out of their data space (ala lisp). ! 91: * If we didn't do this in that scenerio, the ITLB miss code would call us ! 92: * and we would call vm_fault() with RX permission. However, the space was ! 93: * probably vm_allocate()ed with just RW and vm_fault would fail. The "right" ! 94: * solution to me is to have the un*x server always allocate data with RWX for ! 95: * compatibility with existing binaries. ! 96: */ ! 97: ! 98: #define PROT_EXEC (VM_PROT_READ) ! 99: #define PROT_RO (VM_PROT_READ) ! 100: #define PROT_RW (VM_PROT_READ|VM_PROT_WRITE) ! 101: ! 102: /* A useful macro to update the ppc_exception_state in the PCB ! 103: * before calling doexception ! 104: */ ! 105: #define UPDATE_PPC_EXCEPTION_STATE { \ ! 106: thread_act_t thr_act = current_act(); \ ! 107: struct ppc_exception_state *es = &thr_act->mact.pcb->es; \ ! 108: es->dar = dar; \ ! 109: es->dsisr = dsisr; \ ! 110: es->exception = trapno / T_VECTOR_SIZE; /* back to powerpc */ \ ! 111: } ! 112: ! 113: static void unresolved_kernel_trap(int trapno, ! 114: struct ppc_saved_state *ssp, ! 115: unsigned int dsisr, ! 116: unsigned int dar, ! 117: char *message); ! 118: ! 119: struct ppc_saved_state *trap(int trapno, ! 120: struct ppc_saved_state *ssp, ! 121: unsigned int dsisr, ! 122: unsigned int dar) ! 123: { ! 124: int exception=0; ! 125: int code; ! 126: int subcode; ! 127: vm_map_t map; ! 128: unsigned int sp; ! 129: unsigned int space,space2; ! 130: unsigned int offset; ! 131: thread_act_t thr_act = current_act(); ! 132: #ifdef MACH_BSD ! 133: time_value_t tv; ! 134: #endif /* MACH_BSD */ ! 135: ! 136: ! 137: TRAP_DEBUG(TRAP_ALL,("NMGS TRAP %d srr0=0x%08x, srr1=0x%08x\n", ! 138: trapno/4,ssp->srr0,ssp->srr1)); ! 139: ! 140: #if DEBUG ! 141: { ! 142: /* make sure we're not near to overflowing kernel stack */ ! 143: int sp; ! 144: mp_disable_preemption(); /* Make sure we don't preempt */ ! 145: #ifdef __ELF__ ! 146: __asm__ volatile("mr %0, 1" : "=r" (sp)); ! 147: #else ! 148: __asm__ volatile("mr %0, r1" : "=r" (sp)); ! 149: #endif ! 150: if (sp < ! 151: (cpu_data[cpu_number()].active_thread->kernel_stack + ! 152: sizeof(struct ppc_saved_state)+256)) { ! 153: printf("TRAP - LOW ON KERNEL STACK!\n"); ! 154: } ! 155: mp_enable_preemption(); /* Preemption is cool now */ ! 156: } ! 157: #endif /* DEBUG */ ! 158: /* Handle kernel traps first */ ! 159: ! 160: if (!USER_MODE(ssp->srr1)) { ! 161: /* ! 162: * Trap came from system task, ie kernel or collocated server ! 163: */ ! 164: switch (trapno) { ! 165: ! 166: case T_PREEMPT: /* Handle a preempt trap */ ! 167: mp_disable_preemption(); /* since preemption is not enabled */ ! 168: ast_off(AST_URGENT); /* clear urgent and let it sched */ ! 169: mp_enable_preemption(); /* normally... */ ! 170: break; /* Do nothing, just check... */ ! 171: ! 172: /* ! 173: * These trap types should never be seen by trap() ! 174: * in kernel mode, anyway. ! 175: * Some are interrupts that should be seen by ! 176: * interrupt() others just don't happen because they ! 177: * are handled elsewhere. Some could happen but are ! 178: * considered to be fatal in kernel mode. ! 179: */ ! 180: case T_DECREMENTER: ! 181: case T_IN_VAIN: /* Shouldn't ever see this, lowmem_vectors eats it */ ! 182: case T_RESET: ! 183: case T_MACHINE_CHECK: ! 184: case T_SYSTEM_MANAGEMENT: ! 185: case T_ALTIVEC_ASSIST: ! 186: case T_INTERRUPT: ! 187: case T_FP_UNAVAILABLE: ! 188: case T_IO_ERROR: ! 189: case T_RESERVED: ! 190: default: ! 191: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 192: break; ! 193: ! 194: case T_TRACE: ! 195: case T_RUNMODE_TRACE: ! 196: case T_INSTRUCTION_BKPT: ! 197: #if MACH_KDP || MACH_KDB ! 198: if (!Call_Debugger(trapno, ssp)) ! 199: #endif ! 200: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 201: break; ! 202: ! 203: case T_PROGRAM: ! 204: if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) { ! 205: #if MACH_KDP || MACH_KDB ! 206: if (!Call_Debugger(trapno, ssp)) ! 207: #endif ! 208: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 209: } else { ! 210: unresolved_kernel_trap(trapno, ssp, ! 211: dsisr, dar, NULL); ! 212: } ! 213: break; ! 214: case T_ALIGNMENT: ! 215: TRAP_DEBUG(TRAP_ALIGNMENT, ! 216: ("NMGS KERNEL ALIGNMENT_ACCESS, " ! 217: "DAR=0x%08x, DSISR = 0x%B\n", ! 218: dar, dsisr, ! 219: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 220: if (alignment(dsisr, dar, ssp)) { ! 221: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 222: } ! 223: break; ! 224: case T_DATA_ACCESS: ! 225: TRAP_DEBUG(TRAP_DATA, ! 226: ("NMGS KERNEL DATA_ACCESS, DAR=0x%08x," ! 227: "DSISR = 0x%B\n", dar, dsisr, ! 228: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 229: ! 230: #if MACH_KDB ! 231: mp_disable_preemption(); ! 232: if (debug_mode ! 233: #if NCPUS > 1 ! 234: && debugger_active[cpu_number()] ! 235: #endif /* NCPUS > 1 */ ! 236: && !let_ddb_vm_fault) { ! 237: /* ! 238: * Force kdb to handle this one. ! 239: */ ! 240: kdb_trap(trapno, ssp); ! 241: } ! 242: mp_enable_preemption(); ! 243: #endif /* MACH_KDB */ ! 244: ! 245: /* simple case : not SR_COPYIN segment, from kernel */ ! 246: if ((dar >> 28) != SR_COPYIN_NUM) { ! 247: map = kernel_map; ! 248: ! 249: offset = dar; ! 250: ! 251: ! 252: /* ! 253: * Note: Some ROM device drivers will access page 0 when they start. The IOKit will ! 254: * set a flag to tell us to ignore any access fault on page 0. After the driver is ! 255: * opened, it will clear the flag. ! 256: */ ! 257: if((0 == (dar & -PAGE_SIZE)) && /* Check for access of page 0 and */ ! 258: ((thr_act->mact.specFlags) & ignoreZeroFault)) { ! 259: /* special case of ignoring page zero faults */ ! 260: ssp->srr0 += 4; /* Point to next instruction */ ! 261: break; ! 262: } ! 263: ! 264: TRAP_DEBUG(TRAP_DATA, ! 265: ("SYSTEM FAULT FROM 0x%08x\n", ! 266: offset)); ! 267: ! 268: code = vm_fault(map, ! 269: trunc_page(offset), ! 270: dsisr & MASK(DSISR_WRITE) ? ! 271: PROT_RW : PROT_RO, ! 272: FALSE); ! 273: if (code != KERN_SUCCESS) { ! 274: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 275: } ! 276: else { ! 277: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */ ! 278: ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */ ! 279: } ! 280: break; ! 281: } ! 282: ! 283: /* If we get here, the fault was due to a copyin/out */ ! 284: ! 285: map = thr_act->map; ! 286: ! 287: /* Mask out SR_COPYIN and mask in original segment */ ! 288: ! 289: offset = (dar & 0x0fffffff) | ! 290: ((mfsrin(dar)<<8) & 0xF0000000); ! 291: ! 292: TRAP_DEBUG(TRAP_DATA, ! 293: ("sr=0x%08x, dar=0x%08x, sp=0x%x\n", ! 294: mfsrin(dar), dar,map->pmap->space)); ! 295: assert((mfsrin(dar) & 0x000FFFFF) == ! 296: map->pmap->space); ! 297: TRAP_DEBUG(TRAP_DATA, ! 298: ("KERNEL FAULT FROM 0x%x,0x%08x\n", ! 299: map->pmap->space, offset)); ! 300: ! 301: code = vm_fault(map, ! 302: trunc_page(offset), ! 303: dsisr & MASK(DSISR_WRITE) ? ! 304: PROT_RW : PROT_RO, ! 305: FALSE); ! 306: ! 307: /* If we failed, there should be a recovery ! 308: * spot to rfi to. ! 309: */ ! 310: if (code != KERN_SUCCESS) { ! 311: TRAP_DEBUG(TRAP_DATA, ! 312: ("FAULT FAILED- srr0=0x%08x," ! 313: "pcb-srr0=0x%08x\n", ! 314: ssp->srr0, ! 315: thr_act->mact.pcb->ss.srr0)); ! 316: ! 317: if (thr_act->thread->recover) { ! 318: ! 319: #if 0 ! 320: __asm__ volatile("tweq r1,r1"); /* (TEST/DEBUG) */ ! 321: #endif ! 322: ! 323: act_lock_thread(thr_act); ! 324: ssp->srr0 = thr_act->thread->recover; ! 325: thr_act->thread->recover = ! 326: (vm_offset_t)NULL; ! 327: act_unlock_thread(thr_act); ! 328: } else { ! 329: unresolved_kernel_trap(trapno, ssp, dsisr, dar, "copyin/out has no recovery point"); ! 330: } ! 331: } ! 332: else { ! 333: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */ ! 334: ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */ ! 335: } ! 336: ! 337: break; ! 338: ! 339: case T_INSTRUCTION_ACCESS: ! 340: ! 341: TRAP_DEBUG(TRAP_INSTRUCTION, ! 342: ("NMGS KERNEL INSTRUCTION ACCESS," ! 343: "DSISR = 0x%B\n", dsisr, ! 344: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 345: ! 346: #if MACH_KDB ! 347: if (debug_mode ! 348: #if NCPUS > 1 ! 349: && debugger_active[cpu_number()] ! 350: #endif /* NCPUS > 1 */ ! 351: && !let_ddb_vm_fault) { ! 352: /* ! 353: * Force kdb to handle this one. ! 354: */ ! 355: kdb_trap(trapno, ssp); ! 356: } ! 357: #endif /* MACH_KDB */ ! 358: ! 359: /* Same as for data access, except fault type ! 360: * is PROT_EXEC and addr comes from srr0 ! 361: */ ! 362: map = thr_act->map; ! 363: ! 364: code = vm_fault(map, trunc_page(ssp->srr0), ! 365: PROT_EXEC, FALSE); ! 366: if (code != KERN_SUCCESS) { ! 367: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 368: } ! 369: else { ! 370: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */ ! 371: ssp->srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */ ! 372: } ! 373: break; ! 374: ! 375: /* Usually shandler handles all the system calls, but the ! 376: * atomic thread switcher may throwup (via thandler) and ! 377: * have to pass it up to the exception handler. ! 378: */ ! 379: ! 380: case T_SYSTEM_CALL: ! 381: unresolved_kernel_trap(trapno, ssp, dsisr, dar, NULL); ! 382: break; ! 383: ! 384: case T_AST: ! 385: TRAP_DEBUG(TRAP_AST, ! 386: ("T_AST FROM KERNEL MODE\n")); ! 387: ast_taken(FALSE, AST_ALL, 0); ! 388: break; ! 389: } ! 390: } else { ! 391: #ifdef MACH_BSD ! 392: { ! 393: void get_procrustime(time_value_t *); ! 394: ! 395: get_procrustime(&tv); ! 396: } ! 397: #endif /* MACH_BSD */ ! 398: ! 399: ! 400: /* ! 401: * Trap came from user task ! 402: */ ! 403: ! 404: switch (trapno) { ! 405: case T_PREEMPT: /* Handle a preempt trap */ ! 406: break; /* Do nothing, just check... */ ! 407: ! 408: /* ! 409: * These trap types should never be seen by trap() ! 410: * Some are interrupts that should be seen by ! 411: * interrupt() others just don't happen because they ! 412: * are handled elsewhere. ! 413: */ ! 414: case T_DECREMENTER: ! 415: case T_IN_VAIN: /* Shouldn't ever see this, lowmem_vectors eats it */ ! 416: case T_MACHINE_CHECK: ! 417: case T_INTERRUPT: ! 418: case T_FP_UNAVAILABLE: ! 419: case T_SYSTEM_MANAGEMENT: ! 420: case T_RESERVED: ! 421: case T_IO_ERROR: ! 422: ! 423: default: ! 424: panic("Unexpected exception type"); ! 425: break; ! 426: ! 427: case T_RESET: ! 428: halt_all_cpus(TRUE); /* never returns */ ! 429: ! 430: case T_ALIGNMENT: ! 431: TRAP_DEBUG(TRAP_ALIGNMENT, ! 432: ("NMGS USER ALIGNMENT_ACCESS, " ! 433: "DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr, ! 434: "\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 435: if (alignment(dsisr, dar, ssp)) { ! 436: code = EXC_PPC_UNALIGNED; ! 437: exception = EXC_BAD_ACCESS; ! 438: subcode = dar; ! 439: } ! 440: break; ! 441: ! 442: case T_TRACE: /* Real PPC chips */ ! 443: case T_INSTRUCTION_BKPT: /* 603 PPC chips */ ! 444: case T_RUNMODE_TRACE: /* 601 PPC chips */ ! 445: TRAP_DEBUG(TRAP_TRACE,("NMGS TRACE TRAP\n")); ! 446: ! 447: exception = EXC_BREAKPOINT; ! 448: code = EXC_PPC_TRACE; ! 449: subcode = ssp->srr0; ! 450: break; ! 451: ! 452: case T_PROGRAM: ! 453: TRAP_DEBUG(TRAP_PROGRAM, ! 454: ("NMGS PROGRAM TRAP\n")); ! 455: if (ssp->srr1 & MASK(SRR1_PRG_FE)) { ! 456: TRAP_DEBUG(TRAP_PROGRAM, ! 457: ("FP EXCEPTION\n")); ! 458: fpu_save(); ! 459: UPDATE_PPC_EXCEPTION_STATE; ! 460: exception = EXC_ARITHMETIC; ! 461: code = EXC_ARITHMETIC; ! 462: ! 463: mp_disable_preemption(); ! 464: subcode = current_act()->mact.FPU_pcb->fs.fpscr; ! 465: mp_enable_preemption(); ! 466: } ! 467: else if (ssp->srr1 & MASK(SRR1_PRG_ILL_INS)) { ! 468: ! 469: TRAP_DEBUG(TRAP_PROGRAM, ! 470: ("ILLEGAL INSTRUCTION\n")); ! 471: ! 472: UPDATE_PPC_EXCEPTION_STATE ! 473: exception = EXC_BAD_INSTRUCTION; ! 474: code = EXC_PPC_UNIPL_INST; ! 475: subcode = ssp->srr0; ! 476: } else if (ssp->srr1 & MASK(SRR1_PRG_PRV_INS)) { ! 477: TRAP_DEBUG(TRAP_PROGRAM, ! 478: ("PRIVILEGED INSTRUCTION\n")); ! 479: ! 480: UPDATE_PPC_EXCEPTION_STATE; ! 481: exception = EXC_BAD_INSTRUCTION; ! 482: code = EXC_PPC_PRIVINST; ! 483: subcode = ssp->srr0; ! 484: } else if (ssp->srr1 & MASK(SRR1_PRG_TRAP)) { ! 485: unsigned int inst; ! 486: ! 487: if (copyin((char *) ssp->srr0, (char *) &inst, 4 )) ! 488: panic("copyin failed\n"); ! 489: UPDATE_PPC_EXCEPTION_STATE; ! 490: if (inst == 0x7FE00008) { ! 491: exception = EXC_BREAKPOINT; ! 492: code = EXC_PPC_BREAKPOINT; ! 493: } else { ! 494: exception = EXC_SOFTWARE; ! 495: code = EXC_PPC_TRAP; ! 496: } ! 497: subcode = ssp->srr0; ! 498: } ! 499: break; ! 500: ! 501: case T_ALTIVEC_ASSIST: ! 502: UPDATE_PPC_EXCEPTION_STATE; ! 503: exception = EXC_ARITHMETIC; ! 504: code = EXC_PPC_ALTIVECASSIST; ! 505: subcode = ssp->srr0; ! 506: break; ! 507: ! 508: case T_DATA_ACCESS: ! 509: TRAP_DEBUG(TRAP_DATA, ! 510: ("NMGS USER DATA_ACCESS, DAR=0x%08x, DSISR = 0x%B\n", dar, dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 511: ! 512: map = thr_act->map; ! 513: ! 514: code = vm_fault(map, trunc_page(dar), ! 515: dsisr & MASK(DSISR_WRITE) ? PROT_RW : PROT_RO, ! 516: FALSE); ! 517: if (code != KERN_SUCCESS) { ! 518: ! 519: TRAP_DEBUG(TRAP_DATA,("FAULT FAILED!\n")); ! 520: UPDATE_PPC_EXCEPTION_STATE; ! 521: exception = EXC_BAD_ACCESS; ! 522: subcode = dar; ! 523: } ! 524: else { ! 525: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */ ! 526: ((savearea *)ssp)->save_dsisr |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */ ! 527: } ! 528: break; ! 529: ! 530: case T_INSTRUCTION_ACCESS: ! 531: TRAP_DEBUG(TRAP_INSTRUCTION,("NMGS USER INSTRUCTION ACCESS, DSISR = 0x%B\n", dsisr,"\20\2HASH\5PROT\6IO_SPC\7WRITE\12WATCH\14EIO")); ! 532: ! 533: /* Same as for data access, except fault type ! 534: * is PROT_EXEC and addr comes from srr0 ! 535: */ ! 536: map = thr_act->map; ! 537: ! 538: code = vm_fault(map, trunc_page(ssp->srr0), ! 539: PROT_EXEC, FALSE); ! 540: if (code != KERN_SUCCESS) { ! 541: ! 542: ! 543: TRAP_DEBUG(TRAP_INSTRUCTION, ! 544: ("INSTR FAULT FAILED!\n")); ! 545: UPDATE_PPC_EXCEPTION_STATE; ! 546: exception = EXC_BAD_ACCESS; ! 547: subcode = ssp->srr0; ! 548: } ! 549: else { ! 550: ((savearea *)ssp)->save_flags |= SAVredrive; /* Tell low-level to re-try fault */ ! 551: ssp->srr1 |= MASK(DSISR_HASH); /* Make sure this is marked as a miss */ ! 552: } ! 553: break; ! 554: ! 555: case T_AST: ! 556: TRAP_DEBUG(TRAP_AST,("T_AST FROM USER MODE\n")); ! 557: ast_taken(FALSE, AST_ALL, 0); ! 558: break; ! 559: ! 560: } ! 561: #ifdef MACH_BSD ! 562: { ! 563: void bsd_uprofil(time_value_t *, unsigned int); ! 564: ! 565: bsd_uprofil(&tv, ssp->srr0); ! 566: } ! 567: #endif /* MACH_BSD */ ! 568: } ! 569: ! 570: if (exception) { ! 571: TRAP_DEBUG(TRAP_EXCEPTION, ! 572: ("doexception (0x%x, 0x%x, 0x%x\n", ! 573: exception,code,subcode)); ! 574: ! 575: #if 0 ! 576: __asm__ volatile("tweq r1,r1"); /* (TEST/DEBUG) */ ! 577: #endif ! 578: ! 579: doexception(exception, code, subcode); ! 580: return ssp; ! 581: } ! 582: /* AST delivery ! 583: * Check to see if we need an AST, if so take care of it here ! 584: */ ! 585: ! 586: mp_disable_preemption(); /* We can't preempt here */ ! 587: while (ast_needed(cpu_number()) && USER_MODE(ssp->srr1)) { ! 588: mp_enable_preemption(); /* ast_taken doesn't expect preemption disabled */ ! 589: ast_taken(FALSE, AST_ALL, 0); ! 590: mp_disable_preemption(); /* Disable pretemption for check */ ! 591: } ! 592: mp_enable_preemption(); /* Preemption be cool again */ ! 593: ! 594: return ssp; ! 595: } ! 596: ! 597: /* This routine is called from assembly before each and every system call. ! 598: * It must preserve r3. ! 599: */ ! 600: ! 601: extern int syscall_trace(int, struct ppc_saved_state *); ! 602: ! 603: ! 604: extern int pmdebug; ! 605: ! 606: int syscall_trace(int retval, struct ppc_saved_state *ssp) ! 607: { ! 608: int i, argc; ! 609: ! 610: int kdarg[3]; ! 611: /* Always prepare to trace mach system calls */ ! 612: if (kdebug_enable && (ssp->r0 & 0x80000000)) { ! 613: /* Mach trap */ ! 614: kdarg[0]=0; ! 615: kdarg[1]=0; ! 616: kdarg[2]=0; ! 617: argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count; ! 618: if (argc > 3) ! 619: argc = 3; ! 620: for (i=0; i < argc; i++) ! 621: kdarg[i] = (int)*(&ssp->r3 + i); ! 622: KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC, (-(ssp->r0))) | DBG_FUNC_START, ! 623: kdarg[0], kdarg[1], kdarg[2], 0, 0); ! 624: } ! 625: ! 626: #if MACH_ASSERT ! 627: if (trapdebug & TRAP_SYSCALL) ! 628: trapdebug |= (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL); ! 629: ! 630: if (!(trapdebug & (TRAP_MACH_SYSCALL|TRAP_SERVER_SYSCALL))) ! 631: return retval; ! 632: if (ssp->r0 & 0x80000000) { ! 633: /* Mach trap */ ! 634: if (!(trapdebug & TRAP_MACH_SYSCALL)) ! 635: return retval; ! 636: ! 637: printf("0x%08x : %30s (", ! 638: ssp->srr0, mach_trap_table[-(ssp->r0)].mach_trap_name); ! 639: argc = mach_trap_table[-(ssp->r0)].mach_trap_arg_count; ! 640: for (i = 0; i < argc; i++) ! 641: printf("%08x ",*(&ssp->r3 + i)); ! 642: printf(")\n"); ! 643: } else { ! 644: if (!(trapdebug & TRAP_SERVER_SYSCALL)) ! 645: return retval; ! 646: printf("0x%08x : UNIX %3d (", ssp->srr0, ssp->r0); ! 647: argc = 4; /* print 4 of 'em! */ ! 648: for (i = 0; i < argc; i++) ! 649: printf("%08x ",*(&ssp->r3 + i)); ! 650: printf(")\n"); ! 651: } ! 652: #endif /* MACH_ASSERT */ ! 653: return retval; ! 654: } ! 655: ! 656: /* This routine is called from assembly after each mach system call ! 657: * It must preserve r3. ! 658: */ ! 659: ! 660: extern int syscall_trace_end(int, struct ppc_saved_state *); ! 661: ! 662: int syscall_trace_end(int retval, struct ppc_saved_state *ssp) ! 663: { ! 664: if (kdebug_enable && (ssp->r0 & 0x80000000)) { ! 665: /* Mach trap */ ! 666: KERNEL_DEBUG_CONSTANT(MACHDBG_CODE(DBG_MACH_EXCP_SC,(-(ssp->r0))) | DBG_FUNC_END, ! 667: retval, 0, 0, 0, 0); ! 668: } ! 669: return retval; ! 670: } ! 671: ! 672: /* ! 673: * called from syscall if there is an error ! 674: */ ! 675: ! 676: int syscall_error( ! 677: int exception, ! 678: int code, ! 679: int subcode, ! 680: struct ppc_saved_state *ssp) ! 681: { ! 682: register thread_t thread; ! 683: ! 684: thread = current_thread(); ! 685: ! 686: if (thread == 0) ! 687: panic("syscall error in boot phase"); ! 688: ! 689: if (!USER_MODE(ssp->srr1)) ! 690: panic("system call called from kernel"); ! 691: ! 692: doexception(exception, code, subcode); ! 693: ! 694: return 0; ! 695: } ! 696: ! 697: /* Pass up a server syscall/exception */ ! 698: void ! 699: doexception( ! 700: int exc, ! 701: int code, ! 702: int sub) ! 703: { ! 704: exception_data_type_t codes[EXCEPTION_CODE_MAX]; ! 705: ! 706: codes[0] = code; ! 707: codes[1] = sub; ! 708: exception(exc, codes, 2); ! 709: } ! 710: ! 711: char *trap_type[] = { ! 712: "0x000 Interrupt in vain", ! 713: "0x100 System reset", ! 714: "0x200 Machine check", ! 715: "0x300 Data access", ! 716: "0x400 Instruction access", ! 717: "0x500 External interrupt", ! 718: "0x600 Alignment", ! 719: "0x700 Program", ! 720: "0x800 Floating point", ! 721: "0x900 Decrementer", ! 722: "0xA00 I/O controller interface", ! 723: "0xB00 INVALID EXCEPTION", ! 724: "0xC00 System call exception", ! 725: "0xD00 Trace", ! 726: "0xE00 FP assist", ! 727: "0xF20 VMX", ! 728: "0xF00 INVALID EXCEPTION", ! 729: "0x1000 Instruction PTE miss", ! 730: "0x1100 Data load PTE miss", ! 731: "0x1200 Data store PTE miss", ! 732: "0x1300 Instruction Breakpoint", ! 733: "0x1400 System Management", ! 734: "0x1500 INVALID EXCEPTION", ! 735: "0x1600 Altivec Assist", ! 736: "0x1700 INVALID EXCEPTION", ! 737: "0x1800 INVALID EXCEPTION", ! 738: "0x1900 INVALID EXCEPTION", ! 739: "0x1A00 INVALID EXCEPTION", ! 740: "0x1B00 INVALID EXCEPTION", ! 741: "0x1C00 INVALID EXCEPTION", ! 742: "0x1D00 INVALID EXCEPTION", ! 743: "0x1E00 INVALID EXCEPTION", ! 744: "0x1F00 INVALID EXCEPTION", ! 745: "0x2000 Run Mode/Trace" ! 746: }; ! 747: int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]); ! 748: ! 749: void unresolved_kernel_trap(int trapno, ! 750: struct ppc_saved_state *ssp, ! 751: unsigned int dsisr, ! 752: unsigned int dar, ! 753: char *message) ! 754: { ! 755: unsigned int* stackptr; ! 756: char *trap_name; ! 757: int i, lr; ! 758: extern void print_backtrace(struct ppc_saved_state *); ! 759: extern unsigned int debug_mode, disableDebugOuput; ! 760: ! 761: disableDebugOuput = FALSE; ! 762: debug_mode++; ! 763: if ((unsigned)trapno <= T_MAX) ! 764: trap_name = trap_type[trapno / T_VECTOR_SIZE]; ! 765: else ! 766: trap_name = "???? unrecognized exception"; ! 767: if (message == NULL) ! 768: message = trap_name; ! 769: ! 770: printf("\n\nUnresolved kernel trap: %s DSISR=0x%08x DAR=0x%08x PC=0x%08x\n" ! 771: "generating stack backtrace prior to panic:\n\n", ! 772: trap_name, dsisr, dar, ssp->srr0); ! 773: ! 774: printf("backtrace: %08x ", ssp->srr0); ! 775: ! 776: stackptr = (unsigned int *)(ssp->r1); ! 777: ! 778: #ifdef __ELF__ ! 779: lr = 1; ! 780: #else ! 781: lr = 2; ! 782: #endif ! 783: ! 784: print_backtrace(ssp); ! 785: ! 786: #if MACH_KDB || MACH_KDP ! 787: (void *)Call_Debugger(trapno, ssp); ! 788: #endif ! 789: panic(message); ! 790: } ! 791: ! 792: #if MACH_KDB ! 793: void ! 794: thread_kdb_return(void) ! 795: { ! 796: register thread_act_t thr_act = current_act(); ! 797: register thread_t cur_thr = current_thread(); ! 798: register struct ppc_saved_state *regs = USER_REGS(thr_act); ! 799: ! 800: Call_Debugger(thr_act->mact.pcb->es.exception, regs); ! 801: #if MACH_LDEBUG ! 802: assert(cur_thr->mutex_count == 0); ! 803: #endif /* MACH_LDEBUG */ ! 804: check_simple_locks(); ! 805: thread_exception_return(); ! 806: /*NOTREACHED*/ ! 807: } ! 808: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.