test: ppc/exceptn.c File Reference

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.