Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

exceptn.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 Copyright (c) 1993, 1994 Digital Equipment Corporation 00005 00006 Module Name: 00007 00008 exceptn.c 00009 00010 Abstract: 00011 00012 This module implements the code necessary to dispatch exceptions to the 00013 proper mode and invoke the exception dispatcher. 00014 00015 Author: 00016 00017 David N. Cutler (davec) 3-Apr-1990 00018 00019 Environment: 00020 00021 Kernel mode only. 00022 00023 Revision History: 00024 00025 Thomas Van Baak (tvb) 12-May-1992 00026 00027 Adapted for Alpha AXP. 00028 00029 --*/ 00030 00031 #include "ki.h" 00032 00033 VOID 00034 KiMachineCheck ( 00035 IN PEXCEPTION_RECORD ExceptionRecord, 00036 IN PKEXCEPTION_FRAME ExceptionFrame, 00037 IN PKTRAP_FRAME TrapFrame 00038 ); 00039 00040 // 00041 // Alpha data misalignment exception (auto alignment fixup) control. 00042 // 00043 // If KiEnableAlignmentFaultExceptions is 0, then no alignment 00044 // exceptions are raised and all misaligned user and kernel mode data 00045 // references are emulated. This is consistent with NT/Alpha version 00046 // 3.1 behavior. 00047 // 00048 // If KiEnableAlignmentFaultExceptions is 1, then the 00049 // current thread automatic alignment fixup enable determines whether 00050 // emulation is attempted in user mode. This is consistent with NT/Mips 00051 // behavior. 00052 // 00053 // If KiEnableAlignmentFaultExceptions is 2 and the process is being 00054 // debugged, the current thread automatic alignment fixup enable determines 00055 // whether emulation is attempted in user mode. This allows developers to 00056 // easily find and fix alignment problems. 00057 // 00058 // If KiEnableAlignmentFaultExceptions is 2 and the process is NOT being 00059 // debugged, then no alignment exceptions are raised and all misaligned 00060 // user and kernel mode data references are emulated. 00061 // 00062 // N.B. This default value may be reset from the Registry during init. 00063 // 00064 00065 #if defined(_AXP64_) && defined(_AXP64_FIXFIX) 00066 00067 // 00068 // On AXP64, the default is to disable alignment fault fixups. 00069 // 00070 // FIXFIX: This code is currently disabled by _AXP64_FIXFIX. 00071 00072 #define DEFAULT_NO_ALIGNMENT_FIXUPS TRUE 00073 #else 00074 #define DEFAULT_NO_ALIGNMENT_FIXUPS FALSE 00075 #endif 00076 00077 ULONG KiEnableAlignmentFaultExceptions = DEFAULT_NO_ALIGNMENT_FIXUPS ? 1 : 0; 00078 00079 #if DBG 00080 00081 // 00082 // Set KiBreakOnAlignmentFault to TRUE to stop the debugger on each alignment 00083 // fault. 00084 // 00085 00086 BOOLEAN KiBreakOnAlignmentFault = FALSE; 00087 00088 // 00089 // Alignment fixups are counted by mode and reported at intervals. 00090 // 00091 // N.B. Set masks to 0 to see every exception (set to 0x7 to see every 00092 // 8th, etc.). 00093 // 00094 00095 ULONG KiKernelFixupCount = 0; 00096 ULONG KiKernelFixupMask = DEFAULT_NO_ALIGNMENT_FIXUPS ? 0 : 0x7f; 00097 00098 ULONG KiUserFixupCount = 0; 00099 ULONG KiUserFixupMask = DEFAULT_NO_ALIGNMENT_FIXUPS ? 0 : 0x3ff; 00100 00101 #endif 00102 00103 VOID 00104 KeContextFromKframes ( 00105 IN PKTRAP_FRAME TrapFrame, 00106 IN PKEXCEPTION_FRAME ExceptionFrame, 00107 IN OUT PCONTEXT ContextFrame 00108 ) 00109 00110 /*++ 00111 00112 Routine Description: 00113 00114 This routine moves the selected contents of the specified trap and exception 00115 frames into the specified context frame according to the specified context 00116 flags. 00117 00118 Arguments: 00119 00120 TrapFrame - Supplies a pointer to a trap frame from which volatile context 00121 should be copied into the context record. 00122 00123 ExceptionFrame - Supplies a pointer to an exception frame from which context 00124 should be copied into the context record. 00125 00126 ContextFrame - Supplies a pointer to the context frame that receives the 00127 context copied from the trap and exception frames. 00128 00129 Return Value: 00130 00131 None. 00132 00133 --*/ 00134 00135 { 00136 00137 // 00138 // Set control information if specified. 00139 // 00140 00141 if ((ContextFrame->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { 00142 00143 // 00144 // Set integer register gp, ra, sp, FIR, and PSR from trap frame. 00145 // 00146 00147 ContextFrame->IntGp = TrapFrame->IntGp; 00148 ContextFrame->IntSp = TrapFrame->IntSp; 00149 ContextFrame->IntRa = TrapFrame->IntRa; 00150 ContextFrame->Fir = TrapFrame->Fir; 00151 ContextFrame->Psr = TrapFrame->Psr; 00152 } 00153 00154 // 00155 // Set integer register contents if specified. 00156 // 00157 00158 if ((ContextFrame->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) { 00159 00160 // 00161 // Set volatile integer registers v0 and t0 - t7 from trap frame. 00162 // 00163 00164 ContextFrame->IntV0 = TrapFrame->IntV0; 00165 ContextFrame->IntT0 = TrapFrame->IntT0; 00166 ContextFrame->IntT1 = TrapFrame->IntT1; 00167 ContextFrame->IntT2 = TrapFrame->IntT2; 00168 ContextFrame->IntT3 = TrapFrame->IntT3; 00169 ContextFrame->IntT4 = TrapFrame->IntT4; 00170 ContextFrame->IntT5 = TrapFrame->IntT5; 00171 ContextFrame->IntT6 = TrapFrame->IntT6; 00172 ContextFrame->IntT7 = TrapFrame->IntT7; 00173 00174 // 00175 // Set nonvolatile integer registers s0 - s5 from exception frame. 00176 // 00177 00178 ContextFrame->IntS0 = ExceptionFrame->IntS0; 00179 ContextFrame->IntS1 = ExceptionFrame->IntS1; 00180 ContextFrame->IntS2 = ExceptionFrame->IntS2; 00181 ContextFrame->IntS3 = ExceptionFrame->IntS3; 00182 ContextFrame->IntS4 = ExceptionFrame->IntS4; 00183 ContextFrame->IntS5 = ExceptionFrame->IntS5; 00184 00185 // 00186 // Set volatile integer registers a0 - a5, and t8 - t11 from trap 00187 // frame. 00188 // 00189 00190 ContextFrame->IntA0 = TrapFrame->IntA0; 00191 ContextFrame->IntA1 = TrapFrame->IntA1; 00192 ContextFrame->IntA2 = TrapFrame->IntA2; 00193 ContextFrame->IntA3 = TrapFrame->IntA3; 00194 ContextFrame->IntA4 = TrapFrame->IntA4; 00195 ContextFrame->IntA5 = TrapFrame->IntA5; 00196 00197 ContextFrame->IntT8 = TrapFrame->IntT8; 00198 ContextFrame->IntT9 = TrapFrame->IntT9; 00199 ContextFrame->IntT10 = TrapFrame->IntT10; 00200 ContextFrame->IntT11 = TrapFrame->IntT11; 00201 00202 // 00203 // Set volatile integer registers fp, t12 and at from trap frame. 00204 // Set integer register zero. 00205 // 00206 00207 ContextFrame->IntFp = TrapFrame->IntFp; 00208 ContextFrame->IntT12 = TrapFrame->IntT12; 00209 ContextFrame->IntAt = TrapFrame->IntAt; 00210 ContextFrame->IntZero = 0; 00211 } 00212 00213 // 00214 // Set floating register contents if specified. 00215 // 00216 00217 if ((ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) { 00218 00219 // 00220 // Set volatile floating registers f0 - f1 from trap frame. 00221 // Set volatile floating registers f10 - f30 from trap frame. 00222 // Set floating zero register f31 to 0. 00223 // 00224 00225 ContextFrame->FltF0 = TrapFrame->FltF0; 00226 ContextFrame->FltF1 = TrapFrame->FltF1; 00227 RtlMoveMemory(&ContextFrame->FltF10, &TrapFrame->FltF10, 00228 sizeof(ULONGLONG) * 21); 00229 ContextFrame->FltF31 = 0; 00230 00231 // 00232 // Set nonvolatile floating registers f2 - f9 from exception frame. 00233 // 00234 00235 ContextFrame->FltF2 = ExceptionFrame->FltF2; 00236 ContextFrame->FltF3 = ExceptionFrame->FltF3; 00237 ContextFrame->FltF4 = ExceptionFrame->FltF4; 00238 ContextFrame->FltF5 = ExceptionFrame->FltF5; 00239 ContextFrame->FltF6 = ExceptionFrame->FltF6; 00240 ContextFrame->FltF7 = ExceptionFrame->FltF7; 00241 ContextFrame->FltF8 = ExceptionFrame->FltF8; 00242 ContextFrame->FltF9 = ExceptionFrame->FltF9; 00243 00244 // 00245 // Set floating point control register from trap frame. 00246 // Clear software floating point control register in context frame 00247 // (if necessary, it can be set to the proper value by the caller). 00248 // 00249 00250 ContextFrame->Fpcr = TrapFrame->Fpcr; 00251 ContextFrame->SoftFpcr = 0; 00252 } 00253 00254 return; 00255 } 00256 00257 VOID 00258 KeContextToKframes ( 00259 IN OUT PKTRAP_FRAME TrapFrame, 00260 IN OUT PKEXCEPTION_FRAME ExceptionFrame, 00261 IN PCONTEXT ContextFrame, 00262 IN ULONG ContextFlags, 00263 IN KPROCESSOR_MODE PreviousMode 00264 ) 00265 00266 /*++ 00267 00268 Routine Description: 00269 00270 This routine moves the selected contents of the specified context frame into 00271 the specified trap and exception frames according to the specified context 00272 flags. 00273 00274 Arguments: 00275 00276 TrapFrame - Supplies a pointer to a trap frame that receives the volatile 00277 context from the context record. 00278 00279 ExceptionFrame - Supplies a pointer to an exception frame that receives 00280 the nonvolatile context from the context record. 00281 00282 ContextFrame - Supplies a pointer to a context frame that contains the 00283 context that is to be copied into the trap and exception frames. 00284 00285 ContextFlags - Supplies the set of flags that specify which parts of the 00286 context frame are to be copied into the trap and exception frames. 00287 00288 PreviousMode - Supplies the processor mode for which the trap and exception 00289 frames are being built. 00290 00291 Return Value: 00292 00293 None. 00294 00295 --*/ 00296 00297 { 00298 00299 // 00300 // Set control information if specified. 00301 // 00302 00303 if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { 00304 00305 // 00306 // Set integer register gp, sp, ra, FIR, and PSR in trap frame. 00307 // 00308 00309 TrapFrame->IntGp = ContextFrame->IntGp; 00310 TrapFrame->IntSp = ContextFrame->IntSp; 00311 TrapFrame->IntRa = ContextFrame->IntRa; 00312 TrapFrame->Fir = ContextFrame->Fir; 00313 TrapFrame->Psr = SANITIZE_PSR(ContextFrame->Psr, PreviousMode); 00314 } 00315 00316 // 00317 // Set integer register contents if specified. 00318 // 00319 00320 if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) { 00321 00322 // 00323 // Set volatile integer registers v0 and t0 - t7 in trap frame. 00324 // 00325 00326 TrapFrame->IntV0 = ContextFrame->IntV0; 00327 TrapFrame->IntT0 = ContextFrame->IntT0; 00328 TrapFrame->IntT1 = ContextFrame->IntT1; 00329 TrapFrame->IntT2 = ContextFrame->IntT2; 00330 TrapFrame->IntT3 = ContextFrame->IntT3; 00331 TrapFrame->IntT4 = ContextFrame->IntT4; 00332 TrapFrame->IntT5 = ContextFrame->IntT5; 00333 TrapFrame->IntT6 = ContextFrame->IntT6; 00334 TrapFrame->IntT7 = ContextFrame->IntT7; 00335 00336 // 00337 // Set nonvolatile integer registers s0 - s5 in exception frame. 00338 // 00339 00340 ExceptionFrame->IntS0 = ContextFrame->IntS0; 00341 ExceptionFrame->IntS1 = ContextFrame->IntS1; 00342 ExceptionFrame->IntS2 = ContextFrame->IntS2; 00343 ExceptionFrame->IntS3 = ContextFrame->IntS3; 00344 ExceptionFrame->IntS4 = ContextFrame->IntS4; 00345 ExceptionFrame->IntS5 = ContextFrame->IntS5; 00346 00347 // 00348 // Set volatile integer registers a0 - a5, and t8 - t11 in trap frame. 00349 // 00350 00351 TrapFrame->IntA0 = ContextFrame->IntA0; 00352 TrapFrame->IntA1 = ContextFrame->IntA1; 00353 TrapFrame->IntA2 = ContextFrame->IntA2; 00354 TrapFrame->IntA3 = ContextFrame->IntA3; 00355 TrapFrame->IntA4 = ContextFrame->IntA4; 00356 TrapFrame->IntA5 = ContextFrame->IntA5; 00357 00358 TrapFrame->IntT8 = ContextFrame->IntT8; 00359 TrapFrame->IntT9 = ContextFrame->IntT9; 00360 TrapFrame->IntT10 = ContextFrame->IntT10; 00361 TrapFrame->IntT11 = ContextFrame->IntT11; 00362 00363 // 00364 // Set volatile integer registers fp, t12 and at in trap frame. 00365 // 00366 00367 TrapFrame->IntFp = ContextFrame->IntFp; 00368 TrapFrame->IntT12 = ContextFrame->IntT12; 00369 TrapFrame->IntAt = ContextFrame->IntAt; 00370 } 00371 00372 // 00373 // Set floating register contents if specified. 00374 // 00375 00376 if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) { 00377 00378 // 00379 // Set volatile floating registers f0 - f1 in trap frame. 00380 // Set volatile floating registers f10 - f30 in trap frame. 00381 // 00382 00383 TrapFrame->FltF0 = ContextFrame->FltF0; 00384 TrapFrame->FltF1 = ContextFrame->FltF1; 00385 RtlMoveMemory(&TrapFrame->FltF10, &ContextFrame->FltF10, 00386 sizeof(ULONGLONG) * 21); 00387 00388 // 00389 // Set nonvolatile floating registers f2 - f9 in exception frame. 00390 // 00391 00392 ExceptionFrame->FltF2 = ContextFrame->FltF2; 00393 ExceptionFrame->FltF3 = ContextFrame->FltF3; 00394 ExceptionFrame->FltF4 = ContextFrame->FltF4; 00395 ExceptionFrame->FltF5 = ContextFrame->FltF5; 00396 ExceptionFrame->FltF6 = ContextFrame->FltF6; 00397 ExceptionFrame->FltF7 = ContextFrame->FltF7; 00398 ExceptionFrame->FltF8 = ContextFrame->FltF8; 00399 ExceptionFrame->FltF9 = ContextFrame->FltF9; 00400 00401 // 00402 // Set floating point control register in trap frame. 00403 // 00404 00405 TrapFrame->Fpcr = ContextFrame->Fpcr; 00406 } 00407 00408 return; 00409 } 00410 00411 VOID 00412 KiDispatchException ( 00413 IN PEXCEPTION_RECORD ExceptionRecord, 00414 IN PKEXCEPTION_FRAME ExceptionFrame, 00415 IN PKTRAP_FRAME TrapFrame, 00416 IN KPROCESSOR_MODE PreviousMode, 00417 IN BOOLEAN FirstChance 00418 ) 00419 00420 /*++ 00421 00422 Routine Description: 00423 00424 This function is called to dispatch an exception to the proper mode and 00425 to cause the exception dispatcher to be called. 00426 00427 If the exception is a data misalignment, the previous mode is user, this 00428 is the first chance for handling the exception, and the current thread 00429 has enabled automatic alignment fixup, then an attempt is made to emulate 00430 the unaligned reference. Data misalignment exceptions are never emulated 00431 for kernel mode. 00432 00433 If the exception is a floating not implemented exception, then an attempt 00434 is made to emulate the floating operation. If the exception is an 00435 arithmetic exception, then an attempt is made to convert the imprecise 00436 exception into a precise exception, and then emulate the floating 00437 operation in order to obtain the proper IEEE results and exceptions. 00438 Floating exceptions are never emulated for kernel mode. 00439 00440 If the exception is neither a data misalignment nor a floating point 00441 exception and the previous mode is kernel, then the exception 00442 dispatcher is called directly to process the exception. Otherwise the 00443 exception record, exception frame, and trap frame contents are copied 00444 to the user mode stack. The contents of the exception frame and trap 00445 are then modified such that when control is returned, execution will 00446 commence in user mode in a routine which will call the exception 00447 dispatcher. 00448 00449 Arguments: 00450 00451 ExceptionRecord - Supplies a pointer to an exception record. 00452 00453 ExceptionFrame - Supplies a pointer to an exception frame. 00454 00455 TrapFrame - Supplies a pointer to a trap frame. 00456 00457 PreviousMode - Supplies the previous processor mode. 00458 00459 FirstChance - Supplies a boolean variable that specifies whether this 00460 is the first (TRUE) or second (FALSE) time that this exception has 00461 been processed. 00462 00463 Return Value: 00464 00465 None. 00466 00467 --*/ 00468 00469 { 00470 00471 CONTEXT ContextFrame; 00472 EXCEPTION_RECORD ExceptionRecord1; 00473 PEXC_SUM ExceptionSummary; 00474 LONG Length; 00475 ULONG SoftFpcr; 00476 ULONGLONG UserStack1; 00477 ULONGLONG UserStack2; 00478 00479 // 00480 // If the exception is an illegal instruction exception, then check for 00481 // a byte/word instruction that should be emulated. 00482 // 00483 // N.B. The exception code STATUS_ILLEGAL_INSTRUCTION may be converted 00484 // into STATUS_DATATYPE_MISALIGNMENT in the case of unaligned word 00485 // access. 00486 // 00487 00488 if (ExceptionRecord->ExceptionCode == STATUS_ILLEGAL_INSTRUCTION) { 00489 if (KiEmulateByteWord(ExceptionRecord, 00490 ExceptionFrame, 00491 TrapFrame) != FALSE) { 00492 KeGetCurrentPrcb()->KeByteWordEmulationCount += 1; 00493 goto Handled2; 00494 } 00495 } 00496 00497 #if DBG 00498 if (KiBreakOnAlignmentFault != FALSE) { 00499 00500 if (ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) { 00501 00502 DbgPrint("KI: Alignment fault exr = %p Pc = %p Address = %p\n", 00503 ExceptionRecord, 00504 ExceptionRecord->ExceptionAddress, 00505 ExceptionRecord->ExceptionInformation[2]); 00506 00507 DbgBreakPoint(); 00508 } 00509 } 00510 #endif 00511 00512 // 00513 // If the exception is a data misalignment, the previous mode was user, 00514 // this is the first chance for handling the exception, and the current 00515 // thread has enabled automatic alignment fixup, then attempt to emulate 00516 // the unaligned reference. 00517 // 00518 00519 if ((ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) && 00520 (FirstChance != FALSE)) { 00521 00522 #if DBG 00523 00524 // 00525 // Count alignment faults by mode and display them at intervals. 00526 // 00527 00528 if (PreviousMode == KernelMode) { 00529 KiKernelFixupCount += 1; 00530 if ((KiKernelFixupCount & KiKernelFixupMask) == 0) { 00531 DbgPrint("KI: Kernel Fixup: Pid=0x%.3lx, Pc=%.16p, Address=%.16p ... Total=%ld\n", 00532 PsGetCurrentProcess()->UniqueProcessId, 00533 ExceptionRecord->ExceptionAddress, 00534 ExceptionRecord->ExceptionInformation[2], 00535 KiKernelFixupCount); 00536 } 00537 00538 } else { 00539 KiUserFixupCount += 1; 00540 if ((KiUserFixupCount & KiUserFixupMask) == 0) { 00541 DbgPrint("KI: User Fixup: Pid=0x%.3lx, Pc=%.16p, Address=%.16p ... Total=%ld\n", 00542 PsGetCurrentProcess()->UniqueProcessId, 00543 ExceptionRecord->ExceptionAddress, 00544 ExceptionRecord->ExceptionInformation[2], 00545 KiUserFixupCount); 00546 } 00547 } 00548 00549 #endif 00550 00551 // 00552 // If alignment fault exceptions are not enabled, then no exception 00553 // should be raised and the data reference should be emulated. 00554 // 00555 // We will emulate the reference if 00556 // KiEnableAlignmentFaultExceptions == 0 (always fix up all faults, the default) 00557 // OR The thread has explicitly enabled alignment fixups 00558 // OR KiEnableAlignmentFaultExceptions == 2 and the process is not being debugged 00559 // 00560 00561 if ( (KiEnableAlignmentFaultExceptions == 0) || 00562 00563 ((KeGetCurrentThread()->AutoAlignment != FALSE) || 00564 (KeGetCurrentThread()->ApcState.Process->AutoAlignment != FALSE)) || 00565 00566 (((PsGetCurrentProcess()->DebugPort == NULL) || (PreviousMode == KernelMode)) && 00567 (KiEnableAlignmentFaultExceptions == 2)) ) { 00568 00569 if (KiEmulateReference(ExceptionRecord, 00570 ExceptionFrame, 00571 TrapFrame, 00572 FALSE) != FALSE) { 00573 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1; 00574 goto Handled2; 00575 } 00576 } 00577 } 00578 00579 // 00580 // If the exception is a data bus error then a machine check has 00581 // been trapped by the PALcode. The error will be forwarded to the 00582 // HAL eventually for logging or handling. If the handler returns 00583 // it is assumed that the HAL successfully handled the error and 00584 // execution may resume. 00585 // 00586 // N.B. A special exception code is used to signal a data bus error. 00587 // This code is equivalent to the bug check code merged with a 00588 // reserved facility code and the reserved bit set. 00589 // 00590 00591 if (ExceptionRecord->ExceptionCode == (DATA_BUS_ERROR | 0xdfff0000)) { 00592 KiMachineCheck(ExceptionRecord, ExceptionFrame, TrapFrame); 00593 goto Handled2; 00594 } 00595 00596 // 00597 // Initialize the copy of the software FPCR. The proper value is set 00598 // if a floating emulation operation is performed. Case on arithmetic 00599 // exception codes that require special handling by the kernel. 00600 // 00601 00602 SoftFpcr = 0; 00603 switch (ExceptionRecord->ExceptionCode) { 00604 00605 // 00606 // If the exception is a gentrap, then attempt to translate the 00607 // Alpha specific gentrap value to a status code value. This 00608 // exception is a precise trap. 00609 // 00610 // N.B. STATUS_ALPHA_GENTRAP is a pseudo status code generated by 00611 // PALcode when a callpal gentrap is executed. The status is 00612 // visible in user mode only when the gentrap code value is 00613 // unrecognized. 00614 // 00615 00616 case STATUS_ALPHA_GENTRAP : 00617 switch (ExceptionRecord->ExceptionInformation[0]) { 00618 case GENTRAP_INTEGER_OVERFLOW : 00619 ExceptionRecord->ExceptionCode = STATUS_INTEGER_OVERFLOW; 00620 break; 00621 00622 case GENTRAP_INTEGER_DIVIDE_BY_ZERO : 00623 ExceptionRecord->ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO; 00624 break; 00625 00626 case GENTRAP_FLOATING_OVERFLOW : 00627 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 00628 break; 00629 00630 case GENTRAP_FLOATING_DIVIDE_BY_ZERO : 00631 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 00632 break; 00633 00634 case GENTRAP_FLOATING_UNDERFLOW : 00635 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 00636 break; 00637 00638 case GENTRAP_FLOATING_INVALID_OPERAND : 00639 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00640 break; 00641 00642 case GENTRAP_FLOATING_INEXACT_RESULT : 00643 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 00644 break; 00645 } 00646 break; 00647 00648 // 00649 // If the exception is an unimplemented floating operation, then 00650 // PALcode has detected a subsetted floating point operation. These 00651 // include attempts to use round to plus or minus infinity rounding 00652 // modes on EV4. This exception is a fault. 00653 // 00654 // If the previous mode was user, an attempt is made to emulate the 00655 // operation. If the emulation is successful, the continuation 00656 // address is incremented to the next instruction. 00657 // 00658 // N.B. STATUS_ALPHA_FLOATING_NOT_IMPLEMENTED is a pseudo status code 00659 // generated by PALcode. The status is never visible outside of 00660 // this handler because the floating emulation routine converts 00661 // the status code to the proper floating status value. 00662 // 00663 00664 case STATUS_ALPHA_FLOATING_NOT_IMPLEMENTED : 00665 if (PreviousMode != KernelMode) { 00666 if (KiFloatingException(ExceptionRecord, 00667 ExceptionFrame, 00668 TrapFrame, 00669 FALSE, 00670 &SoftFpcr) != FALSE) { 00671 TrapFrame->Fir += 4; 00672 goto Handled2; 00673 } 00674 00675 } else { 00676 ExceptionRecord->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION; 00677 } 00678 00679 break; 00680 00681 // 00682 // If the exception is an arithmetic exception, then one or more 00683 // integer overflow or floating point traps has occurred. This 00684 // exception is an imprecise (asynchronous) trap. Attempt to locate 00685 // the original trapping instruction and emulate the instruction. 00686 // 00687 // N.B. STATUS_ALPHA_ARITHMETIC_EXCEPTION is a pseudo status code 00688 // generated by PALcode. The status is never visible outside of 00689 // this handler because the floating emulation routine converts 00690 // the status code to the proper floating status value. 00691 // 00692 00693 case STATUS_ALPHA_ARITHMETIC_EXCEPTION : 00694 if (KiFloatingException(ExceptionRecord, 00695 ExceptionFrame, 00696 TrapFrame, 00697 TRUE, 00698 &SoftFpcr) != FALSE) { 00699 goto Handled2; 00700 } 00701 break; 00702 } 00703 00704 // 00705 // Move machine state from trap and exception frames to a context frame, 00706 // and increment the number of exceptions dispatched. 00707 // 00708 // Explicitly set the value of the software FPCR in the context frame 00709 // (because it is not a hardware register and thus not present in the 00710 // trap or exception frames). 00711 // 00712 00713 ContextFrame.ContextFlags = CONTEXT_FULL; 00714 KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame); 00715 KeGetCurrentPrcb()->KeExceptionDispatchCount += 1; 00716 ContextFrame.SoftFpcr = (ULONGLONG)SoftFpcr; 00717 00718 // 00719 // Select the method of handling the exception based on the previous mode. 00720 // 00721 00722 if (PreviousMode == KernelMode) { 00723 00724 // 00725 // If the kernel debugger is active, the exception is a breakpoint, 00726 // the breakpoint is handled by the kernel debugger, and this is the 00727 // first chance, then give the kernel debugger a chance to handle 00728 // the exception. 00729 // 00730 00731 if ((FirstChance != FALSE) && (KiDebugRoutine != NULL) && 00732 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00733 (KdIsThisAKdTrap(ExceptionRecord, 00734 &ContextFrame, 00735 KernelMode) != FALSE) && 00736 00737 (((KiDebugRoutine) (TrapFrame, 00738 ExceptionFrame, 00739 ExceptionRecord, 00740 &ContextFrame, 00741 KernelMode, 00742 FALSE)) != FALSE)) { 00743 00744 goto Handled1; 00745 } 00746 00747 00748 // 00749 // Previous mode was kernel. 00750 // 00751 // If this is the first chance, then attempt to dispatch the exception 00752 // to a frame based handler. If the exception is handled, then continue 00753 // execution. 00754 // 00755 // If this is the second chance or the exception is not handled, 00756 // then if the kernel debugger is active, then give the kernel 00757 // debugger a second chance to handle the exception. If the kernel 00758 // debugger handles the exception, then continue execution. Otherwise 00759 // bug check. 00760 // 00761 00762 if (FirstChance != FALSE) { 00763 00764 // 00765 // This is the first chance to handle the exception. 00766 // 00767 00768 if (RtlDispatchException(ExceptionRecord, &ContextFrame) != FALSE) { 00769 goto Handled1; 00770 } 00771 } 00772 00773 // 00774 // This is the second chance to handle the exception. 00775 // 00776 00777 if ((KiDebugRoutine != NULL) && 00778 (((KiDebugRoutine) (TrapFrame, 00779 ExceptionFrame, 00780 ExceptionRecord, 00781 &ContextFrame, 00782 PreviousMode, 00783 TRUE)) != FALSE)) { 00784 00785 goto Handled1; 00786 } 00787 00788 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00789 ExceptionRecord->ExceptionCode, 00790 (ULONG_PTR)ExceptionRecord->ExceptionAddress, 00791 ExceptionRecord->ExceptionInformation[0], 00792 ExceptionRecord->ExceptionInformation[1]); 00793 00794 } else { 00795 00796 // 00797 // If the kernel debugger is active, the exception is a breakpoint, 00798 // the breakpoint is handled by the kernel debugger, and this is the 00799 // first chance, then give the kernel debugger a chance to handle 00800 // the exception. 00801 // 00802 00803 if ((FirstChance != FALSE) && 00804 (KiDebugRoutine != NULL) && 00805 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00806 (KdIsThisAKdTrap(ExceptionRecord, 00807 &ContextFrame, 00808 UserMode) != FALSE) && 00809 00810 ((PsGetCurrentProcess()->DebugPort == NULL) || 00811 ((PsGetCurrentProcess()->DebugPort != NULL) && 00812 (ExceptionRecord->ExceptionInformation[0] != 00813 DEBUG_STOP_BREAKPOINT)))) { 00814 00815 if (((KiDebugRoutine) (TrapFrame, 00816 ExceptionFrame, 00817 ExceptionRecord, 00818 &ContextFrame, 00819 UserMode, 00820 FALSE)) != FALSE) { 00821 00822 goto Handled1; 00823 } 00824 } 00825 00826 // 00827 // Previous mode was user. 00828 // 00829 // If this is the first chance and the current process has a debugger 00830 // port, then send a message to the debugger port and wait for a reply. 00831 // If the debugger handles the exception, then continue execution. Otherwise 00832 // transfer the exception information to the user stack, transition to 00833 // user mode, and attempt to dispatch the exception to a frame based 00834 // handler. If a frame based handler handles the exception, then continue 00835 // execution. Otherwise, execute the raise exception system service 00836 // which will call this routine a second time to process the exception. 00837 // 00838 // If this is the second chance and the current process has a debugger 00839 // port, then send a message to the debugger port and wait for a reply. 00840 // If the debugger handles the exception, then continue execution. Otherwise 00841 // if the current process has a subsystem port, then send a message to 00842 // the subsystem port and wait for a reply. If the subsystem handles the 00843 // exception, then continue execution. Otherwise terminate the thread. 00844 // 00845 00846 if (FirstChance != FALSE) { 00847 00848 // 00849 // This is the first chance to handle the exception. 00850 // 00851 00852 if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) { 00853 goto Handled2; 00854 } 00855 00856 // 00857 // Transfer exception information to the user stack, transition 00858 // to user mode, and attempt to dispatch the exception to a frame 00859 // based handler. 00860 // 00861 00862 repeat: 00863 try { 00864 00865 // 00866 // Compute length of exception record and new aligned stack 00867 // address. 00868 // 00869 00870 Length = (sizeof(EXCEPTION_RECORD) + 15) & (~15); 00871 UserStack1 = (ContextFrame.IntSp & ~((ULONG_PTR)15)) - Length; 00872 00873 // 00874 // Probe user stack area for writability and then transfer the 00875 // exception record to the user stack area. 00876 // 00877 00878 ProbeForWrite((PCHAR)UserStack1, Length, sizeof(QUAD)); 00879 RtlMoveMemory((PVOID)UserStack1, ExceptionRecord, Length); 00880 00881 // 00882 // Compute length of context record and new aligned user stack 00883 // pointer. 00884 // 00885 00886 Length = (sizeof(CONTEXT) + 15) & (~15); 00887 UserStack2 = UserStack1 - Length; 00888 00889 // 00890 // Probe user stack area for writability and then transfer the 00891 // context record to the user stack. 00892 // 00893 00894 ProbeForWrite((PCHAR)UserStack2, Length, sizeof(QUAD)); 00895 RtlMoveMemory((PVOID)UserStack2, &ContextFrame, sizeof(CONTEXT)); 00896 00897 // 00898 // Set address of exception record, context record, and the 00899 // and the new stack pointer in the current trap frame. 00900 // 00901 00902 TrapFrame->IntSp = UserStack2; 00903 TrapFrame->IntFp = UserStack2; 00904 ExceptionFrame->IntS0 = UserStack1; 00905 ExceptionFrame->IntS1 = UserStack2; 00906 00907 // 00908 // Set the address of the exception routine that will call the 00909 // exception dispatcher and then return to the trap handler. 00910 // The trap handler will restore the exception and trap frame 00911 // context and continue execution in the routine that will 00912 // call the exception dispatcher. 00913 // 00914 00915 TrapFrame->Fir = (ULONGLONG)(LONG_PTR)KeUserExceptionDispatcher; 00916 return; 00917 00918 // 00919 // If an exception occurs, then copy the new exception information 00920 // to an exception record and handle the exception. 00921 // 00922 00923 } except (KiCopyInformation(&ExceptionRecord1, 00924 (GetExceptionInformation())->ExceptionRecord)) { 00925 00926 // 00927 // If the exception is a stack overflow, then attempt 00928 // to raise the stack overflow exception. Otherwise, 00929 // the user's stack is not accessible, or is misaligned, 00930 // and second chance processing is performed. 00931 // 00932 00933 if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) { 00934 ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress; 00935 RtlMoveMemory((PVOID)ExceptionRecord, 00936 &ExceptionRecord1, sizeof(EXCEPTION_RECORD)); 00937 goto repeat; 00938 } 00939 } 00940 } 00941 00942 // 00943 // This is the second chance to handle the exception. 00944 // 00945 00946 if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) { 00947 goto Handled2; 00948 00949 } else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) { 00950 goto Handled2; 00951 00952 } else { 00953 ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode); 00954 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00955 ExceptionRecord->ExceptionCode, 00956 (ULONG_PTR)ExceptionRecord->ExceptionAddress, 00957 ExceptionRecord->ExceptionInformation[0], 00958 ExceptionRecord->ExceptionInformation[1]); 00959 00960 } 00961 } 00962 00963 // 00964 // Move machine state from context frame to trap and exception frames and 00965 // then return to continue execution with the restored state. 00966 // 00967 00968 Handled1: 00969 KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame, 00970 ContextFrame.ContextFlags, PreviousMode); 00971 00972 // 00973 // Exception was handled by the debugger or the associated subsystem 00974 // and state was modified, if necessary, using the get state and set 00975 // state capabilities. Therefore the context frame does not need to 00976 // be transferred to the trap and exception frames. 00977 // 00978 00979 Handled2: 00980 return; 00981 } 00982 00983 ULONG 00984 KiCopyInformation ( 00985 IN OUT PEXCEPTION_RECORD ExceptionRecord1, 00986 IN PEXCEPTION_RECORD ExceptionRecord2 00987 ) 00988 00989 /*++ 00990 00991 Routine Description: 00992 00993 This function is called from an exception filter to copy the exception 00994 information from one exception record to another when an exception occurs. 00995 00996 Arguments: 00997 00998 ExceptionRecord1 - Supplies a pointer to the destination exception record. 00999 01000 ExceptionRecord2 - Supplies a pointer to the source exception record. 01001 01002 Return Value: 01003 01004 A value of EXCEPTION_EXECUTE_HANDLER is returned as the function value. 01005 01006 --*/ 01007 01008 { 01009 01010 // 01011 // Copy one exception record to another and return value that causes 01012 // an exception handler to be executed. 01013 // 01014 01015 RtlMoveMemory((PVOID)ExceptionRecord1, 01016 (PVOID)ExceptionRecord2, 01017 sizeof(EXCEPTION_RECORD)); 01018 01019 return EXCEPTION_EXECUTE_HANDLER; 01020 } 01021 01022 01023 NTSTATUS 01024 KeRaiseUserException( 01025 IN NTSTATUS ExceptionCode 01026 ) 01027 01028 /*++ 01029 01030 Routine Description: 01031 01032 This function causes an exception to be raised in the calling thread's user-mode 01033 context. It does this by editing the trap frame the kernel was entered with to 01034 point to trampoline code that raises the requested exception. 01035 01036 Arguments: 01037 01038 ExceptionCode - Supplies the status value to be used as the exception 01039 code for the exception that is to be raised. 01040 01041 Return Value: 01042 01043 The status value that should be returned by the caller. 01044 01045 --*/ 01046 01047 { 01048 01049 PKTRAP_FRAME TrapFrame; 01050 01051 ASSERT(KeGetPreviousMode() == UserMode); 01052 01053 TrapFrame = KeGetCurrentThread()->TrapFrame; 01054 01055 TrapFrame->Fir = (ULONGLONG)(LONG_PTR)KeRaiseUserExceptionDispatcher; 01056 return(ExceptionCode); 01057 } 01058 01059 #if 0 01060 01061 LOGICAL 01062 BdReportExceptionStateChange ( 01063 IN PEXCEPTION_RECORD ExceptionRecord, 01064 IN OUT PCONTEXT ContextRecord 01065 ); 01066 01067 LOGICAL 01068 BdReportLoadSymbolsStateChange ( 01069 IN PSTRING PathName, 01070 IN PKD_SYMBOLS_INFO SymbolInfo, 01071 IN LOGICAL UnloadSymbols, 01072 IN OUT PCONTEXT ContextRecord 01073 ); 01074 01075 LOGICAL 01076 BdPrintString ( 01077 IN PSTRING Output 01078 ); 01079 01080 LOGICAL 01081 BdPromptString ( 01082 IN PSTRING Output, 01083 IN OUT PSTRING Input 01084 ); 01085 01086 LOGICAL 01087 BdTrap ( 01088 IN PEXCEPTION_RECORD ExceptionRecord, 01089 IN PKEXCEPTION_FRAME ExceptionFrame, 01090 IN PKTRAP_FRAME TrapFrame, 01091 IN KPROCESSOR_MODE PreviousMode, 01092 IN BOOLEAN FirstChance 01093 ) 01094 01095 /*++ 01096 01097 Routine Description: 01098 01099 This routine is called whenever a exception is dispatched and the kernel 01100 debugger is active. 01101 01102 Arguments: 01103 01104 FirmwareFrame - Supplies a pointer to a firmware frame that describes the 01105 trap. 01106 01107 Return Value: 01108 01109 A value of TRUE is returned if the exception is handled. Otherwise a 01110 value of FALSE is returned. 01111 01112 --*/ 01113 01114 { 01115 01116 CONTEXT ContextFrame; 01117 LOGICAL Completion; 01118 PCONTEXT ContextRecord; 01119 STRING Input; 01120 ULONGLONG OldFir; 01121 STRING Output; 01122 PKD_SYMBOLS_INFO SymbolInfo; 01123 LOGICAL UnloadSymbols; 01124 01125 // 01126 // Set address of context record and set context flags. 01127 // 01128 01129 ContextRecord = &ContextFrame; 01130 ContextRecord->ContextFlags = CONTEXT_FULL; 01131 01132 // 01133 // Print, prompt, load symbols, and unload symbols are all special cases 01134 // of breakpoint. 01135 // 01136 01137 // BlPrint("bd: debug code entered with type %lx, p1 %lx\r\n", 01138 // (ULONG)FirmwareFrame->Type, 01139 // (ULONG)FirmwareFrame->Param1); 01140 01141 if ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 01142 (ExceptionRecord->ExceptionInformation[0] >= DEBUG_PRINT_BREAKPOINT)) { 01143 01144 // 01145 // Switch on the breakpoint code. 01146 // 01147 01148 UnloadSymbols = FALSE; 01149 switch (ExceptionRecord->ExceptionInformation[0]) { 01150 01151 // 01152 // Print: 01153 // 01154 // Arguments: 01155 // 01156 // a0 - Supplies a pointer to an output string buffer. 01157 // a1 - Supplies the length of the output string buffer. 01158 // 01159 01160 case DEBUG_PRINT_BREAKPOINT: 01161 // BlPrint("bd/debug: print\r\n"); 01162 Output.Buffer = (PCHAR)TrapFrame->IntA0; 01163 Output.Length = (USHORT)TrapFrame->IntA1; 01164 if (BdPrintString(&Output)) { 01165 TrapFrame->IntV0 = STATUS_BREAKPOINT; 01166 01167 } else { 01168 TrapFrame->IntV0 = STATUS_SUCCESS; 01169 } 01170 01171 TrapFrame->Fir += 4; 01172 // BlPrint("bd/debug: exit - print\r\n"); 01173 KeSweepCurrentIcache(); 01174 return TRUE; 01175 01176 // 01177 // Stop in debugger: 01178 // 01179 // As this is not a normal breakpoint we must increment the 01180 // context past the breakpoint instruction. 01181 // 01182 01183 case BREAKIN_BREAKPOINT: 01184 TrapFrame->Fir += 4; 01185 break; 01186 01187 // 01188 // Prompt: 01189 // 01190 // a0 - Supplies a pointer to an output string buffer. 01191 // a1 - Supplies the length of the output string buffer.. 01192 // a2 - supplies a pointer to an input string buffer. 01193 // a3 - Supplies the length of the input string bufffer. 01194 // 01195 01196 case DEBUG_PROMPT_BREAKPOINT: 01197 // BlPrint("bd/debug: prompt\r\n"); 01198 Output.Buffer = (PCHAR)TrapFrame->IntA0; 01199 Output.Length = (USHORT)TrapFrame->IntA1; 01200 Input.Buffer = (PCHAR)TrapFrame->IntA2; 01201 Input.MaximumLength = (USHORT)TrapFrame->IntA3; 01202 01203 // 01204 // Prompt and keep prompting until no breakin seen. 01205 // 01206 01207 do { 01208 } while(BdPromptString(&Output, &Input) != FALSE); 01209 01210 TrapFrame->IntV0 = Input.Length; 01211 TrapFrame->Fir += 4; 01212 // BlPrint("bd/debug: exit - prompt\r\n"); 01213 KeSweepCurrentIcache(); 01214 return TRUE; 01215 01216 // 01217 // Unload Symbols: 01218 // 01219 // Arguments: 01220 // 01221 // a0 - Supplies a pointer to the image path string descriptor. 01222 // a1 - Supplies a pointer to he symbol information. 01223 // 01224 01225 case DEBUG_UNLOAD_SYMBOLS_BREAKPOINT: 01226 // BlPrint("bd/debug: unload\r\n"); 01227 UnloadSymbols = TRUE; 01228 01229 // 01230 // Fall through to load symbol case. 01231 // 01232 01233 case DEBUG_LOAD_SYMBOLS_BREAKPOINT: 01234 // BlPrint("bd/debug: load\r\n"); 01235 KeContextFromKframes(TrapFrame, ExceptionFrame, ContextRecord); 01236 OldFir = ContextRecord->Fir; 01237 SymbolInfo = (PKD_SYMBOLS_INFO)ContextRecord->IntA1; 01238 BdReportLoadSymbolsStateChange((PSTRING)ContextRecord->IntA0, 01239 SymbolInfo, 01240 UnloadSymbols, 01241 ContextRecord); 01242 01243 01244 // 01245 // If the kernel debugger did not update the FIR, then increment 01246 // past the breakpoint instruction. 01247 // 01248 01249 if (ContextRecord->Fir == OldFir) { 01250 ContextRecord->Fir += 4; 01251 } 01252 01253 KeContextToKframes(TrapFrame, 01254 ExceptionFrame, 01255 ContextRecord, 01256 ContextRecord->ContextFlags, 01257 PreviousMode); 01258 01259 // BlPrint("bd/debug: exit - load/unload\r\n"); 01260 KeSweepCurrentIcache(); 01261 return TRUE; 01262 01263 // 01264 // Unknown internal command. 01265 // 01266 01267 default: 01268 break; 01269 } 01270 } 01271 01272 // 01273 // Report state change to kernel debugger on host machine. 01274 // 01275 01276 // BlPrint("bd/debug: report\r\n"); 01277 KeContextFromKframes(TrapFrame, ExceptionFrame, ContextRecord); 01278 Completion = BdReportExceptionStateChange(ExceptionRecord, 01279 ContextRecord); 01280 01281 KeContextToKframes(TrapFrame, 01282 ExceptionFrame, 01283 ContextRecord, 01284 ContextRecord->ContextFlags, 01285 PreviousMode); 01286 01287 // BlPrint("bd/debug: exit - report\r\n"); 01288 KeSweepCurrentIcache(); 01289 return TRUE; 01290 } 01291 01292 LOGICAL 01293 BdStub ( 01294 IN PEXCEPTION_RECORD ExceptionRecord, 01295 IN PKEXCEPTION_FRAME ExceptionFrame, 01296 IN PKTRAP_FRAME TrapFrame, 01297 IN KPROCESSOR_MODE PreviousMode, 01298 IN BOOLEAN FirstChance 01299 ) 01300 01301 /*++ 01302 01303 Routine Description: 01304 01305 This routine provides a kernel debugger stub routine that catchs debug 01306 prints in checked systems when the kernel debugger is not active. 01307 01308 Arguments: 01309 01310 FirmwareFrame - Supplies a pointer to a firmware frame that describes 01311 the trap. 01312 01313 Return Value: 01314 01315 A value of TRUE is returned if the exception is handled. Otherwise a 01316 value of FALSE is returned. 01317 01318 --*/ 01319 01320 { 01321 01322 return FALSE; 01323 } 01324 01325 #endif

Generated on Sat May 15 19:39:57 2004 for test by doxygen 1.3.7