|
|
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: /* ! 26: * Copyright (c) 1992 NeXT Computer, Inc. ! 27: * ! 28: * Intel386 Family: Trap handlers. ! 29: * ! 30: * HISTORY ! 31: * ! 32: * 13 April 1992 ? at NeXT ! 33: * Created. ! 34: */ ! 35: ! 36: #import <gdb.h> ! 37: ! 38: #import <mach/mach_types.h> ! 39: #import <mach/exception.h> ! 40: ! 41: #import <kern/syscall_sw.h> ! 42: #import <kern/kdp.h> ! 43: ! 44: #import <vm/vm_kern.h> ! 45: ! 46: #import <machdep/i386/trap.h> ! 47: #import <machdep/i386/machdep_call.h> ! 48: #import <machdep/i386/cpu_inline.h> ! 49: #import <machdep/i386/fp_exported.h> ! 50: #import <machdep/i386/sel_inline.h> ! 51: #import <machdep/i386/err_inline.h> ! 52: ! 53: #import <sys/kernel.h> ! 54: #import <sys/systm.h> ! 55: #import <sys/proc.h> ! 56: #import <sys/user.h> ! 57: #import <sys/syslog.h> ! 58: ! 59: #define N_BACKTRACE 4 // number of backtrace frames to print ! 60: ! 61: static ! 62: void ! 63: kernel_debug_trap( ! 64: thread_saved_state_t *saved_state ! 65: ); ! 66: static ! 67: kern_return_t ! 68: kernel_pagefault( ! 69: vm_offset_t address, ! 70: except_frame_t *frame ! 71: ); ! 72: static ! 73: boolean_t ! 74: kernel_try_recover( ! 75: except_frame_t *frame ! 76: ); ! 77: static ! 78: void ! 79: kernel_recover_thread( ! 80: thread_saved_state_t *saved_state ! 81: ); ! 82: ! 83: void ! 84: _i386_backtrace( ! 85: void *frame, ! 86: int nframes ! 87: ); ! 88: ! 89: void ! 90: user_trap( ! 91: thread_saved_state_t *state ! 92: ) ! 93: { ! 94: except_frame_t *frame = &state->frame; ! 95: int trapno; ! 96: thread_t thread; ! 97: int _exception, code = 0, subcode = 0; ! 98: vm_offset_t va; ! 99: kern_return_t result; ! 100: int uerror; ! 101: struct proc *p; ! 102: struct timeval syst; ! 103: ! 104: thread = current_thread(); ! 105: trapno = state->trapno; ! 106: ! 107: if (p = current_proc()) ! 108: syst = p->p_stats->p_ru.ru_stime; ! 109: ! 110: switch (trapno) { ! 111: ! 112: case T_ZERO_DIVIDE: ! 113: _exception = EXC_ARITHMETIC; ! 114: code = EXC_I386_ZERO_DIVIDE; ! 115: break; ! 116: ! 117: case T_DEBUG: ! 118: _exception = EXC_BREAKPOINT; ! 119: code = EXC_I386_DEBUG; ! 120: break; ! 121: ! 122: case T_BREAKPOINT: ! 123: _exception = EXC_BREAKPOINT; ! 124: code = EXC_I386_BREAKPOINT; ! 125: break; ! 126: ! 127: case T_OVERFLOW: ! 128: _exception = EXC_SOFTWARE; ! 129: code = EXC_I386_OVERFLOW; ! 130: break; ! 131: ! 132: case T_BOUNDS_CHECK: ! 133: _exception = EXC_SOFTWARE; ! 134: code = EXC_I386_BOUNDS_CHECK; ! 135: break; ! 136: ! 137: case T_INVALID_OPCODE: ! 138: _exception = EXC_BAD_INSTRUCTION; ! 139: code = EXC_I386_INVALID_OPCODE; ! 140: break; ! 141: ! 142: case T_NOEXTENSION: ! 143: fp_noextension(state); ! 144: goto out; ! 145: ! 146: case T_SEGMENT_NOTPRESENT: ! 147: _exception = EXC_BAD_INSTRUCTION; ! 148: code = EXC_I386_SEGMENT_NOTPRESENT; ! 149: subcode = err_to_error_code(frame->err); ! 150: break; ! 151: ! 152: case T_STACK_EXCEPTION: ! 153: _exception = EXC_BAD_INSTRUCTION; ! 154: code = EXC_I386_STACK_EXCEPTION; ! 155: subcode = err_to_error_code(frame->err); ! 156: break; ! 157: ! 158: case T_GENERAL_PROTECTION: ! 159: _exception = EXC_BAD_INSTRUCTION; ! 160: code = EXC_I386_GENERAL_PROTECTION; ! 161: subcode = err_to_error_code(frame->err); ! 162: break; ! 163: ! 164: case T_PAGE_FAULT: ! 165: va = cr2(); ! 166: result = vm_fault(thread->task->map, trunc_page(va), ! 167: frame->err.pgfault.wrtflt? ! 168: VM_PROT_READ | VM_PROT_WRITE: ! 169: VM_PROT_READ, ! 170: FALSE, 0); ! 171: if (result == KERN_SUCCESS) ! 172: goto out; ! 173: ! 174: _exception = EXC_BAD_ACCESS; ! 175: code = result; ! 176: subcode = va; ! 177: break; ! 178: ! 179: case T_EXTENSION_FAULT: ! 180: fp_extension_fault(state); ! 181: goto out; ! 182: ! 183: case T_ALIGNMENT_CHECK: ! 184: _exception = EXC_SOFTWARE; ! 185: code = EXC_I386_ALIGNMENT_CHECK; ! 186: break; ! 187: ! 188: default: ! 189: _exception = EXC_BAD_INSTRUCTION; ! 190: code = trapno; ! 191: break; ! 192: } ! 193: ! 194: exception(_exception, code, subcode); ! 195: /* NOTREACHED */ ! 196: ! 197: out: ! 198: if (p && (p->p_flag & P_PROFIL)) { ! 199: int ticks; ! 200: struct timeval *tv = &p->p_stats->p_ru.ru_stime; ! 201: ! 202: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + ! 203: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); ! 204: if (ticks) ! 205: addupc_task(p, frame->eip, ticks); ! 206: } ! 207: ! 208: thread_exception_return(); ! 209: /* NOTREACHED */ ! 210: } ! 211: ! 212: void ! 213: kernel_trap( ! 214: thread_saved_state_t *state ! 215: ) ! 216: { ! 217: except_frame_t *frame = &state->frame; ! 218: int trapno; ! 219: vm_offset_t va; ! 220: int _exception, code = 0, subcode = 0; ! 221: kern_return_t result; ! 222: int uerror; ! 223: ! 224: trapno = state->trapno; ! 225: ! 226: switch (trapno) { ! 227: ! 228: case T_NOEXTENSION: ! 229: /* ignore exception */; ! 230: return; ! 231: ! 232: case T_EXTENSION_FAULT: ! 233: fp_kernel_extension_fault(state); ! 234: return; ! 235: ! 236: case T_DEBUG: ! 237: case T_BREAKPOINT: ! 238: kernel_debug_trap(state); ! 239: return; ! 240: ! 241: case T_PAGE_FAULT: ! 242: va = cr2(); ! 243: ! 244: if (va >= KERNEL_LINEAR_BASE) ! 245: result = kernel_pagefault(va, frame); ! 246: else ! 247: result = vm_fault(current_task()->map, trunc_page(va), ! 248: frame->err.pgfault.wrtflt? ! 249: VM_PROT_READ | VM_PROT_WRITE: ! 250: VM_PROT_READ, ! 251: FALSE, 0); ! 252: ! 253: if (result == KERN_SUCCESS) ! 254: return; ! 255: ! 256: if (kernel_try_recover(frame)) ! 257: return; ! 258: ! 259: if (va < KERNEL_LINEAR_BASE) { ! 260: /* ! 261: * This can happen on return to user mode ! 262: * when a private thread LDT contains ! 263: * unallocated virtual memory. Send an ! 264: * exception RPC, after carefully piecing ! 265: * the thread state back together. ! 266: */ ! 267: kernel_recover_thread(state); ! 268: ! 269: _exception = EXC_BAD_ACCESS; ! 270: code = result; ! 271: subcode = va; ! 272: exception_from_kernel(_exception, code, subcode); ! 273: thread_exception_return(); ! 274: /* NOTREACHED */ ! 275: } ! 276: break; ! 277: ! 278: case T_GENERAL_PROTECTION: ! 279: case T_SEGMENT_NOTPRESENT: ! 280: case T_STACK_EXCEPTION: ! 281: if (frame->err.normal.tbl == ERR_LDT) { ! 282: /* ! 283: * This can happen on return to user mode ! 284: * when one of the segment registers refers ! 285: * to a descriptor that is invalid for some ! 286: * reason or another. Send an exception RPC, ! 287: * after carefully piecing the thread state ! 288: * back together. ! 289: */ ! 290: kernel_recover_thread(state); ! 291: ! 292: _exception = EXC_BAD_INSTRUCTION; ! 293: code = trapno; ! 294: subcode = err_to_error_code(frame->err); ! 295: exception_from_kernel(_exception, code, subcode); ! 296: thread_exception_return(); ! 297: /* NOTREACHED */ ! 298: } ! 299: break; ! 300: ! 301: case T_INVALID_TSS: ! 302: if ((frame->eflags & EFL_NT) != 0) { ! 303: /* ! 304: * This can happen on return to user mode ! 305: * when a thread managed to set the NT flag ! 306: * and then entered the kernel through a call ! 307: * gate. The fix is to redo the IRET, since ! 308: * the NT flag cannot be set at this point (we ! 309: * just came through a trap gate to get here). ! 310: */ ! 311: kernel_recover_thread(state); ! 312: thread_exception_return(); ! 313: /* NOTREACHED */ ! 314: } ! 315: break; ! 316: } ! 317: ! 318: if (kernel_try_recover(frame)) ! 319: return; ! 320: ! 321: #if GDB ! 322: DoSafeAlert("Kernel Trap", "", FALSE); ! 323: printf("unexpected kernel trap %x eip %x\n", trapno, frame->eip); ! 324: switch (trapno) { ! 325: ! 326: case T_ZERO_DIVIDE: ! 327: _exception = EXC_ARITHMETIC; ! 328: code = EXC_I386_ZERO_DIVIDE; ! 329: break; ! 330: ! 331: case T_OVERFLOW: ! 332: _exception = EXC_SOFTWARE; ! 333: code = EXC_I386_OVERFLOW; ! 334: break; ! 335: ! 336: case T_BOUNDS_CHECK: ! 337: _exception = EXC_ARITHMETIC; ! 338: code = EXC_I386_BOUNDS_CHECK; ! 339: break; ! 340: ! 341: case T_INVALID_OPCODE: ! 342: _exception = EXC_BAD_INSTRUCTION; ! 343: code = EXC_I386_INVALID_OPCODE; ! 344: break; ! 345: ! 346: case T_SEGMENT_NOTPRESENT: ! 347: _exception = EXC_BAD_INSTRUCTION; ! 348: code = EXC_I386_SEGMENT_NOTPRESENT; ! 349: subcode = err_to_error_code(frame->err); ! 350: break; ! 351: ! 352: case T_STACK_EXCEPTION: ! 353: _exception = EXC_BAD_INSTRUCTION; ! 354: code = EXC_I386_STACK_EXCEPTION; ! 355: subcode = err_to_error_code(frame->err); ! 356: break; ! 357: ! 358: case T_GENERAL_PROTECTION: ! 359: _exception = EXC_BAD_INSTRUCTION; ! 360: code = EXC_I386_GENERAL_PROTECTION; ! 361: subcode = err_to_error_code(frame->err); ! 362: break; ! 363: ! 364: case T_PAGE_FAULT: ! 365: _exception = EXC_BAD_ACCESS; ! 366: code = result; ! 367: subcode = va; ! 368: break; ! 369: ! 370: case T_ALIGNMENT_CHECK: ! 371: _exception = EXC_SOFTWARE; ! 372: code = EXC_I386_ALIGNMENT_CHECK; ! 373: break; ! 374: ! 375: default: ! 376: _exception = EXC_BAD_INSTRUCTION; ! 377: code = trapno; ! 378: break; ! 379: } ! 380: ! 381: _i386_backtrace(state->regs.ebp, N_BACKTRACE); ! 382: ! 383: kdp_raise_exception(_exception, code, subcode, state); ! 384: DoRestore(); ! 385: panic("continued after kernel trap"); ! 386: #else ! 387: printf("unexpected kernel trap %x eip %x\n", trapno, frame->eip); ! 388: panic("kernel trap"); ! 389: #endif ! 390: } ! 391: ! 392: static ! 393: kern_return_t ! 394: kernel_pagefault( ! 395: vm_offset_t va, ! 396: except_frame_t *frame ! 397: ) ! 398: { ! 399: thread_t thread = current_thread(); ! 400: vm_map_t map; ! 401: kern_return_t result; ! 402: ! 403: if (thread == THREAD_NULL) ! 404: map = kernel_map; ! 405: else { ! 406: map = thread->task->map; ! 407: if (vm_map_pmap(map) != kernel_pmap) ! 408: map = kernel_map; ! 409: } ! 410: ! 411: result = vm_fault(map, trunc_page(va - KERNEL_LINEAR_BASE), ! 412: frame->err.pgfault.wrtflt? ! 413: VM_PROT_READ | VM_PROT_WRITE: ! 414: VM_PROT_READ, ! 415: FALSE, 0); ! 416: ! 417: return (result); ! 418: } ! 419: ! 420: static ! 421: void ! 422: kernel_debug_trap( ! 423: thread_saved_state_t *state ! 424: ) ! 425: { ! 426: except_frame_t *frame = &state->frame; ! 427: int code; ! 428: dr6_t debug = (dr6_t) { 0 }; ! 429: extern void unix_syscall_(void), ! 430: mach_kernel_trap_(void), ! 431: machdep_call_(void); ! 432: ! 433: // Clear debug status ! 434: set_dr6(debug); ! 435: ! 436: if (state->trapno == T_DEBUG) { ! 437: if ( frame->eip == (unsigned int)unix_syscall_ || ! 438: frame->eip == (unsigned int)mach_kernel_trap_ || ! 439: frame->eip == (unsigned int)machdep_call_ ) { ! 440: current_thread()->pcb->trace = TRUE; ! 441: frame->eflags &= ~EFL_TF; ! 442: return; ! 443: } ! 444: code = EXC_I386_DEBUG; ! 445: } ! 446: else ! 447: code = EXC_I386_BREAKPOINT; ! 448: ! 449: #if GDB ! 450: kdp_raise_exception(EXC_BREAKPOINT, code, 0, state); ! 451: #else ! 452: panic("kernel debug trap"); ! 453: #endif ! 454: } ! 455: ! 456: static ! 457: boolean_t ! 458: kernel_try_recover( ! 459: except_frame_t *frame ! 460: ) ! 461: { ! 462: vm_offset_t recover = current_thread()->recover; ! 463: ! 464: if (recover != 0) { ! 465: frame->eip = recover; ! 466: frame->cs = KCS_SEL; ! 467: frame->eflags &= ~EFL_DF; ! 468: } ! 469: else ! 470: return (FALSE); ! 471: ! 472: current_thread()->recover = 0; ! 473: ! 474: return (TRUE); ! 475: } ! 476: ! 477: static ! 478: void ! 479: kernel_recover_thread( ! 480: thread_saved_state_t *state ! 481: ) ! 482: { ! 483: thread_saved_state_t *user_regs = USER_REGS(current_thread()); ! 484: vm_offset_t stack_ptr = (vm_offset_t)&state->frame.esp; ! 485: ! 486: user_regs->frame.err = state->frame.err; ! 487: ! 488: if (stack_ptr > (vm_offset_t)&user_regs->regs.ds) { ! 489: ! 490: user_regs->regs.eax = state->regs.eax; ! 491: user_regs->regs.ecx = state->regs.ecx; ! 492: user_regs->regs.edx = state->regs.edx; ! 493: user_regs->regs.ebx = state->regs.ebx; ! 494: user_regs->regs.ebp = state->regs.ebp; ! 495: user_regs->regs.esi = state->regs.esi; ! 496: user_regs->regs.edi = state->regs.edi; ! 497: ! 498: user_regs->regs.ds = state->regs.ds; ! 499: user_regs->regs.es = state->regs.es; ! 500: user_regs->regs.fs = state->regs.fs; ! 501: user_regs->regs.gs = state->regs.gs; ! 502: } ! 503: else if (stack_ptr > (vm_offset_t)&user_regs->regs.es) { ! 504: user_regs->regs.es = state->regs.es; ! 505: user_regs->regs.fs = state->regs.fs; ! 506: user_regs->regs.gs = state->regs.gs; ! 507: } ! 508: else if (stack_ptr > (vm_offset_t)&user_regs->regs.fs) { ! 509: user_regs->regs.fs = state->regs.fs; ! 510: user_regs->regs.gs = state->regs.gs; ! 511: } ! 512: else if (stack_ptr > (vm_offset_t)&user_regs->regs.gs) ! 513: user_regs->regs.gs = state->regs.gs; ! 514: } ! 515: ! 516: static inline ! 517: void ! 518: check_for_trace( ! 519: thread_saved_state_t *state ! 520: ) ! 521: { ! 522: thread_t thread = current_thread(); ! 523: ! 524: if (thread->pcb->trace) { ! 525: thread->pcb->trace = FALSE; ! 526: state->frame.eflags |= EFL_TF; ! 527: } ! 528: } ! 529: ! 530: void ! 531: machdep_call( ! 532: thread_saved_state_t *state ! 533: ) ! 534: { ! 535: except_frame_t *frame = &state->frame; ! 536: regs_t *regs = &state->regs; ! 537: int trapno, nargs; ! 538: machdep_call_t *entry; ! 539: ! 540: check_for_trace(state); ! 541: ! 542: trapno = regs->eax; ! 543: if (trapno < 0 || trapno >= machdep_call_count) { ! 544: regs->eax = (unsigned int)kern_invalid(); ! 545: ! 546: thread_exception_return(); ! 547: /* NOTREACHED */ ! 548: } ! 549: ! 550: entry = &machdep_call_table[trapno]; ! 551: nargs = entry->nargs; ! 552: ! 553: if (nargs > 0) { ! 554: int args[nargs]; ! 555: ! 556: if (copyin(frame->esp + sizeof (int), ! 557: args, ! 558: nargs * sizeof (int))) { ! 559: ! 560: regs->eax = KERN_INVALID_ADDRESS; ! 561: ! 562: thread_exception_return(); ! 563: /* NOTREACHED */ ! 564: } ! 565: ! 566: asm volatile(" ! 567: 1: ! 568: mov (%2),%%eax; ! 569: pushl %%eax; ! 570: sub $4,%2; ! 571: dec %1; ! 572: jne 1b; ! 573: mov %3,%%eax; ! 574: call *%%eax; ! 575: mov %%eax,%0" ! 576: ! 577: : "=r" (regs->eax) ! 578: : "r" (nargs), ! 579: "r" (&args[nargs - 1]), ! 580: "g" (entry->routine) ! 581: : "ax", "cx", "dx", "sp"); ! 582: } ! 583: else ! 584: regs->eax = (unsigned int)(*entry->routine)(); ! 585: ! 586: thread_exception_return(); ! 587: /* NOTREACHED */ ! 588: } ! 589: ! 590: void ! 591: mach_kernel_trap( ! 592: thread_saved_state_t *state ! 593: ) ! 594: { ! 595: except_frame_t *frame = &state->frame; ! 596: regs_t *regs = &state->regs; ! 597: int trapno, nargs; ! 598: mach_trap_t *entry; ! 599: ! 600: check_for_trace(state); ! 601: ! 602: trapno = -(int)regs->eax; ! 603: if (trapno < 0 || trapno >= mach_trap_count) { ! 604: regs->eax = (unsigned int)kern_invalid(); ! 605: ! 606: thread_exception_return(); ! 607: /* NOTREACHED */ ! 608: } ! 609: ! 610: entry = &mach_trap_table[trapno]; ! 611: nargs = entry->mach_trap_arg_count; ! 612: ! 613: if (nargs > 0) { ! 614: int args[nargs]; ! 615: ! 616: if (copyin(frame->esp + sizeof (int), ! 617: args, ! 618: nargs * sizeof (int))) { ! 619: ! 620: exception(EXC_BAD_ACCESS, ! 621: KERN_INVALID_ADDRESS, ! 622: frame->esp + sizeof (int)); ! 623: /* NOTREACHED */ ! 624: } ! 625: ! 626: asm volatile(" ! 627: 1: ! 628: mov (%2),%%eax; ! 629: pushl %%eax; ! 630: sub $4,%2; ! 631: dec %1; ! 632: jne 1b; ! 633: mov %3,%%eax; ! 634: call *%%eax; ! 635: mov %%eax,%0" ! 636: ! 637: : "=r" (regs->eax) ! 638: : "r" (nargs), ! 639: "r" (&args[nargs - 1]), ! 640: "g" (entry->mach_trap_function) ! 641: : "ax", "cx", "dx", "sp"); ! 642: } ! 643: else ! 644: regs->eax = (unsigned int)(*entry->mach_trap_function)(); ! 645: ! 646: thread_exception_return(); ! 647: /* NOTREACHED */ ! 648: } ! 649: ! 650: void ! 651: unix_syscall( ! 652: thread_saved_state_t *state ! 653: ) ! 654: { ! 655: except_frame_t *frame = &state->frame; ! 656: regs_t *regs = &state->regs; ! 657: thread_t thread = current_thread(); ! 658: struct uthread *uthread; ! 659: struct sysent *callp; ! 660: struct proc *p; ! 661: struct timeval syst; ! 662: int nargs, error = 0; ! 663: unsigned short code; ! 664: caddr_t params; ! 665: int rval[2]; ! 666: ! 667: check_for_trace(state); ! 668: ! 669: uthread = thread->_uthread; ! 670: uthread->uu_ar0 = (int *)state; ! 671: if (p = current_proc()) ! 672: syst = p->p_stats->p_ru.ru_stime; ! 673: ! 674: code = regs->eax; ! 675: params = (caddr_t)frame->esp + sizeof (int); ! 676: callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; ! 677: if (callp == sysent) { ! 678: code = fuword(params); ! 679: params += sizeof (int); ! 680: callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; ! 681: } ! 682: ! 683: if ((nargs = (callp->sy_narg * sizeof (int))) && ! 684: (error = copyin(params, (caddr_t)uthread->uu_arg, nargs)) != 0) { ! 685: regs->eax = error; ! 686: frame->eflags |= EFL_CF; ! 687: thread_exception_return(); ! 688: /* NOTREACHED */ ! 689: } ! 690: ! 691: rval[0] = 0; ! 692: rval[1] = regs->edx; ! 693: ! 694: error = (*(callp->sy_call))(p, (caddr_t)uthread->uu_arg, rval); ! 695: ! 696: if (error == ERESTART) { ! 697: state->frame.eip -= 7; ! 698: } ! 699: else if (error != EJUSTRETURN) { ! 700: if (error) { ! 701: state->regs.eax = error; ! 702: state->frame.eflags |= EFL_CF; /* carry bit */ ! 703: } else { /* (not error) */ ! 704: state->regs.eax = rval[0]; ! 705: state->regs.edx = rval[1]; ! 706: state->frame.eflags &= ~EFL_CF; ! 707: } ! 708: } ! 709: /* else (error == EJUSTRETURN) { nothing } */ ! 710: ! 711: thread_exception_return(); ! 712: /* NOTREACHED */ ! 713: ! 714: } ! 715: ! 716: ! 717: void ! 718: check_for_ast( ! 719: thread_saved_state_t *state ! 720: ) ! 721: { ! 722: thread_t thread = current_thread(); ! 723: struct proc *p = current_proc(); ! 724: ! 725: while (TRUE) { ! 726: ast_t reasons; ! 727: int mycpu = cpu_number(); ! 728: int signum; ! 729: ! 730: cli(); // disable interrupts ! 731: ! 732: reasons = ast_needed(mycpu); ! 733: ! 734: if (p) { ! 735: if ((p->p_flag & P_OWEUPC) && (p->p_flag & P_PROFIL)) { ! 736: addupc_task(p, state->frame.eip, 1); ! 737: p->p_flag &= ~P_OWEUPC; ! 738: } ! 739: ! 740: ast_off(mycpu, AST_UNIX); ! 741: ! 742: if (CHECK_SIGNALS(p, thread, thread->_uthread)) { ! 743: signum = issignal(p); ! 744: if (signum) ! 745: postsig(signum); ! 746: cli(); ! 747: } ! 748: } ! 749: ! 750: ast_off(mycpu, reasons); ! 751: ! 752: if (thread_should_halt(thread)) ! 753: thread_halt_self(); ! 754: else ! 755: if ((reasons & AST_BLOCK) || ! 756: csw_needed(thread, current_processor())) { ! 757: p->p_stats->p_ru.ru_nivcsw++; ! 758: thread_block_with_continuation(thread_exception_return); ! 759: } ! 760: else ! 761: if (reasons & AST_FP_EXTEN) ! 762: fp_ast(thread); ! 763: else ! 764: break; ! 765: } ! 766: } ! 767: ! 768: typedef struct _cframe_t { ! 769: struct _cframe_t *prev; ! 770: unsigned caller; ! 771: unsigned args[0]; ! 772: } cframe_t; ! 773: ! 774: ! 775: #define MAX_FRAME_DELTA 65536 ! 776: ! 777: void ! 778: _i386_backtrace( ! 779: void *_frame, ! 780: int nframes ! 781: ) ! 782: { ! 783: cframe_t *frame = (cframe_t *)_frame; ! 784: int i; ! 785: ! 786: for (i=0; i<nframes; i++) { ! 787: if ((vm_offset_t)frame < VM_MIN_KERNEL_ADDRESS || ! 788: (vm_offset_t)frame > VM_MAX_KERNEL_ADDRESS) { ! 789: goto invalid; ! 790: } ! 791: safe_prf("frame %x called by %x ", ! 792: frame, frame->caller); ! 793: safe_prf("args %x %x %x %x\n", ! 794: frame->args[0], frame->args[1], ! 795: frame->args[2], frame->args[3]); ! 796: if ((frame->prev < frame) || /* wrong direction */ ! 797: ((frame->prev - frame) > MAX_FRAME_DELTA)) { ! 798: goto invalid; ! 799: } ! 800: frame = frame->prev; ! 801: } ! 802: return; ! 803: invalid: ! 804: safe_prf("invalid frame pointer %x\n",frame->prev); ! 805: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.