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

exceptn.c File Reference

#include "ki.h"
#include "kxppc.h"

Go to the source code of this file.

Defines

#define _KXPPC_C_HEADER_
#define BREAK_INST   (TRAP_INSTR | TO_BREAKPOINT)
#define DIVIDE_BREAKPOINT   (TRAP_INSTR | TO_DIVIDE_BY_ZERO)
#define UDIVIDE_BREAKPOINT   (TRAP_INSTR | TO_UNCONDITIONAL_DIVIDE_BY_ZERO)
#define KERNEL_BREAKPOINT_INSTRUCTION   (BREAK_INSTR | DEBUG_STOP_BREAKPOINT)
#define KDDEBUG_BREAKPOINT   (BREAK_INSTR | BREAKIN_BREAKPOINT)

Functions

BOOLEAN KiEmulateDcbz (IN OUT PEXCEPTION_RECORD ExceptionRecord, IN OUT PKEXCEPTION_FRAME ExceptionFrame, IN OUT PKTRAP_FRAME TrapFrame)
VOID KeContextFromKframes (IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN OUT PCONTEXT ContextFrame)
VOID KeContextToKframes (IN OUT PKTRAP_FRAME TrapFrame, IN OUT PKEXCEPTION_FRAME ExceptionFrame, IN PCONTEXT ContextFrame, IN ULONG ContextFlags, IN KPROCESSOR_MODE PreviousMode)
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 = TRUE
ULONG KiBreakPoints


Define Documentation

#define _KXPPC_C_HEADER_
 

Definition at line 29 of file ppc/exceptn.c.

#define BREAK_INST   (TRAP_INSTR | TO_BREAKPOINT)
 

Definition at line 59 of file ppc/exceptn.c.

#define DIVIDE_BREAKPOINT   (TRAP_INSTR | TO_DIVIDE_BY_ZERO)
 

Definition at line 65 of file ppc/exceptn.c.

#define KDDEBUG_BREAKPOINT   (BREAK_INSTR | BREAKIN_BREAKPOINT)
 

Definition at line 73 of file ppc/exceptn.c.

#define KERNEL_BREAKPOINT_INSTRUCTION   (BREAK_INSTR | DEBUG_STOP_BREAKPOINT)
 

Definition at line 72 of file ppc/exceptn.c.

#define UDIVIDE_BREAKPOINT   (TRAP_INSTR | TO_UNCONDITIONAL_DIVIDE_BY_ZERO)
 

Definition at line 66 of file ppc/exceptn.c.

Referenced by KiDispatchException().


Function Documentation

VOID KeContextFromKframes IN PKTRAP_FRAME  TrapFrame,
IN PKEXCEPTION_FRAME  ExceptionFrame,
IN OUT PCONTEXT  ContextFrame
 

Definition at line 81 of file ppc/exceptn.c.

References CONTEXT_CONTROL, CONTEXT_FLOATING_POINT, CONTEXT_INTEGER, KeGetCurrentThread, KernelMode, and KiBreakPoints.

Referenced by Ke386SetIOPL(), KiDispatchException(), KiInitializeUserApc(), KiSaveProcessorState(), and PspGetContext().

