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

exceptn.c File Reference

#include "ki.h"
#include "ntfpia64.h"

Go to the source code of this file.

Defines

#define DEFAULT_NO_ALIGNMENT_FIXUPS   FALSE

Functions

VOID KiRestoreHigherFPVolatile (VOID)
LONG fp_emulate (ULONG trap_type, PVOID pbundle, ULONGLONG *pipsr, ULONGLONG *pfpsr, ULONGLONG *pisr, ULONGLONG *ppreds, ULONGLONG *pifs, PVOID fp_state)
BOOLEAN KiEmulateFloat (PEXCEPTION_RECORD ExceptionRecord, PKEXCEPTION_FRAME ExceptionFrame, PKTRAP_FRAME TrapFrame)
VOID KiDispatchException (IN PEXCEPTION_RECORD ExceptionRecord, IN PKEXCEPTION_FRAME ExceptionFrame, IN PKTRAP_FRAME TrapFrame, IN KPROCESSOR_MODE PreviousMode, IN BOOLEAN FirstChance)
ULONG KiCopyInformation (IN OUT PEXCEPTION_RECORD ExceptionRecord1, IN PEXCEPTION_RECORD ExceptionRecord2)
NTSTATUS KeRaiseUserException (IN NTSTATUS ExceptionCode)

Variables

ULONG KiEnableAlignmentFaultExceptions = DEFAULT_NO_ALIGNMENT_FIXUPS ? 1 : 2


Define Documentation

#define DEFAULT_NO_ALIGNMENT_FIXUPS   FALSE
 

Definition at line 52 of file ia64/exceptn.c.


Function Documentation

LONG fp_emulate ULONG  trap_type,
PVOID  pbundle,
ULONGLONG *  pipsr,
ULONGLONG *  pfpsr,
ULONGLONG *  pisr,
ULONGLONG *  ppreds,
ULONGLONG *  pifs,
PVOID  fp_state
 

NTSTATUS KeRaiseUserException IN NTSTATUS  ExceptionCode  ) 
 

Definition at line 760 of file ia64/exceptn.c.

References ASSERT, EXCEPTION_EXECUTE_HANDLER, KeGetCurrentThread, KeRaiseUserExceptionDispatcher, ProbeForWrite(), and UserMode.

00766 : 00767 00768 This function causes an exception to be raised in the calling thread's user-mode 00769 context. It does this by editing the trap frame the kernel was entered with to 00770 point to trampoline code that raises the requested exception. 00771 00772 Arguments: 00773 00774 ExceptionCode - Supplies the status value to be used as the exception 00775 code for the exception that is to be raised. 00776 00777 Return Value: 00778 00779 The status value that should be returned by the caller. 00780 00781 --*/ 00782 00783 { 00784 PKTRAP_FRAME TrapFrame; 00785 00786 ASSERT(KeGetPreviousMode() == UserMode); 00787 00788 TrapFrame = KeGetCurrentThread()->TrapFrame; 00789 00790 try { 00791 ProbeForWrite ((PVOID)TrapFrame->IntSp, 16, sizeof(QUAD)); 00792 *(PULONGLONG)TrapFrame->IntSp = TrapFrame->BrRp; 00793 *(PULONGLONG)(TrapFrame->IntSp + 8) = TrapFrame->RsPFS; 00794 } except (EXCEPTION_EXECUTE_HANDLER) { 00795 return (ExceptionCode); 00796 } 00797 00798 TrapFrame->StIIP = ((PPLABEL_DESCRIPTOR)KeRaiseUserExceptionDispatcher)->EntryPoint; 00799 TrapFrame->StIFS &= (0x3i64 << 62); 00800 return(ExceptionCode); 00801 } }

ULONG KiCopyInformation IN OUT PEXCEPTION_RECORD  ExceptionRecord1,
IN PEXCEPTION_RECORD  ExceptionRecord2
 

Definition at line 722 of file ia64/exceptn.c.

References EXCEPTION_EXECUTE_HANDLER.