00089 : 00090 00091 This routine moves the selected contents of the specified trap and exception frames 00092 frames into the specified context frame according to the specified context 00093 flags. 00094 00095 Arguments: 00096 00097 TrapFrame - Supplies a pointer to a trap frame from which volatile context 00098 should be copied into the context record. 00099 00100 ExceptionFrame - Supplies a pointer to an exception frame from which context 00101 should be copied into the context record. 00102 00103 ContextFrame - Supplies a pointer to the context frame that receives the 00104 context copied from the trap and exception frames. 00105 00106 Return Value: 00107 00108 None. 00109 00110 --*/ 00111 00112 { 00113 00114 // 00115 // Set control information if specified. 00116 // 00117 00118 if ((ContextFrame->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { 00119 00120 // 00121 // Set machine state, instr address, link, count registers 00122 // 00123 00124 ContextFrame->Msr = TrapFrame->Msr; 00125 ContextFrame->Iar = TrapFrame->Iar; 00126 ContextFrame->Lr = TrapFrame->Lr; 00127 ContextFrame->Ctr = TrapFrame->Ctr; 00128 } 00129 00130 // 00131 // Set integer register contents if specified. 00132 // 00133 00134 if ((ContextFrame->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) { 00135 00136 // 00137 // Volatile integer regs in trap frame are 0..12 00138 // 00139 00140 RtlMoveMemory (&ContextFrame->Gpr0, &TrapFrame->Gpr0, 00141 sizeof (ULONG) * 13); 00142 00143 // 00144 // Non-volatile integer regs in exception frame are 13..31 00145 // 00146 00147 RtlMoveMemory (&ContextFrame->Gpr13, &ExceptionFrame->Gpr13, 00148 sizeof (ULONG) * 19); 00149 00150 // 00151 // The CR is made up of volatile and non-volatile fields, 00152 // but the entire CR is saved in the trap frame 00153 // 00154 00155 ContextFrame->Cr = TrapFrame->Cr; 00156 00157 // 00158 // Fixed Point Exception Register (XER) is part of the 00159 // integer state 00160 // 00161 00162 ContextFrame->Xer = TrapFrame->Xer; 00163 } 00164 00165 // 00166 // Set floating register contents if specified. 00167 // 00168 00169 if ((ContextFrame->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) { 00170 00171 // 00172 // Volatile floating point regs in trap frame are 0..13 00173 // 00174 00175 RtlMoveMemory(&ContextFrame->Fpr0, &TrapFrame->Fpr0, 00176 sizeof(DOUBLE) * (14)); 00177 00178 // 00179 // Non-volatile floating point regs in exception frame are 14..31 00180 // 00181 00182 RtlMoveMemory(&ContextFrame->Fpr14, &ExceptionFrame->Fpr14, 00183 sizeof(DOUBLE) * (18)); 00184 00185 // 00186 // Set floating point status and control register. 00187 // 00188 00189 ContextFrame->Fpscr = TrapFrame->Fpscr; 00190 } 00191 00192 // 00193 // Fetch Dr register contents if requested. Values may be trash. 00194 // 00195 00196 if ((ContextFrame->ContextFlags & CONTEXT_DEBUG_REGISTERS) == 00197 CONTEXT_DEBUG_REGISTERS) { 00198 00199 ContextFrame->Dr0 = TrapFrame->Dr0; 00200 ContextFrame->Dr1 = TrapFrame->Dr1; 00201 ContextFrame->Dr2 = TrapFrame->Dr2; 00202 ContextFrame->Dr3 = TrapFrame->Dr3; 00203 ContextFrame->Dr6 = TrapFrame->Dr6; 00204 ContextFrame->Dr6 |= KiBreakPoints; 00205 ContextFrame->Dr5 = 0; // Zero initialize unused regs 00206 ContextFrame->Dr4 = 0; 00207 00208 // 00209 // If it's a user mode frame, and the thread doesn't have DRs set, 00210 // and we just return the trash in the frame, we risk accidentally 00211 // making the thread active with trash values on a set. Therefore, 00212 // Dr7 must be set to the number of available data address breakpoint 00213 // registers if we get a non-active user mode frame. 00214 // 00215 00216 if (((TrapFrame->PreviousMode) != KernelMode) && 00217 (KeGetCurrentThread()->DebugActive)) { 00218 00219 ContextFrame->Dr7 = TrapFrame->Dr7; 00220 } else { 00221 00222 ContextFrame->Dr7 = 0; 00223 } 00224 } 00225 00226 return; 00227 }

VOID KeContextToKframes IN OUT PKTRAP_FRAME  TrapFrame,
IN OUT PKEXCEPTION_FRAME  ExceptionFrame,
IN PCONTEXT  ContextFrame,
IN ULONG  ContextFlags,
IN KPROCESSOR_MODE  PreviousMode
 

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

References CONTEXT_CONTROL, CONTEXT_FLOATING_POINT, CONTEXT_INTEGER, KeGetCurrentThread, KeGetPcr, and KernelMode.

Referenced by Ke386SetIOPL(), KiContinue(), KiContinuePreviousModeUser(), KiDispatchException(), KiInitializeContextThread(), KiRaiseException(), KiRestoreProcessorState(), and PspSetContext().

00240 : 00241 00242 This routine moves the selected contents of the specified context frame into 00243 the specified trap and exception frames according to the specified context 00244 flags. 00245 00246 Arguments: 00247 00248 TrapFrame - Supplies a pointer to a trap frame that receives the volatile 00249 context from the context record. 00250 00251 ExceptionFrame - Supplies a pointer to an exception frame that receives 00252 the nonvolatile context from the context record. 00253 00254 ContextFrame - Supplies a pointer to a context frame that contains the 00255 context that is to be copied into the trap and exception frames. 00256 00257 ContextFlags - Supplies the set of flags that specify which parts of the 00258 context frame are to be copied into the trap and exception frames. 00259 00260 PreviousMode - Supplies the processor mode for which the trap and exception 00261 frames are being built. 00262 00263 Return Value: 00264 00265 None. 00266 00267 --*/ 00268 00269 { 00270 00271 // 00272 // Set control information if specified. 00273 // 00274 00275 if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) { 00276 00277 // 00278 // Set instruction address, link, count, and machine state registers 00279 // 00280 00281 TrapFrame->Iar = ContextFrame->Iar; 00282 TrapFrame->Lr = ContextFrame->Lr; 00283 TrapFrame->Ctr = ContextFrame->Ctr; 00284 TrapFrame->Msr = SANITIZE_MSR(ContextFrame->Msr, PreviousMode); 00285 } 00286 00287 // 00288 // Set integer registers contents if specified. 00289 // 00290 00291 if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) { 00292 00293 // 00294 // Volatile integer regs are 0..12 00295 // 00296 00297 RtlMoveMemory(&TrapFrame->Gpr0, &ContextFrame->Gpr0, 00298 sizeof(ULONG) * (13)); 00299 00300 // 00301 // Non-volatile integer regs are 13..31 00302 // 00303 00304 RtlMoveMemory(&ExceptionFrame->Gpr13, &ContextFrame->Gpr13, 00305 sizeof(ULONG) * (19)); 00306 00307 // 00308 // Copy the Condition Reg and Fixed Point Exception Reg 00309 // 00310 00311 TrapFrame->Cr = ContextFrame->Cr; 00312 TrapFrame->Xer = ContextFrame->Xer; 00313 } 00314 00315 // 00316 // Set floating register contents if specified. 00317 // 00318 00319 if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) { 00320 00321 // 00322 // Volatile floating point regs are 0..13 00323 // 00324 00325 RtlMoveMemory(&TrapFrame->Fpr0, &ContextFrame->Fpr0, 00326 sizeof(DOUBLE) * (14)); 00327 00328 // 00329 // Non-volatile floating point regs are 14..31 00330 // 00331 00332 RtlMoveMemory(&ExceptionFrame->Fpr14, &ContextFrame->Fpr14, 00333 sizeof(DOUBLE) * (18)); 00334 00335 // 00336 // Set floating point status and control register. 00337 // 00338 00339 TrapFrame->Fpscr = SANITIZE_FPSCR(ContextFrame->Fpscr, PreviousMode); 00340 } 00341 00342 // 00343 // Set debug register state if specified. If previous mode is user 00344 // mode (i.e. it's a user frame we're setting) and if effect will be to 00345 // cause at least one of the debug register enable bits in Dr7 00346 // to be set then set DebugActive to the enable bit mask. 00347 // 00348 00349 if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) { 00350 00351 // 00352 // Set the debug control register for the 601 and 604 00353 // indicating the number of address breakpoints supported. 00354 // 00355 00356 TrapFrame->Dr0 = SANITIZE_DRADDR(ContextFrame->Dr0, PreviousMode); 00357 TrapFrame->Dr1 = SANITIZE_DRADDR(ContextFrame->Dr1, PreviousMode); 00358 TrapFrame->Dr2 = SANITIZE_DRADDR(ContextFrame->Dr2, PreviousMode); 00359 TrapFrame->Dr3 = SANITIZE_DRADDR(ContextFrame->Dr3, PreviousMode); 00360 TrapFrame->Dr6 = SANITIZE_DR6(ContextFrame->Dr6, PreviousMode); 00361 TrapFrame->Dr7 = SANITIZE_DR7(ContextFrame->Dr7, PreviousMode); 00362 00363 if (PreviousMode != KernelMode) { 00364 KeGetPcr()->DebugActive = KeGetCurrentThread()->DebugActive = 00365 (UCHAR)(TrapFrame->Dr7 & DR7_ACTIVE); 00366 } 00367 } 00368 00369 return; 00370 }

NTSTATUS KeRaiseUserException IN NTSTATUS  ExceptionCode  ) 
 

Definition at line 925 of file ppc/exceptn.c.

References ASSERT, KeGetCurrentThread, KeRaiseUserExceptionDispatcher, and UserMode.

Referenced by NtClose(), and NtSetEvent().

00931 : 00932 00933 This function causes an exception to be raised in the calling thread's user-mode 00934 context. It does this by editing the trap frame the kernel was entered with to 00935 point to trampoline code that raises the requested exception. 00936 00937 Arguments: 00938 00939 ExceptionCode - Supplies the status value to be used as the exception 00940 code for the exception that is to be raised. 00941 00942 Return Value: 00943 00944 The status value that should be returned by the caller. 00945 00946 --*/ 00947 00948 { 00949 PKTRAP_FRAME TrapFrame; 00950 PULONG FnDesc; 00951 00952 ASSERT(KeGetPreviousMode() == UserMode); 00953 00954 TrapFrame = KeGetCurrentThread()->TrapFrame; 00955 FnDesc = (PULONG)KeRaiseUserExceptionDispatcher; 00956 00957 TrapFrame->Iar = FnDesc[0]; 00958 TrapFrame->Gpr2 = FnDesc[1]; 00959 00960 return(ExceptionCode); 00961 } }

ULONG KiCopyInformation IN OUT PEXCEPTION_RECORD  ExceptionRecord1,
IN PEXCEPTION_RECORD  ExceptionRecord2
 

Definition at line 886 of file ppc/exceptn.c.

References EXCEPTION_EXECUTE_HANDLER.

Referenced by Ki386CheckDelayedNpxTrap(), KiDispatchException(), KiEmulateByteWord(), KiEmulateDcbz(), KiEmulateFloating(), KiEmulateReference(), and KiInitializeUserApc().

00893 : 00894 00895 This function is called from an exception filter to copy the exception 00896 information from one exception record to another when an exception occurs. 00897 00898 Arguments: 00899 00900 ExceptionRecord1 - Supplies a pointer to the destination exception record. 00901 00902 ExceptionRecord2 - Supplies a pointer to the source exception record. 00903 00904 Return Value: 00905 00906 A value of EXCEPTION_EXECUTE_HANDLER is returned as the function value. 00907 00908 --*/ 00909 00910 { 00911 00912 // 00913 // Copy one exception record to another and return value that causes 00914 // an exception handler to be executed. 00915 // 00916 00917 RtlMoveMemory((PVOID)ExceptionRecord1, 00918 (PVOID)ExceptionRecord2, 00919 sizeof(EXCEPTION_RECORD)); 00920 00921 return EXCEPTION_EXECUTE_HANDLER; 00922 }

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

Definition at line 373 of file ppc/exceptn.c.

References CONTEXT_FULL, DATA_BUS_ERROR, DbgkForwardException(), DbgPrint, DIVIDE_BREAKPOINT, FALSE, KDDEBUG_BREAKPOINT, KdIsThisAKdTrap(), KeBugCheckEx(), KeContextFromKframes(), KeContextToKframes(), KeGetCurrentPrcb, KeGetCurrentThread, KERNEL_BREAKPOINT_INSTRUCTION, KernelMode, KeUserExceptionDispatcher, KiCopyInformation(), KiDebugRoutine, KiEmulateByteWord(), KiEmulateDcbz(), KiEmulateReference(), KiEnableAlignmentFaultExceptions, KiFloatingException(), KiMachineCheck(), KMODE_EXCEPTION_NOT_HANDLED, NULL, ProbeForWrite(), PsGetCurrentProcess, RtlDispatchException(), TRUE, UDIVIDE_BREAKPOINT, and UserMode.

Referenced by Ki386CheckDelayedNpxTrap(), KiInitializeUserApc(), and KiRaiseException().

00383 : 00384 00385 This function is called to dispatch an exception to the proper mode and 00386 to cause the exception dispatcher to be called. 00387 00388 If the exception is a data misalignment, this is the first chance for 00389 handling the exception, and the current thread has enabled automatic 00390 alignment fixup, then an attempt is made to emulate the unaligned 00391 reference. 00392 00393 If the exception is a floating exception (N.B. the pseudo status 00394 STATUS_FLOAT_STACK_CHECK is used to signify this), we convert the 00395 exception code to the correct STATUS based on the FPSCR. 00396 It is up to the handler to figure out what to do to emulate/repair 00397 the operation. 00398 00399 If the exception is neither a data misalignment nor a floating point 00400 exception and the the previous mode is kernel, then the exception 00401 dispatcher is called directly to process the exception. Otherwise the 00402 exception record, exception frame, and trap frame contents are copied 00403 to the user mode stack. The contents of the exception frame and trap 00404 are then modified such that when control is returned, execution will 00405 commence in user mode in a routine which will call the exception 00406 dispatcher. 00407 00408 Arguments: 00409 00410 ExceptionRecord - Supplies a pointer to an exception record. 00411 00412 ExceptionFrame - Supplies a pointer to an exception frame. 00413 00414 TrapFrame - Supplies a pointer to a trap frame. 00415 00416 PreviousMode - Supplies the previous processor mode. 00417 00418 FirstChance - Supplies a boolean variable that specifies whether this 00419 is the first (TRUE) or second (FALSE) time that this exception has 00420 been processed. 00421 00422 Return Value: 00423 00424 None. 00425 00426 --*/ 00427 00428 { 00429 00430 CONTEXT ContextFrame; 00431 EXCEPTION_RECORD ExceptionRecord1; 00432 LONG Length; 00433 BOOLEAN UserApcPending; 00434 00435 // 00436 // If the exception is a data misalignment, this is the first chance for 00437 // handling the exception, and the current thread has enabled automatic 00438 // alignment fixup, then attempt to emulate the unaligned reference. 00439 // 00440 // We always emulate dcbz, even if the thread hasn't enabled automatic 00441 // alignment fixup. This is because the hardware declares an alignment 00442 // fault if dcbz is attempted on noncached memory. 00443 // 00444 00445 if (ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) { 00446 if (FirstChance != FALSE) { 00447 00448 // 00449 // If alignment fault exceptions are not enabled, then no exception 00450 // should be raised and the data reference should be emulated. 00451 // 00452 00453 if ((KiEnableAlignmentFaultExceptions == FALSE) || 00454 (KeGetCurrentThread()->AutoAlignment != FALSE) || 00455 (KeGetCurrentThread()->ApcState.Process->AutoAlignment != FALSE)) { 00456 if (KiEmulateReference(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE) { 00457 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1; 00458 goto Handled2; 00459 } 00460 } else { 00461 if (KiEmulateDcbz(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE) { 00462 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1; 00463 goto Handled2; 00464 } 00465 } 00466 } 00467 } 00468 00469 // 00470 // If the exception is a breakpoint, then translate it to an appropriate 00471 // exception code if it is a division by zero or an integer overflow 00472 // caused by multiplication. 00473 // 00474 00475 if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) { 00476 00477 ULONG Instr = ExceptionRecord->ExceptionInformation[0]; 00478 00479 if ((Instr & 0xffe0ffff) == DIVIDE_BREAKPOINT || 00480 (Instr & 0xffe0ffff) == UDIVIDE_BREAKPOINT) { 00481 ExceptionRecord->ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO; 00482 } else if (Instr == KDDEBUG_BREAKPOINT) { 00483 TrapFrame->Iar += 4; 00484 } 00485 } 00486 00487 // 00488 // If the exception is a floating point exception, then the 00489 // ExceptionCode was set to STATUS_FLOAT_STACK_CHECK. We now sort 00490 // that out and set a more correct STATUS code. We clear the 00491 // exception enable bit in the FPSCR of the exception being reported 00492 // to eliminate floating point exception recursion. 00493 // 00494 00495 if (ExceptionRecord->ExceptionCode == STATUS_FLOAT_STACK_CHECK) { 00496 00497 PFPSCR Fpscr = (PFPSCR)(&TrapFrame->Fpscr); 00498 00499 if ((Fpscr->XE == 1) && (Fpscr->XX == 1)) { 00500 00501 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INEXACT_RESULT; 00502 Fpscr->XE = 0; 00503 00504 } 00505 else if ((Fpscr->ZE == 1) && (Fpscr->ZX == 1)) { 00506 00507 ExceptionRecord->ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO; 00508 Fpscr->ZE = 0; 00509 00510 } 00511 else if ((Fpscr->UE == 1) && (Fpscr->UX == 1)) { 00512 00513 ExceptionRecord->ExceptionCode = STATUS_FLOAT_UNDERFLOW; 00514 Fpscr->UE = 0; 00515 00516 } 00517 00518 else if ((Fpscr->OE == 1) && (Fpscr->OX == 1)) { 00519 00520 ExceptionRecord->ExceptionCode = STATUS_FLOAT_OVERFLOW; 00521 Fpscr->OE = 0; 00522 00523 } 00524 else { 00525 00526 // Must be some form of Invalid Operation 00527 00528 ExceptionRecord->ExceptionCode = STATUS_FLOAT_INVALID_OPERATION; 00529 Fpscr->VE = 0; 00530 } 00531 } 00532 00533 // 00534 // Move machine state from trap and exception frames to a context frame, 00535 // and increment the number of exceptions dispatched. 00536 // 00537 00538 ContextFrame.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS; 00539 KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame); 00540 KeGetCurrentPrcb()->KeExceptionDispatchCount += 1; 00541 00542 // 00543 // Select the method of handling the exception based on the previous mode. 00544 // 00545 00546 if (PreviousMode == KernelMode) { 00547 00548 // 00549 // Previous mode was kernel. 00550 // 00551 // If this is the first chance, the kernel debugger is active, and 00552 // the exception is a kernel breakpoint, then give the kernel debugger 00553 // a chance to handle the exception. 00554 // 00555 // If this is the first chance and the kernel debugger is not active 00556 // or does not handle the exception, then attempt to find a frame 00557 // handler to handle the exception. 00558 // 00559 // If this is the second chance or the exception is not handled, then 00560 // if the kernel debugger is active, then give the kernel debugger a 00561 // second chance to handle the exception. If the kernel debugger does 00562 // not handle the exception, then bug check. 00563 // 00564 00565 if (FirstChance != FALSE) { 00566 00567 // 00568 // If the kernel debugger is active, the exception is a breakpoint, 00569 // and the breakpoint is handled by the kernel debugger, then give 00570 // the kernel debugger a chance to handle the exception. 00571 // 00572 00573 if ((KiDebugRoutine != NULL) && 00574 ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) || 00575 (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)) && 00576 (KdIsThisAKdTrap(ExceptionRecord, 00577 &ContextFrame, 00578 KernelMode) != FALSE)) { 00579 00580 if (((KiDebugRoutine) (TrapFrame, 00581 ExceptionFrame, 00582 ExceptionRecord, 00583 &ContextFrame, 00584 KernelMode, 00585 FALSE)) != FALSE) { 00586 00587 goto Handled1; 00588 } 00589 } 00590 00591 // 00592 // This is the first chance to handle the exception. 00593 // 00594 00595 if (RtlDispatchException(ExceptionRecord, &ContextFrame) != FALSE) { 00596 goto Handled1; 00597 } 00598 } 00599 00600 // 00601 // This is the second chance to handle the exception. 00602 // 00603 00604 if (KiDebugRoutine != NULL) { 00605 if (((KiDebugRoutine) (TrapFrame, 00606 ExceptionFrame, 00607 ExceptionRecord, 00608 &ContextFrame, 00609 PreviousMode, 00610 TRUE)) != FALSE) { 00611 goto Handled1; 00612 } 00613 } 00614 00615 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00616 ExceptionRecord->ExceptionCode, 00617 (ULONG)ExceptionRecord->ExceptionAddress, 00618 ExceptionRecord->ExceptionInformation[0], 00619 ExceptionRecord->ExceptionInformation[1]); 00620 00621 } else { 00622 00623 // 00624 // Previous mode was user. 00625 // 00626 // If this is the first chance, the kernel debugger is active, the 00627 // exception is a kernel breakpoint, and the current process is not 00628 // being debugged, or the current process is being debugged, but the 00629 // the breakpoint is not a kernel breakpoint instruction, then give 00630 // the kernel debugger a chance to handle the exception. 00631 // 00632 // If this is the first chance and the current process has a debugger 00633 // port, then send a message to the debugger port and wait for a reply. 00634 // If the debugger handles the exception, then continue execution. Else 00635 // transfer the exception information to the user stack, transition to 00636 // user mode, and attempt to dispatch the exception to a frame based 00637 // handler. If a frame based handler handles the exception, then continue 00638 // execution. Otherwise, execute the raise exception system service 00639 // which will call this routine a second time to process the exception. 00640 // 00641 // If this is the second chance and the current process has a debugger 00642 // port, then send a message to the debugger port and wait for a reply. 00643 // If the debugger handles the exception, then continue execution. Else 00644 // if the current process has a subsystem port, then send a message to 00645 // the subsystem port and wait for a reply. If the subsystem handles the 00646 // exception, then continue execution. Else terminate the thread. 00647 // 00648 00649 if (FirstChance != FALSE) { 00650 00651 // 00652 // If the kernel debugger is active, the exception is a kernel 00653 // breakpoint, and the current process is not being debugged, 00654 // or the current process is being debugged, but the breakpoint 00655 // is not a kernel breakpoint instruction, then give the kernel 00656 // debugger a chance to handle the exception. 00657 // 00658 00659 if ((KiDebugRoutine != NULL) && 00660 ((ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) || 00661 (ExceptionRecord->ExceptionCode == STATUS_SINGLE_STEP)) && 00662 (KdIsThisAKdTrap(ExceptionRecord, 00663 &ContextFrame, 00664 UserMode) != FALSE) && 00665 ((PsGetCurrentProcess()->DebugPort == NULL) || 00666 ((PsGetCurrentProcess()->DebugPort != NULL) && 00667 (ExceptionRecord->ExceptionInformation[0] != 00668 KERNEL_BREAKPOINT_INSTRUCTION)))) { 00669 00670 if (((KiDebugRoutine) (TrapFrame, 00671 ExceptionFrame, 00672 ExceptionRecord, 00673 &ContextFrame, 00674 UserMode, 00675 FALSE)) != FALSE) { 00676 00677 goto Handled1; 00678 } 00679 } 00680 00681 // 00682 // This is the first chance to handle the exception. 00683 // 00684 00685 if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) { 00686 TrapFrame->Fpscr = SANITIZE_FPSCR(TrapFrame->Fpscr, UserMode); 00687 goto Handled2; 00688 } 00689 00690 // 00691 // Transfer exception information to the user stack, transition 00692 // to user mode, and attempt to dispatch the exception to a frame 00693 // based handler. 00694 // 00695 // We are running on the kernel stack now. On the user stack, we 00696 // build a stack frame containing the following: 00697 // 00698 // | | 00699 // |-----------------------------------| 00700 // | | 00701 // | Stack frame header | 00702 // | | 00703 // |- - - - - - - - - - - - - - - - - -| 00704 // | | 00705 // | Exception record | 00706 // | | 00707 // |- - - - - - - - - - - - - - - - - -| 00708 // | | 00709 // | Context record | 00710 // | | 00711 // | | 00712 // | | 00713 // |- - - - - - - - - - - - - - - - - -| 00714 // | Saved TOC for backtrack | 00715 // |- - - - - - - - - - - - - - - - - -| 00716 // | | 00717 // | | 00718 // | STK_SLACK_SPACE | 00719 // | | 00720 // | | 00721 // | | 00722 // |- - - - - - - - - - - - - - - - - -| 00723 // | | 00724 // | User's stack frame | 00725 // | | 00726 // | | 00727 // 00728 // This stack frame is for KiUserExceptionDispatcher, the assembly 00729 // langauge routine that effects transfer in user mode to 00730 // RtlDispatchException. KiUserExceptionDispatcher is passed 00731 // pointers to the Exception Record and Context Record as 00732 // parameters. 00733 00734 repeat: 00735 try { 00736 00737 // 00738 // Compute positions on user stack of items shown above 00739 // 00740 00741 ULONG Length = (sizeof (STACK_FRAME_HEADER) + sizeof (EXCEPTION_RECORD) + 00742 sizeof (CONTEXT) + sizeof (ULONG) + STK_SLACK_SPACE + 7) & (~7); 00743 00744 ULONG UserStack = (ContextFrame.Gpr1 & (~7)) - Length; 00745 ULONG ExceptSlot = UserStack + sizeof (STACK_FRAME_HEADER); 00746 ULONG ContextSlot = ExceptSlot + sizeof (EXCEPTION_RECORD); 00747 ULONG TocSlot = ContextSlot + sizeof (CONTEXT); 00748 00749 // 00750 // Probe user stack area for writeability and then transfer the 00751 // exception record and context record to the user stack area. 00752 // 00753 00754 ProbeForWrite((PCHAR) UserStack, ContextFrame.Gpr1 - UserStack, sizeof(QUAD)); 00755 RtlMoveMemory((PVOID) ExceptSlot, ExceptionRecord, sizeof (EXCEPTION_RECORD)); 00756 RtlMoveMemory((PVOID) ContextSlot, &ContextFrame, sizeof (CONTEXT)); 00757 00758 // 00759 // Fill in TOC value as if it had been saved by prologue to 00760 // KiUserExceptionDispatcher 00761 // 00762 00763 *((PULONG) TocSlot) = ContextFrame.Gpr2; 00764 00765 // 00766 // Set back chain from newly-constructed stack frame 00767 // 00768 00769 *((PULONG) UserStack) = ContextFrame.Gpr1; 00770 00771 // 00772 // Set address of exception record, context record, 00773 // and the new stack pointer in the current trap frame. 00774 // 00775 00776 TrapFrame->Gpr1 = UserStack; // Stack pointer 00777 TrapFrame->Gpr3 = ExceptSlot; // First parameter 00778 TrapFrame->Gpr4 = ContextSlot; // Second parameter 00779 00780 // 00781 // Sanitize the floating status register so a recursive 00782 // exception will not occur. 00783 // 00784 00785 TrapFrame->Fpscr = SANITIZE_FPSCR(ContextFrame.Fpscr, UserMode); 00786 00787 // 00788 // Set the execution address and TOC pointer of the exception 00789 // routine that will call the exception dispatcher and then return 00790 // to the trap handler. The trap handler will restore the exception 00791 // and trap frame context and continue execution in the routine 00792 // that will call the exception dispatcher. 00793 // 00794 00795 { 00796 PULONG FnDesc = (PULONG) KeUserExceptionDispatcher; 00797 TrapFrame->Iar = FnDesc[0]; 00798 TrapFrame->Gpr2 = FnDesc[1]; 00799 } 00800 00801 return; 00802 00803 // 00804 // If an exception occurs, then copy the new exception information 00805 // to an exception record and handle the exception. 00806 // 00807 00808 } except (KiCopyInformation(&ExceptionRecord1, 00809 (GetExceptionInformation())->ExceptionRecord)) { 00810 00811 // 00812 // If the exception is a stack overflow, then attempt 00813 // to raise the stack overflow exception. Otherwise, 00814 // the user's stack is not accessible, or is misaligned, 00815 // and second chance processing is performed. 00816 // 00817 00818 if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) { 00819 ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress; 00820 RtlMoveMemory((PVOID)ExceptionRecord, 00821 &ExceptionRecord1, sizeof(EXCEPTION_RECORD)); 00822 goto repeat; 00823 } 00824 } 00825 } 00826 00827 // 00828 // This is the second chance to handle the exception. 00829 // 00830 00831 UserApcPending = KeGetCurrentThread()->ApcState.UserApcPending; 00832 if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) { 00833 TrapFrame->Fpscr = SANITIZE_FPSCR(TrapFrame->Fpscr, UserMode); 00834 goto Handled2; 00835 00836 } else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) { 00837 // 00838 // If a user APC was not previously pending and one is now 00839 // pending, then the thread has been terminated and the PC 00840 // must be forced to a legal address so an infinite loop does 00841 // not occur for the case where a jump to an unmapped address 00842 // occurred. 00843 // 00844 00845 if ((UserApcPending == FALSE) && 00846 (KeGetCurrentThread()->ApcState.UserApcPending != FALSE)) { 00847 // TEMPORARY .... PAT 00848 // Commenting out reference to USPCR (a known legal address .. 00849 // TrapFrame->Iar = (ULONG)USPCR; 00850 } 00851 00852 TrapFrame->Fpscr = SANITIZE_FPSCR(TrapFrame->Fpscr, UserMode); 00853 goto Handled2; 00854 00855 } else { 00856 ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode); 00857 KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, 00858 ExceptionRecord->ExceptionCode, 00859 (ULONG)ExceptionRecord->ExceptionAddress, 00860 ExceptionRecord->ExceptionInformation[0], 00861 ExceptionRecord->ExceptionInformation[1]); 00862 } 00863 } 00864 00865 // 00866 // Move machine state from context frame to trap and exception frames and 00867 // then return to continue execution with the restored state. 00868 // 00869 00870 Handled1: 00871 KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame, 00872 ContextFrame.ContextFlags, PreviousMode); 00873 00874 // 00875 // Exception was handled by the debugger or the associated subsystem 00876 // and state was modified, if necessary, using the get state and set 00877 // state capabilities. Therefore the context frame does not need to 00878 // be transfered to the trap and exception frames. 00879 // 00880 00881 Handled2: 00882 return; 00883 }

BOOLEAN KiEmulateDcbz IN OUT PEXCEPTION_RECORD  ExceptionRecord,
IN OUT PKEXCEPTION_FRAME  ExceptionFrame,
IN OUT PKTRAP_FRAME  TrapFrame
 

Definition at line 754 of file ppc/alignem.c.

References AlFault, _DSISR::DataReg, DCBZ_INDEX_VALUE, _ALFAULT::Escape, FALSE, _DSISR::Index, KiCopyInformation(), TRUE, and _ALFAULT::Valid.

Referenced by KiDispatchException().

00762 : 00763 00764 This function is called to emulate a Data Cache Block Zero instruction. 00765 The PowerPC hardware will raise an alignment exception if a DCBZ is 00766 attempted on non-cached memory. We need to emulate this even in kernel 00767 mode so we can debug h/w problems by disabling the data cache. 00768 00769 Arguments: 00770 00771 ExceptionRecord - Supplies a pointer to an exception record. 00772 00773 ExceptionFrame - Supplies a pointer to an exception frame. 00774 00775 TrapFrame - Supplies a pointer to a trap frame. 00776 00777 Return Value: 00778 00779 A value of TRUE is returned if the data reference is successfully 00780 emulated. Otherwise, a value of FALSE is returned. 00781 00782 --*/ 00783 00784 { 00785 00786 PUCHAR DataAddress; 00787 PVOID ExceptionAddress; 00788 DSISR DsisrValue; 00789 ULONG TableIndex; 00790 ULONG DataRegNum; 00791 ALFAULT Info; 00792 00793 // 00794 // Save the original exception address in case another exception 00795 // occurs. 00796 // 00797 00798 ExceptionAddress = ExceptionRecord->ExceptionAddress; 00799 00800 // 00801 // Any exception that occurs during the attempted emulation of the 00802 // unaligned reference causes the emulation to be aborted. The new 00803 // exception code and information is copied to the original exception 00804 // record and a value of FALSE is returned. 00805 // 00806 00807 try { 00808 00809 // 00810 // The effective address of the reference from the DAR was saved 00811 // in the exception record. Check to make sure it is within the 00812 // user part of the address space. Alignment exceptions take 00813 // precedence over memory management exceptions (this is true 00814 // for PowerPC as well as MIPS) and the address could be a 00815 // system address. 00816 // 00817 00818 DataAddress = (PUCHAR) (ExceptionRecord->ExceptionInformation[1]); 00819 00820 // 00821 // Get information about the failing instruction from saved DSISR. 00822 // 00823 00824 DsisrValue = *(DSISR*) &(ExceptionRecord->ExceptionInformation[2]); 00825 TableIndex = DsisrValue.Index; 00826 DataRegNum = DsisrValue.DataReg; 00827 Info = AlFault[TableIndex]; 00828 00829 // 00830 // If table entry is valid and does not indicate special processing 00831 // needed, and is a DCBZ instruction, emulate the execution of the 00832 // instruction 00833 // 00834 00835 if (Info.Valid && Info.Escape && (TableIndex == DCBZ_INDEX_VALUE)) { 00836 00837 // 00838 // Data Cache Block Zero 00839 // 00840 // A data cache block is 32 bytes long, we emulate this 00841 // instruction by storing 8 zero integers a the address 00842 // specified. 00843 // 00844 // Note, dcbz zeros the block "containing" the address 00845 // so we round down first. 00846 // 00847 00848 PULONG DcbAddress = (PULONG)((ULONG)DataAddress & ~0x1f); 00849 00850 *DcbAddress++ = 0; 00851 *DcbAddress++ = 0; 00852 *DcbAddress++ = 0; 00853 *DcbAddress++ = 0; 00854 *DcbAddress++ = 0; 00855 *DcbAddress++ = 0; 00856 *DcbAddress++ = 0; 00857 *DcbAddress++ = 0; 00858 00859 // 00860 // Bump instruction address to next instruction. 00861 // 00862 00863 TrapFrame->Iar += 4; 00864 00865 return TRUE; 00866 } 00867 00868 // 00869 // If an exception occurs, then copy the new exception information to the 00870 // original exception record and handle the exception. 00871 // 00872 00873 } except (KiCopyInformation(ExceptionRecord, 00874 (GetExceptionInformation())->ExceptionRecord)) { 00875 00876 // 00877 // Preserve the original exception address. 00878 // 00879 00880 ExceptionRecord->ExceptionAddress = ExceptionAddress; 00881 } 00882 00883 // 00884 // Return a value of FALSE. 00885 // 00886 00887 return FALSE; 00888 } }


Variable Documentation

ULONG KiBreakPoints
 

Definition at line 78 of file ppc/exceptn.c.

Referenced by KeContextFromKframes(), and PspGetContext().

ULONG KiEnableAlignmentFaultExceptions = TRUE
 

Definition at line 53 of file ppc/exceptn.c.


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