00729 : 00730 00731 This function is called from an exception filter to copy the exception 00732 information from one exception record to another when an exception occurs. 00733 00734 Arguments: 00735 00736 ExceptionRecord1 - Supplies a pointer to the destination exception record. 00737 00738 ExceptionRecord2 - Supplies a pointer to the source exception record. 00739 00740 Return Value: 00741 00742 A value of EXCEPTION_EXECUTE_HANDLER is returned as the function value. 00743 00744 --*/ 00745 00746 { 00747 // 00748 // Copy one exception record to another and return value that causes 00749 // an exception handler to be executed. 00750 // 00751 00752 RtlMoveMemory((PVOID)ExceptionRecord1, 00753 (PVOID)ExceptionRecord2, 00754 sizeof(EXCEPTION_RECORD)); 00755 00756 return EXCEPTION_EXECUTE_HANDLER; 00757 }

VOID KiDispatchException IN PEXCEPTION_RECORD  ExceptionRecord,
IN PKEXCEPTION_FRAME  ExceptionFrame,
IN PKTRAP_FRAME  TrapFrame,
IN KPROCESSOR_MODE  PreviousMode,
IN BOOLEAN  FirstChance
 

Definition at line 230 of file ia64/exceptn.c.

References CONTEXT_FULL, DbgkForwardException(), DbgPrint, FALSE, KdIsThisAKdTrap(), KeBugCheckEx(), KeContextFromKframes(), KeContextToKframes(), KeGetCurrentPrcb, KeGetCurrentThread, KernelMode, KeUserExceptionDispatcher, KiCopyInformation(), KiDebugRoutine, KiEmulateFloat(), KiEmulateReference(), KiEnableAlignmentFaultExceptions, KMODE_EXCEPTION_NOT_HANDLED, NULL, ProbeForWrite(), PsGetCurrentProcess, RtlDispatchException(), RtlpCaptureRnats(), TRUE, and UserMode.

00240 : 00241 00242 This function is called to dispatch an exception to the proper mode and 00243 to cause the exception dispatcher to be called. 00244 00245 If the exception is a data misalignment, this is the first chance for 00246 handling the exception, and the current thread has enabled automatic 00247 alignment fixup, then an attempt is made to emulate the unaligned 00248 reference. 00249 00250 If the exception is a floating exception (N.B. the pseudo status 00251 STATUS_FLOAT_STACK_CHECK is used to signify this and is converted to the 00252 proper code by examiningg the main status field of the floating point 00253 status register). 00254 00255 If the exception is neither a data misalignment nor a floating point 00256 exception and the the previous mode is kernel, then the exception 00257 dispatcher is called directly to process the exception. Otherwise the 00258 exception record, exception frame, and trap frame contents are copied 00259 to the user mode stack. The contents of the exception frame and trap 00260 are then modified such that when control is returned, execution will 00261 commense in user mode in a routine which will call the exception 00262 dispatcher. 00263 00264 Arguments: 00265 00266 ExceptionRecord - Supplies a pointer to an exception record. 00267 00268 ExceptionFrame - Supplies a pointer to an exception frame. 00269 00270 TrapFrame - Supplies a pointer to a trap frame. 00271 00272 PreviousMode - Supplies the previous processor mode. 00273 00274 FirstChance - Supplies a boolean variable that specifies whether this 00275 is the first (TRUE) or second (FALSE) time that this exception has 00276 been processed. 00277 00278 Return Value: 00279 00280 None. 00281 00282 --*/ 00283 00284 { 00285 00286 CONTEXT ContextFrame; 00287 EXCEPTION_RECORD ExceptionRecord1; 00288 PPLABEL_DESCRIPTOR Plabel; 00289 BOOLEAN UserApcPending; 00290 00291 // 00292 // If the exception is a data misalignment, the previous mode was user, 00293 // this is the first chance for handling the exception, and the current 00294 // thread has enabled automatic alignment fixup, then attempt to emulate 00295 // the unaligned reference. 00296 // 00297 00298 #if DBG 00299 if (KiBreakOnAlignmentFault != FALSE) { 00300 00301 if (ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) { 00302 00303 DbgPrint("KI: Alignment fault exr = %p Pc = %p Address = %p\n", 00304 ExceptionRecord, 00305 ExceptionRecord->ExceptionAddress, 00306 ExceptionRecord->ExceptionInformation[2]); 00307 00308 DbgBreakPoint(); 00309 } 00310 } 00311 #endif 00312 00313 if ((ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) && 00314 (FirstChance != FALSE)) { 00315 00316 #if DBG 00317 00318 // 00319 // Count alignment faults by mode and display them at intervals. 00320 // 00321 00322 if (PreviousMode == KernelMode) { 00323 KiKernelFixupCount += 1; 00324 if ((KiKernelFixupCount & KiKernelFixupMask) == 0) { 00325 DbgPrint("KI: Kernel Fixup: Pid=0x%.3lx, Pc=%.16p, Address=%.16p ... Total=%ld\n", 00326 PsGetCurrentProcess()->UniqueProcessId, 00327 ExceptionRecord->ExceptionAddress, 00328 ExceptionRecord->ExceptionInformation[1], 00329 KiKernelFixupCount); 00330 } 00331 00332 } else { 00333 KiUserFixupCount += 1; 00334 if ((KiUserFixupCount & KiUserFixupMask) == 0) { 00335 DbgPrint("KI: User Fixup: Pid=0x%.3lx, Pc=%.16p, Address=%.16p ... Total=%ld\n", 00336 PsGetCurrentProcess()->UniqueProcessId, 00337 ExceptionRecord->ExceptionAddress, 00338 ExceptionRecord->ExceptionInformation[1], 00339 KiUserFixupCount); 00340 } 00341 } 00342 00343 #endif 00344 00345 // 00346 // If alignment fault exceptions are not enabled, then no exception 00347 // should be raised and the data reference should be emulated. 00348 // 00349 // We will emulate the reference if 00350 // KiEnableAlignmentFaultExceptions == 0 (always fix up all faults, the default) 00351 // OR The thread has explicitly enabled alignment fixups 00352 // OR KiEnableAlignmentFaultExceptions == 2 and the process is not being debugged 00353 // 00354 00355 if ( (KiEnableAlignmentFaultExceptions == 0) || 00356 00357 ((KeGetCurrentThread()->AutoAlignment != FALSE) || 00358 (KeGetCurrentThread()->ApcState.Process->AutoAlignment != FALSE)) || 00359 00360 (((PsGetCurrentProcess()->DebugPort == NULL) || (PreviousMode == KernelMode)) && 00361 (KiEnableAlignmentFaultExceptions == 2)) ) { 00362 00363 if (KiEmulateReference(ExceptionRecord, 00364 ExceptionFrame, 00365 TrapFrame) != FALSE) 00366 { 00367 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1; 00368 goto Handled2; 00369 } 00370 } 00371 } 00372 00373 // 00374 // N.B. BREAKIN_BREAKPOINT check is in KdpTrap() 00375 // 00376 00377 // 00378 // If the exception is a floating point exception, then the 00379 // ExceptionCode was set to STATUS_FLOAT_MULTIPLE_TRAPS or 00380 // STATUS_FLOAT_MULTIPLE_FAULTS. 00381 // 00382 00383 if ((ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_FAULTS) || 00384 (ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_TRAPS)) { 00385 00386 if (KiEmulateFloat(ExceptionRecord, ExceptionFrame, TrapFrame)) { 00387 00388 // 00389 // Emulation is successful; continue execution 00390 // 00391 00392 return; 00393 } 00394 } 00395 00396 // 00397 // Move machine state from trap and exception frames to a context frame, 00398 // and increment the number of exceptions dispatched. 00399 // 00400 00401 ContextFrame.ContextFlags = CONTEXT_FULL; 00402 KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame); 00403 KeGetCurrentPrcb()->KeExceptionDispatchCount += 1; 00404 00405 // 00406 // Select the method of handling the exception based on the previous mode. 00407 // 00408 00409 if (PreviousMode == KernelMode) { 00410 00411 // 00412 // Previous mode was kernel. 00413 // 00414 // If this is the first chance, the kernel debugger is active, and 00415 // the exception is a kernel breakpoint, then give the kernel debugger 00416 // a chance to handle the exception. 00417 // 00418 // If this is the first chance and the kernel debugger is not active 00419 // or does not handle the exception, then attempt to find a frame 00420 // handler to handle the exception. 00421 // 00422 // If this is the second chance or the exception is not handled, then 00423 // if the kernel debugger is active, then give the kernel debugger a 00424 // second chance to handle the exception. If the kernel debugger does 00425 // not handle the exception, then bug check. 00426 // 00427 00428 if (FirstChance != FALSE) { 00429 00430 // 00431 // This is the first chance to handle the exception. 00432 // 00433 // Note: RtlpCaptureRnats() flushes the RSE and captures the 00434 // Nat bits of stacked registers in the RSE frame at 00435 // which exception happens. 00436 // 00437 00438 RtlpCaptureRnats(&ContextFrame); 00439 TrapFrame->RsRNAT = ContextFrame.RsRNAT; 00440 00441 // 00442 // If the kernel debugger is active, the exception is a breakpoint, 00443 // and the breakpoint is handled by the kernel debugger, then give 00444 // the kernel debugger a chance to handle the exception. 00445 // 00446 00447 if ((KiDebugRoutine != NULL) && 00448 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00449 (KdIsThisAKdTrap(ExceptionRecord, 00450 &ContextFrame, 00451 KernelMode) != FALSE)) { 00452 00453 if (((KiDebugRoutine) (TrapFrame, 00454 ExceptionFrame, 00455 ExceptionRecord, 00456 &ContextFrame, 00457 KernelMode, 00458 FALSE)) != FALSE) { 00459 00460 goto Handled1; 00461 } 00462 } 00463 00464 if (RtlDispatchException(ExceptionRecord, &ContextFrame) != FALSE) { 00465 goto Handled1; 00466 } 00467 } 00468 00469 // 00470 // This is the second chance to handle the exception. 00471 // 00472 00473 if (KiDebugRoutine != NULL) { 00474 if (((KiDebugRoutine) (TrapFrame, 00475 ExceptionFrame, 00476 ExceptionRecord, 00477 &ContextFrame, 00478 PreviousMode, 00479 TRUE)) != FALSE) { 00480 goto Handled1; 00481 } 00482 } 00483 00484 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00485 ExceptionRecord->ExceptionCode, 00486 (ULONG_PTR)ExceptionRecord->ExceptionAddress, 00487 ExceptionRecord->ExceptionInformation[0], 00488 ExceptionRecord->ExceptionInformation[1]); 00489 00490 } else { 00491 00492 // 00493 // Previous mode was user. 00494 // 00495 // If this is the first chance, the kernel debugger is active, the 00496 // exception is a kernel breakpoint, and the current process is not 00497 // being debugged, or the current process is being debugged, but the 00498 // the breakpoint is not a kernel breakpoint instruction, then give 00499 // the kernel debugger a chance to handle the exception. 00500 // 00501 // If this is the first chance and the current process has a debugger 00502 // port, then send a message to the debugger port and wait for a reply. 00503 // If the debugger handles the exception, then continue execution. Else 00504 // transfer the exception information to the user stack, transition to 00505 // user mode, and attempt to dispatch the exception to a frame based 00506 // handler. If a frame based handler handles the exception, then continue 00507 // execution. Otherwise, execute the raise exception system service 00508 // which will call this routine a second time to process the exception. 00509 // 00510 // If this is the second chance and the current process has a debugger 00511 // port, then send a message to the debugger port and wait for a reply. 00512 // If the debugger handles the exception, then continue execution. Else 00513 // if the current process has a subsystem port, then send a message to 00514 // the subsystem port and wait for a reply. If the subsystem handles the 00515 // exception, then continue execution. Else terminate the thread. 00516 // 00517 00518 if (FirstChance != FALSE) { 00519 00520 // 00521 // If the kernel debugger is active, the exception is a kernel 00522 // breakpoint, and the current process is not being debugged, 00523 // or the current process is being debugged, but the breakpoint 00524 // is not a kernel breakpoint instruction, then give the kernel 00525 // debugger a chance to handle the exception. 00526 // 00527 00528 if ((KiDebugRoutine != NULL) && 00529 (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) && 00530 (KdIsThisAKdTrap(ExceptionRecord, 00531 &ContextFrame, 00532 UserMode) != FALSE) && 00533 ((PsGetCurrentProcess()->DebugPort == NULL) || 00534 ((PsGetCurrentProcess()->DebugPort != NULL) && 00535 (ExceptionRecord->ExceptionInformation[0] != 00536 DEBUG_STOP_BREAKPOINT)))) { 00537 00538 if (((KiDebugRoutine) (TrapFrame, 00539 ExceptionFrame, 00540 ExceptionRecord, 00541 &ContextFrame, 00542 UserMode, 00543 FALSE)) != FALSE) { 00544 00545 goto Handled1; 00546 } 00547 } 00548 00549 // 00550 // This is the first chance to handle the exception. 00551 // 00552 00553 if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) { 00554 TrapFrame->StFPSR = SANITIZE_FSR(TrapFrame->StFPSR, UserMode); 00555 goto Handled2; 00556 } 00557 00558 // 00559 // Transfer exception information to the user stack, transition 00560 // to user mode, and attempt to dispatch the exception to a frame 00561 // based handler. 00562 // 00563 // 00564 // We are running on the kernel stack now. On the user stack, we 00565 // build a stack frame containing the following: 00566 // 00567 // | | 00568 // |-----------------------------------| 00569 // | | 00570 // | User's stack frame | 00571 // | | 00572 // |-----------------------------------| 00573 // | | 00574 // | Context record | 00575 // | | 00576 // | | 00577 // |- - - - - - - - - - - - - - - - - -| 00578 // | | 00579 // | Exception record | 00580 // | | 00581 // |- - - - - - - - - - - - - - - - - -| 00582 // | Stack Scratch Area | 00583 // |-----------------------------------| 00584 // | | 00585 // 00586 // This stack frame is for KiUserExceptionDispatcher, the assembly 00587 // langauge routine that effects transfer in user mode to 00588 // RtlDispatchException. KiUserExceptionDispatcher is passed 00589 // pointers to the Exception Record and Context Record as 00590 // parameters. 00591 // 00592 00593 repeat: 00594 try { 00595 00596 // 00597 // Compute length of exception record and new aligned stack 00598 // address. 00599 // 00600 00601 ULONG Length = (STACK_SCRATCH_AREA + 15 + 00602 sizeof(EXCEPTION_REGISTRATION_RECORD) + 00603 sizeof(EXCEPTION_RECORD) + sizeof(CONTEXT)) & ~(15); 00604 ULONGLONG UserStack = (ContextFrame.IntSp & (~15)) - Length; 00605 ULONGLONG ContextSlot = UserStack + STACK_SCRATCH_AREA; 00606 ULONGLONG ExceptSlot = ContextSlot + sizeof(CONTEXT); 00607 PULONGLONG PUserStack = (PULONGLONG) UserStack; 00608 00609 // 00610 // Probe user stack area for writeability and then transfer the 00611 // exception record and conext record to the user stack area. 00612 // 00613 00614 ProbeForWrite((PCHAR)UserStack, Length, sizeof(QUAD)); 00615 RtlMoveMemory((PVOID)ContextSlot, &ContextFrame, 00616 sizeof(CONTEXT)); 00617 RtlMoveMemory((PVOID)ExceptSlot, ExceptionRecord, 00618 sizeof(EXCEPTION_RECORD)); 00619 00620 // 00621 // Set address of exception record and context record in 00622 // the exception frame and the new stack pointer in the 00623 // current trap frame. Also set the initial frame size 00624 // to be zero. 00625 // 00626 // N.B. User exception dispatcher flushes the RSE 00627 // and updates the BSPStore field upon entry. 00628 // 00629 00630 TrapFrame->RsPFS = TrapFrame->StIFS; 00631 TrapFrame->StIFS &= 0xffffffc000000000; 00632 TrapFrame->StIPSR &= ~((0x3i64 << PSR_RI) | (0x1i64 << PSR_IS)); 00633 TrapFrame->IntSp = UserStack; 00634 TrapFrame->IntNats = 0; 00635 00636 ExceptionFrame->IntS0 = ExceptSlot; 00637 ExceptionFrame->IntS1 = ContextSlot; 00638 ExceptionFrame->IntNats = 0; 00639 00640 // 00641 // Set the address and the gp of the exception routine that 00642 // will call the exception dispatcher and then return to the 00643 // trap handler. The trap handler will restore the exception 00644 // and trap frame context and continue execution in the routine 00645 // that will call the exception dispatcher. 00646 // 00647 00648 Plabel = (PPLABEL_DESCRIPTOR)KeUserExceptionDispatcher; 00649 TrapFrame->StIIP = Plabel->EntryPoint; 00650 TrapFrame->IntGp = Plabel->GlobalPointer; 00651 00652 return; 00653 00654 // 00655 // If an exception occurs, then copy the new exception information 00656 // to an exception record and handle the exception. 00657 // 00658 00659 } except (KiCopyInformation(&ExceptionRecord1, 00660 (GetExceptionInformation())->ExceptionRecord)) { 00661 00662 // 00663 // If the exception is a stack overflow, then attempt 00664 // to raise the stack overflow exception. Otherwise, 00665 // the user's stack is not accessible, or is misaligned, 00666 // and second chance processing is performed. 00667 // 00668 00669 if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) { 00670 ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress; 00671 RtlMoveMemory((PVOID)ExceptionRecord, 00672 &ExceptionRecord1, sizeof(EXCEPTION_RECORD)); 00673 goto repeat; 00674 } 00675 } 00676 } 00677 00678 // 00679 // This is the second chance to handle the exception. 00680 // 00681 00682 UserApcPending = KeGetCurrentThread()->ApcState.UserApcPending; 00683 if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) { 00684 TrapFrame->StFPSR = SANITIZE_FSR(TrapFrame->StFPSR, UserMode); 00685 goto Handled2; 00686 00687 } else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) { 00688 TrapFrame->StFPSR = SANITIZE_FSR(TrapFrame->StFPSR, UserMode); 00689 goto Handled2; 00690 00691 } else { 00692 ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode); 00693 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00694 ExceptionRecord->ExceptionCode, 00695 (ULONG_PTR)ExceptionRecord->ExceptionAddress, 00696 ExceptionRecord->ExceptionInformation[0], 00697 ExceptionRecord->ExceptionInformation[1]); 00698 } 00699 } 00700 00701 // 00702 // Move machine state from context frame to trap and exception frames and 00703 // then return to continue execution with the restored state. 00704 // 00705 00706 Handled1: 00707 KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame, 00708 ContextFrame.ContextFlags, PreviousMode); 00709 00710 // 00711 // Exception was handled by the debugger or the associated subsystem 00712 // and state was modified, if necessary, using the get state and set 00713 // state capabilities. Therefore the context frame does not need to 00714 // be transfered to the trap and exception frames. 00715 // 00716 00717 Handled2: 00718 return; 00719 }

BOOLEAN KiEmulateFloat PEXCEPTION_RECORD  ExceptionRecord,
PKEXCEPTION_FRAME  ExceptionFrame,
PKTRAP_FRAME  TrapFrame
 

Definition at line 98 of file ia64/exceptn.c.

References _FLOATING_POINT_STATE::ExceptionFrame, FALSE, FLOATING_POINT_STATE, fp_emulate(), ISRCode, KeBugCheckEx(), KiAdvanceInstPointer(), KiRestoreHigherFPVolatile(), Status, _FLOATING_POINT_STATE::TrapFrame, TRUE, and USHORT.

Referenced by KiDispatchException().

00103 { 00104 00105 FLOATING_POINT_STATE FpState; 00106 USHORT ISRCode; 00107 ULONG TrapType; 00108 PVOID ExceptionAddress; 00109 LONG Status = -1; 00110 00111 FpState.ExceptionFrame = (PVOID)ExceptionFrame; 00112 FpState.TrapFrame = (PVOID)TrapFrame; 00113 00114 if (ExceptionRecord->ExceptionCode == STATUS_FLOAT_MULTIPLE_FAULTS) { 00115 TrapType = 1; 00116 ExceptionAddress = (PVOID)TrapFrame->StIIP; 00117 } else { 00118 TrapType = 0; 00119 ExceptionAddress = (PVOID)TrapFrame->StIIPA; 00120 } 00121 00122 if ((Status = fp_emulate(TrapType, ExceptionAddress, 00123 &TrapFrame->StIPSR, &TrapFrame->StFPSR, &TrapFrame->StISR, 00124 &TrapFrame->Preds, &TrapFrame->StIFS, (PVOID)&FpState)) == 0) { 00125 00126 // 00127 // Exception was handled and state modified. 00128 // Therefore the context frame does not need to 00129 // be transfered to the trap and exception frames. 00130 // 00131 // Since it was fault, PC should be advanced 00132 // 00133 00134 if (TrapType == 1) { 00135 KiAdvanceInstPointer(TrapFrame); 00136 } 00137 00138 if (TrapFrame->StIPSR & (1 << PSR_MFH)) { 00139 00140 // 00141 // high fp set is modified, reload high fp register set 00142 // must prevent interrupt during restore 00143 // 00144 00145 __rsm ((1 << PSR_DFH) | (1 << PSR_I)); 00146 KiRestoreHigherFPVolatile(); 00147 __ssm ((1 << PSR_DFH) | (1 << PSR_I)); 00148 __dsrlz(); 00149 } 00150 00151 return TRUE; 00152 } 00153 00154 if (Status == -1) { 00155 KeBugCheckEx(FP_EMULATION_ERROR, 00156 (ULONG_PTR)TrapFrame, 00157 (ULONG_PTR)ExceptionFrame, 0, 0); 00158 } 00159 00160 ISRCode = (USHORT)TrapFrame->StISR; 00161 00162 if (Status & 0x1) { 00163 00164 ExceptionRecord->ExceptionInformation[4] = TrapFrame->StISR; 00165 00166 if (!(Status & 0x4)) { 00167 if (TrapType == 1) { 00168 00169 // 00170 // FP Fault 00171 // 00172 00173 if (ISRCode & 0x11) { 00174 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00175 } else if (ISRCode & 0x22) { 00176 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DENORMAL_OPERAND; 00177 } else if (ISRCode & 0x44) { 00178 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 00179 } 00180 00181 } else { 00182 00183 // 00184 // FP Trap 00185 // 00186 00187 ISRCode = ISRCode >> 7; 00188 if (ISRCode & 0x11) { 00189 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 00190 } else if (ISRCode & 0x22) { 00191 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 00192 } else if (ISRCode & 0x44) { 00193 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 00194 } 00195 00196 } 00197 } 00198 00199 if (Status & 0x2) { 00200 00201 // 00202 // FP Fault To Trap 00203 // 00204 00205 KiAdvanceInstPointer(TrapFrame); 00206 ExceptionRecord->ExceptionAddress = 00207 (PVOID) RtlIa64InsertIPSlotNumber 00208 (TrapFrame->StIIP, 00209 ((TrapFrame->StISR & ISR_EI_MASK) >> ISR_EI) 00210 ); 00211 if (!(Status & 0x4)) { 00212 ISRCode = ISRCode >> 7; 00213 if (ISRCode & 0x11) { 00214 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 00215 } else if (ISRCode & 0x22) { 00216 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 00217 } else if (ISRCode & 0x44) { 00218 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 00219 } 00220 } else { 00221 ExceptionRecord->ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS; 00222 } 00223 } 00224 } 00225 00226 return FALSE; 00227 }

VOID KiRestoreHigherFPVolatile VOID   ) 
 

Referenced by KiEmulateFloat().


Variable Documentation

ULONG KiEnableAlignmentFaultExceptions = DEFAULT_NO_ALIGNMENT_FIXUPS ? 1 : 2
 

Definition at line 54 of file ia64/exceptn.c.


Generated on Sat May 15 19:43:34 2004 for test by doxygen 1.3.7