test: mips/exceptn.c File Reference

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

# exceptn.c File Reference

`#include "ki.h"`
`#include "kxmips.h"`

Go to the source code of this file.

## Defines

#define | HEADER_FILE
#define | KDDEBUG_BREAKPOINT ((SPEC_OP << 26) | (BREAKIN_BREAKPOINT << 16) | BREAK_OP)
#define | DIVIDE_BREAKPOINT ((SPEC_OP << 26) | (DIVIDE_BY_ZERO_BREAKPOINT << 16) | BREAK_OP)
#define | MULTIPLY_BREAKPOINT ((SPEC_OP << 26) | (MULTIPLY_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)
#define | OVERFLOW_BREAKPOINT ((SPEC_OP << 26) | (DIVIDE_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)
#define | KERNEL_BREAKPOINT_INSTRUCTION 0x16000d

## Functions

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)

## Define Documentation

#define DIVIDE_BREAKPOINT ((SPEC_OP << 26) | (DIVIDE_BY_ZERO_BREAKPOINT << 16) | BREAK_OP)

| Definition at line 36 of file mips/exceptn.c. Referenced by KiDispatchException().

#define HEADER_FILE

| Definition at line 28 of file mips/exceptn.c.

#define KDDEBUG_BREAKPOINT ((SPEC_OP << 26) | (BREAKIN_BREAKPOINT << 16) | BREAK_OP)

| Definition at line 35 of file mips/exceptn.c. Referenced by KiDispatchException().

#define KERNEL_BREAKPOINT_INSTRUCTION 0x16000d

| Definition at line 44 of file mips/exceptn.c. Referenced by KiDispatchException().

#define MULTIPLY_BREAKPOINT ((SPEC_OP << 26) | (MULTIPLY_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)

| Definition at line 37 of file mips/exceptn.c. Referenced by KiDispatchException().

#define OVERFLOW_BREAKPOINT ((SPEC_OP << 26) | (DIVIDE_OVERFLOW_BREAKPOINT << 16) | BREAK_OP)

| Definition at line 38 of file mips/exceptn.c. Referenced by KiDispatchException().

## Function Documentation

VOID KeContextFromKframes | ( | IN PKTRAP_FRAME | TrapFrame,
|  | IN PKEXCEPTION_FRAME | ExceptionFrame,
|  | IN OUT PCONTEXT | ContextFrame
| ) |

Definition at line 47 of file mips/exceptn.c.

References CONTEXT_CONTROL, CONTEXT_FLOATING_POINT, and CONTEXT_INTEGER.

    00055                    :
    00056
    00057     This routine moves the selected contents of the specified trap and exception frames
    00058     frames into the specified context frame according to the specified context
    00059     flags.
    00060
    00061 Arguments:
    00062
    00063     TrapFrame - Supplies a pointer to a trap frame from which volatile context
    00064         should be copied into the context record.
    00065
    00066     ExceptionFrame - Supplies a pointer to an exception frame from which context
    00067         should be copied into the context record.
    00068
    00069     ContextFrame - Supplies a pointer to the context frame that receives the
    00070         context copied from the trap and exception frames.
    00071
    00072 Return Value:
    00073
    00074     None.
    00075
    00076 --*/
    00077
    00078 {
    00079
    00080     ULONG ContextFlags;
    00081
    00082     //
    00083     // Set control information if specified.
    00084     //
    00085
    00086     ContextFlags = ContextFrame->ContextFlags;
    00087     if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
    00088
    00089         //
    00090         // Set integer register gp, ra, sp, FIR, and PSR.
    00091         //
    00092
    00093         ContextFrame->XIntGp = TrapFrame->XIntGp;
    00094         ContextFrame->XIntSp = TrapFrame->XIntSp;
    00095         ContextFrame->Fir = TrapFrame->Fir;
    00096         ContextFrame->Psr = TrapFrame->Psr;
    00097         ContextFrame->XIntRa = TrapFrame->XIntRa;
    00098     }
    00099
    00100     //
    00101     // Set integer register contents if specified.
    00102     //
    00103
    00104     if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
    00105
    00106         //
    00107         // Set integer registers zero, and, at - t9, k0, k1, lo, and hi.
    00108         //
    00109
    00110         ContextFrame->XIntZero = 0;
    00111         ContextFrame->XIntAt = TrapFrame->XIntAt;
    00112         ContextFrame->XIntV0 = TrapFrame->XIntV0;
    00113         ContextFrame->XIntV1 = TrapFrame->XIntV1;
    00114         ContextFrame->XIntA0 = TrapFrame->XIntA0;
    00115         ContextFrame->XIntA1 = TrapFrame->XIntA1;
    00116         ContextFrame->XIntA2 = TrapFrame->XIntA2;
    00117         ContextFrame->XIntA3 = TrapFrame->XIntA3;
    00118         ContextFrame->XIntT0 = TrapFrame->XIntT0;
    00119         ContextFrame->XIntT1 = TrapFrame->XIntT1;
    00120         ContextFrame->XIntT2 = TrapFrame->XIntT2;
    00121         ContextFrame->XIntT3 = TrapFrame->XIntT3;
    00122         ContextFrame->XIntT4 = TrapFrame->XIntT4;
    00123         ContextFrame->XIntT5 = TrapFrame->XIntT5;
    00124         ContextFrame->XIntT6 = TrapFrame->XIntT6;
    00125         ContextFrame->XIntT7 = TrapFrame->XIntT7;
    00126         ContextFrame->XIntT8 = TrapFrame->XIntT8;
    00127         ContextFrame->XIntT9 = TrapFrame->XIntT9;
    00128         ContextFrame->XIntK0 = 0;
    00129         ContextFrame->XIntK1 = 0;
    00130         ContextFrame->XIntLo = TrapFrame->XIntLo;
    00131         ContextFrame->XIntHi = TrapFrame->XIntHi;
    00132
    00133         //
    00134         // Set integer registers s0 - s7, and s8.
    00135         //
    00136
    00137         ContextFrame->XIntS0 = TrapFrame->XIntS0;
    00138         ContextFrame->XIntS1 = TrapFrame->XIntS1;
    00139         ContextFrame->XIntS2 = TrapFrame->XIntS2;
    00140         ContextFrame->XIntS3 = TrapFrame->XIntS3;
    00141         ContextFrame->XIntS4 = TrapFrame->XIntS4;
    00142         ContextFrame->XIntS5 = TrapFrame->XIntS5;
    00143         ContextFrame->XIntS6 = TrapFrame->XIntS6;
    00144         ContextFrame->XIntS7 = TrapFrame->XIntS7;
    00145         ContextFrame->XIntS8 = TrapFrame->XIntS8;
    00146     }
    00147
    00148     //
    00149     // Set floating register contents if specified.
    00150     //
    00151
    00152     if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
    00153
    00154         //
    00155         // Set floating registers f0 - f19.
    00156         //
    00157
    00158         RtlMoveMemory(&ContextFrame->FltF0, &TrapFrame->FltF0,
    00159                      sizeof(ULONG) * (20));
    00160
    00161         //
    00162         // Set floating registers f20 - f31.
    00163         //
    00164
    00165         RtlMoveMemory(&ContextFrame->FltF20, &ExceptionFrame->FltF20,
    00166                      sizeof(ULONG) * (12));
    00167
    00168         //
    00169         // Set floating status register.
    00170         //
    00171
    00172         ContextFrame->Fsr = TrapFrame->Fsr;
    00173     }
    00174
    00175     return;
    00176 }

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 179 of file mips/exceptn.c.

References CONTEXT_CONTROL, CONTEXT_FLOATING_POINT, and CONTEXT_INTEGER.

    00189                    :
    00190
    00191     This routine moves the selected contents of the specified context frame into
    00192     the specified trap and exception frames according to the specified context
    00193     flags.
    00194
    00195 Arguments:
    00196
    00197     TrapFrame - Supplies a pointer to a trap frame that receives the volatile
    00198         context from the context record.
    00199
    00200     ExceptionFrame - Supplies a pointer to an exception frame that receives
    00201         the nonvolatile context from the context record.
    00202
    00203     ContextFrame - Supplies a pointer to a context frame that contains the
    00204         context that is to be copied into the trap and exception frames.
    00205
    00206     ContextFlags - Supplies the set of flags that specify which parts of the
    00207         context frame are to be copied into the trap and exception frames.
    00208
    00209     PreviousMode - Supplies the processor mode for which the trap and exception
    00210         frames are being built.
    00211
    00212 Return Value:
    00213
    00214     None.
    00215
    00216 --*/
    00217
    00218 {
    00219
    00220     //
    00221     // Set control information if specified.
    00222     //
    00223
    00224     if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL) {
    00225
    00226         //
    00227         // Set integer register gp, sp, ra, FIR, and PSR.
    00228         //
    00229
    00230         TrapFrame->XIntGp = ContextFrame->XIntGp;
    00231         TrapFrame->XIntSp = ContextFrame->XIntSp;
    00232         TrapFrame->Fir = ContextFrame->Fir;
    00233         TrapFrame->Psr = SANITIZE_PSR(ContextFrame->Psr, PreviousMode);
    00234         TrapFrame->XIntRa = ContextFrame->XIntRa;
    00235     }
    00236
    00237     //
    00238     // Set integer registers contents if specified.
    00239     //
    00240
    00241     if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) {
    00242
    00243         //
    00244         // Set integer registers at - t9, lo, and hi.
    00245         //
    00246
    00247         TrapFrame->XIntAt = ContextFrame->XIntAt;
    00248         TrapFrame->XIntV0 = ContextFrame->XIntV0;
    00249         TrapFrame->XIntV1 = ContextFrame->XIntV1;
    00250         TrapFrame->XIntA0 = ContextFrame->XIntA0;
    00251         TrapFrame->XIntA1 = ContextFrame->XIntA1;
    00252         TrapFrame->XIntA2 = ContextFrame->XIntA2;
    00253         TrapFrame->XIntA3 = ContextFrame->XIntA3;
    00254         TrapFrame->XIntT0 = ContextFrame->XIntT0;
    00255         TrapFrame->XIntT1 = ContextFrame->XIntT1;
    00256         TrapFrame->XIntT2 = ContextFrame->XIntT2;
    00257         TrapFrame->XIntT3 = ContextFrame->XIntT3;
    00258         TrapFrame->XIntT4 = ContextFrame->XIntT4;
    00259         TrapFrame->XIntT5 = ContextFrame->XIntT5;
    00260         TrapFrame->XIntT6 = ContextFrame->XIntT6;
    00261         TrapFrame->XIntT7 = ContextFrame->XIntT7;
    00262         TrapFrame->XIntT8 = ContextFrame->XIntT8;
    00263         TrapFrame->XIntT9 = ContextFrame->XIntT9;
    00264         TrapFrame->XIntLo = ContextFrame->XIntLo;
    00265         TrapFrame->XIntHi = ContextFrame->XIntHi;
    00266
    00267         //
    00268         // Set integer registers s0 - s7, and s8.
    00269         //
    00270
    00271         TrapFrame->XIntS0 = ContextFrame->XIntS0;
    00272         TrapFrame->XIntS1 = ContextFrame->XIntS1;
    00273         TrapFrame->XIntS2 = ContextFrame->XIntS2;
    00274         TrapFrame->XIntS3 = ContextFrame->XIntS3;
    00275         TrapFrame->XIntS4 = ContextFrame->XIntS4;
    00276         TrapFrame->XIntS5 = ContextFrame->XIntS5;
    00277         TrapFrame->XIntS6 = ContextFrame->XIntS6;
    00278         TrapFrame->XIntS7 = ContextFrame->XIntS7;
    00279         TrapFrame->XIntS8 = ContextFrame->XIntS8;
    00280     }
    00281
    00282     //
    00283     // Set floating register contents if specified.
    00284     //
    00285
    00286     if ((ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) {
    00287
    00288         //
    00289         // Set floating registers f0 - f19.
    00290         //
    00291
    00292         RtlMoveMemory(&TrapFrame->FltF0, &ContextFrame->FltF0,
    00293                      sizeof(ULONG) * (20));
    00294
    00295         //
    00296         // Set floating registers f20 - f31.
    00297         //
    00298
    00299         RtlMoveMemory(&ExceptionFrame->FltF20, &ContextFrame->FltF20,
    00300                      sizeof(ULONG) * (12));
    00301
    00302         //
    00303         // Set floating status register.
    00304         //
    00305
    00306         TrapFrame->Fsr = SANITIZE_FSR(ContextFrame->Fsr, PreviousMode);
    00307     }
    00308
    00309     return;
    00310 }

NTSTATUS KeRaiseUserException | ( | IN NTSTATUS | ExceptionCode | ) |

Definition at line 863 of file mips/exceptn.c.

References ASSERT, KeGetCurrentThread, KeRaiseUserExceptionDispatcher, and UserMode.

    00869                    :
    00870
    00871     This function causes an exception to be raised in the calling thread's
    00872     usermode context. This is accomplished by editing the trap frame the
    00873     kernel was entered with to point to trampoline code that raises the
    00874     requested exception.
    00875
    00876 Arguments:
    00877
    00878     ExceptionCode - Supplies the status value to be used as the exception
    00879         code for the exception that is to be raised.
    00880
    00881 Return Value:
    00882
    00883     The status value that should be returned by the caller.
    00884
    00885 --*/
    00886
    00887 {
    00888
    00889     PKTRAP_FRAME TrapFrame;
    00890
    00891     ASSERT(KeGetPreviousMode() == UserMode);
    00892
    00893     TrapFrame = KeGetCurrentThread()->TrapFrame;
    00894     TrapFrame->Fir = KeRaiseUserExceptionDispatcher;
    00895     return ExceptionCode;
    00896 }
    }

ULONG KiCopyInformation | ( | IN OUT PEXCEPTION_RECORD | ExceptionRecord1,
|  | IN PEXCEPTION_RECORD | ExceptionRecord2
| ) |

Definition at line 823 of file mips/exceptn.c.

References EXCEPTION_EXECUTE_HANDLER.

    00830                    :
    00831
    00832     This function is called from an exception filter to copy the exception
    00833     information from one exception record to another when an exception occurs.
    00834
    00835 Arguments:
    00836
    00837     ExceptionRecord1 - Supplies a pointer to the destination exception record.
    00838
    00839     ExceptionRecord2 - Supplies a pointer to the source exception record.
    00840
    00841 Return Value:
    00842
    00843     A value of EXCEPTION_EXECUTE_HANDLER is returned as the function value.
    00844
    00845 --*/
    00846
    00847 {
    00848
    00849     //
    00850     // Copy one exception record to another and return value that causes
    00851     // an exception handler to be executed.
    00852     //
    00853
    00854     RtlMoveMemory((PVOID)ExceptionRecord1,
    00855                   (PVOID)ExceptionRecord2,
    00856                   sizeof(EXCEPTION_RECORD));
    00857
    00858     return EXCEPTION_EXECUTE_HANDLER;
    00859 }

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

Definition at line 313 of file mips/exceptn.c.

References CONTEXT_FULL, DATA_BUS_ERROR, DbgkForwardException(), DIVIDE_BREAKPOINT, FALSE, Index, INSTRUCTION_BUS_ERROR, KDDEBUG_BREAKPOINT, KdIsThisAKdTrap(), KeBugCheckEx(), KeContextFromKframes(), KeContextToKframes(), KeGetCurrentPrcb, KeGetCurrentThread, KERNEL_BREAKPOINT_INSTRUCTION, KernelMode, KeUserExceptionDispatcher, KiCopyInformation(), KiDataBusError(), KiDebugRoutine, KiEmulateFloating(), KiEmulateReference(), KiInstructionBusError(), KMODE_EXCEPTION_NOT_HANDLED, MULTIPLY_BREAKPOINT, NULL, OVERFLOW_BREAKPOINT, ProbeForWrite(), PsGetCurrentProcess, RtlDispatchException(), TRUE, and UserMode.

    00323                    :
    00324
    00325     This function is called to dispatch an exception to the proper mode and
    00326     to cause the exception dispatcher to be called.
    00327
    00328     If the exception is a data misalignment, the previous mode is user, this
    00329     is the first chance for handling the exception, and the current thread
    00330     has enabled automatic alignment fixup, then an attempt is made to emulate
    00331     the unaligned reference. Data misalignment exceptions are never emulated
    00332     for kernel mode.
    00333
    00334     If the exception is a floating exception (N.B. the pseudo status
    00335     STATUS_FLOAT_STACK_CHECK is used to signify this and is converted to the
    00336     proper code by the floating emulation routine), then an attempt is made
    00337     to emulate the floating operation if it is not implemented.
    00338
    00339     If the exception is neither a data misalignment nor a floating point
    00340     exception and the the previous mode is kernel, then the exception
    00341     dispatcher is called directly to process the exception. Otherwise the
    00342     exception record, exception frame, and trap frame contents are copied
    00343     to the user mode stack. The contents of the exception frame and trap
    00344     are then modified such that when control is returned, execution will
    00345     commense in user mode in a routine which will call the exception
    00346     dispatcher.
    00347
    00348 Arguments:
    00349
    00350     ExceptionRecord - Supplies a pointer to an exception record.
    00351
    00352     ExceptionFrame - Supplies a pointer to an exception frame.
    00353
    00354     TrapFrame - Supplies a pointer to a trap frame.
    00355
    00356     PreviousMode - Supplies the previous processor mode.
    00357
    00358     FirstChance - Supplies a boolean variable that specifies whether this
    00359         is the first (TRUE) or second (FALSE) time that this exception has
    00360         been processed.
    00361
    00362 Return Value:
    00363
    00364     None.
    00365
    00366 --*/
    00367
    00368 {
    00369
    00370     CONTEXT ContextFrame;
    00371     PULONG Destination;
    00372     EXCEPTION_RECORD ExceptionRecord1;
    00373     ULONG Index;
    00374     LONG Length;
    00375     PULONGLONG Source;
    00376     BOOLEAN UserApcPending;
    00377     ULONG UserStack1;
    00378     ULONG UserStack2;
    00379
    00380     //
    00381     // If the exception is an access violation, and the previous mode is
    00382     // user mode, then attempt to emulate a load or store operation if
    00383     // the exception address is at the end of a page.
    00384     //
    00385     // N.B. The following is a workaround for a r4000 chip bug where an
    00386     //      address privilege violation is reported as a access violation
    00387     //      on a load or store instruction that is the last instruction
    00388     //      in a page.
    00389     //
    00390
    00391     if ((ExceptionRecord->ExceptionCode == STATUS_ACCESS_VIOLATION) &&
    00392         (((ULONG)ExceptionRecord->ExceptionAddress & 0xffc) == 0xffc) &&
    00393         (PreviousMode != KernelMode) &&
    00394         (KiEmulateReference(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE)) {
    00395         KeGetCurrentPrcb()->KeAlignmentFixupCount += 1;
    00396         goto Handled2;
    00397     }
    00398
    00399     //
    00400     // If the exception is a data bus error, then process the error.
    00401     //
    00402     // N.B. A special exception code is used to signal a data bus error.
    00403     //      This code is equivalent to the bug check code merged with a
    00404     //      reserved facility code and the reserved bit set.
    00405     //
    00406     // N.B. If control returns, then it is assumed that the error has been
    00407     //      corrected.
    00408     //
    00409
    00410     if (ExceptionRecord->ExceptionCode == (DATA_BUS_ERROR | 0xdfff0000)) {
    00411
    00412         //
    00413         // N.B. The following is a workaround for a r4000 chip bug where an
    00414         //      address privilege violation is reported as a data bus error
    00415         //      on a load or store instruction that is the last instruction
    00416         //      in a page.
    00417         //
    00418
    00419         if ((ExceptionRecord->ExceptionInformation[1] < 0x80000000) &&
    00420             (((ULONG)ExceptionRecord->ExceptionAddress & 0xffc) == 0xffc) &&
    00421             (PreviousMode != KernelMode)) {
    00422             if (KiEmulateReference(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE) {
    00423                 KeGetCurrentPrcb()->KeAlignmentFixupCount += 1;
    00424                 goto Handled2;
    00425             }
    00426         }
    00427
    00428         KiDataBusError(ExceptionRecord, ExceptionFrame, TrapFrame);
    00429         goto Handled2;
    00430     }
    00431
    00432     //
    00433     // If the exception is an instruction bus error, then process the error.
    00434     //
    00435     // N.B. A special exception code is used to signal an instruction bus
    00436     //      error. This code is equivalent to the bug check code merged
    00437     //      with a reserved facility code and the reserved bit set.
    00438     //
    00439     // N.B. If control returns, then it is assumed that the error hand been
    00440     //      corrected.
    00441     //
    00442
    00443     if (ExceptionRecord->ExceptionCode == (INSTRUCTION_BUS_ERROR | 0xdfff0000)) {
    00444         KiInstructionBusError(ExceptionRecord, ExceptionFrame, TrapFrame);
    00445         goto Handled2;
    00446     }
    00447
    00448     //
    00449     // If the exception is a data misalignment, this is the first change for
    00450     // handling the exception, and the current thread has enabled automatic
    00451     // alignment fixup, then attempt to emulate the unaligned reference.
    00452     //
    00453
    00454     if ((ExceptionRecord->ExceptionCode == STATUS_DATATYPE_MISALIGNMENT) &&
    00455         (FirstChance != FALSE) &&
    00456         ((KeGetCurrentThread()->AutoAlignment != FALSE) ||
    00457          (KeGetCurrentThread()->ApcState.Process->AutoAlignment != FALSE) ||
    00458          (((ExceptionRecord->ExceptionInformation[1] & 0x7fff0000) == 0x7fff0000) &&
    00459          (PreviousMode != KernelMode))) &&
    00460         (KiEmulateReference(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE)) {
    00461         KeGetCurrentPrcb()->KeAlignmentFixupCount += 1;
    00462         goto Handled2;
    00463     }
    00464
    00465     //
    00466     // If the exception is a floating exception, then attempt to emulate the
    00467     // operation.
    00468     //
    00469     // N.B. The pseudo status STATUS_FLOAT_STACK_CHECK is used to signify
    00470     //      that the exception is a floating exception and that this it the
    00471     //      first chance for handling the exception. The floating emulation
    00472     //      routine converts the status code to the proper floating status
    00473     //      value.
    00474     //
    00475
    00476     if ((ExceptionRecord->ExceptionCode == STATUS_FLOAT_STACK_CHECK) &&
    00477         (KiEmulateFloating(ExceptionRecord, ExceptionFrame, TrapFrame) != FALSE)) {
    00478         TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, PreviousMode);
    00479         goto Handled2;
    00480     }
    00481
    00482     //
    00483     // If the exception is a breakpoint, then translate it to an appropriate
    00484     // exception code if it is a division by zero or an integer overflow
    00485     // caused by multiplication.
    00486     //
    00487
    00488     if (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) {
    00489         if (ExceptionRecord->ExceptionInformation[0] == DIVIDE_BREAKPOINT) {
    00490             ExceptionRecord->ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
    00491
    00492         } else if ((ExceptionRecord->ExceptionInformation[0] == MULTIPLY_BREAKPOINT) ||
    00493                    (ExceptionRecord->ExceptionInformation[0] == OVERFLOW_BREAKPOINT)) {
    00494             ExceptionRecord->ExceptionCode = STATUS_INTEGER_OVERFLOW;
    00495
    00496         } else if (ExceptionRecord->ExceptionInformation[0] == KDDEBUG_BREAKPOINT) {
    00497             TrapFrame->Fir += 4;
    00498         }
    00499     }
    00500
    00501     //
    00502     // Move machine state from trap and exception frames to a context frame,
    00503     // and increment the number of exceptions dispatched.
    00504     //
    00505
    00506     ContextFrame.ContextFlags = CONTEXT_FULL;
    00507     KeContextFromKframes(TrapFrame, ExceptionFrame, &ContextFrame);
    00508     KeGetCurrentPrcb()->KeExceptionDispatchCount += 1;
    00509
    00510     //
    00511     // Select the method of handling the exception based on the previous mode.
    00512     //
    00513
    00514     if (PreviousMode == KernelMode) {
    00515
    00516         //
    00517         // Previous mode was kernel.
    00518         //
    00519         // If this is the first chance, the kernel debugger is active, and
    00520         // the exception is a kernel breakpoint, then give the kernel debugger
    00521         // a chance to handle the exception.
    00522         //
    00523         // If this is the first chance and the kernel debugger is not active
    00524         // or does not handle the exception, then attempt to find a frame
    00525         // handler to handle the exception.
    00526         //
    00527         // If this is the second chance or the exception is not handled, then
    00528         // if the kernel debugger is active, then give the kernel debugger a
    00529         // second chance to handle the exception. If the kernel debugger does
    00530         // not handle the exception, then bug check.
    00531         //
    00532
    00533         if (FirstChance != FALSE) {
    00534
    00535             //
    00536             // If the kernel debugger is active, the exception is a breakpoint,
    00537             // and the breakpoint is handled by the kernel debugger, then give
    00538             // the kernel debugger a chance to handle the exception.
    00539             //
    00540
    00541             if ((KiDebugRoutine != NULL) &&
    00542                (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
    00543                (KdIsThisAKdTrap(ExceptionRecord,
    00544                                 &ContextFrame,
    00545                                 KernelMode) != FALSE)) {
    00546
    00547                 if (((KiDebugRoutine) (TrapFrame,
    00548                                        ExceptionFrame,
    00549                                        ExceptionRecord,
    00550                                        &ContextFrame,
    00551                                        KernelMode,
    00552                                        FALSE)) != FALSE) {
    00553
    00554                     goto Handled1;
    00555                 }
    00556             }
    00557
    00558             //
    00559             // This is the first chance to handle the exception.
    00560             //
    00561
    00562             if (RtlDispatchException(ExceptionRecord, &ContextFrame) != FALSE) {
    00563                 goto Handled1;
    00564             }
    00565         }
    00566
    00567         //
    00568         // This is the second chance to handle the exception.
    00569         //
    00570
    00571         if (KiDebugRoutine != NULL) {
    00572             if (((KiDebugRoutine) (TrapFrame,
    00573                                    ExceptionFrame,
    00574                                    ExceptionRecord,
    00575                                    &ContextFrame,
    00576                                    PreviousMode,
    00577                                    TRUE)) != FALSE) {
    00578                 goto Handled1;
    00579             }
    00580         }
    00581
    00582         KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
    00583                      ExceptionRecord->ExceptionCode,
    00584                      (ULONG)ExceptionRecord->ExceptionAddress,
    00585                      ExceptionRecord->ExceptionInformation[0],
    00586                      ExceptionRecord->ExceptionInformation[1]);
    00587
    00588     } else {
    00589
    00590         //
    00591         // Previous mode was user.
    00592         //
    00593         // If this is the first chance, the kernel debugger is active, the
    00594         // exception is a kernel breakpoint, and the current process is not
    00595         // being debugged, or the current process is being debugged, but the
    00596         // the breakpoint is not a kernel breakpoint instruction, then give
    00597         // the kernel debugger a chance to handle the exception.
    00598         //
    00599         // If this is the first chance and the current process has a debugger
    00600         // port, then send a message to the debugger port and wait for a reply.
    00601         // If the debugger handles the exception, then continue execution. Else
    00602         // transfer the exception information to the user stack, transition to
    00603         // user mode, and attempt to dispatch the exception to a frame based
    00604         // handler. If a frame based handler handles the exception, then continue
    00605         // execution. Otherwise, execute the raise exception system service
    00606         // which will call this routine a second time to process the exception.
    00607         //
    00608         // If this is the second chance and the current process has a debugger
    00609         // port, then send a message to the debugger port and wait for a reply.
    00610         // If the debugger handles the exception, then continue execution. Else
    00611         // if the current process has a subsystem port, then send a message to
    00612         // the subsystem port and wait for a reply. If the subsystem handles the
    00613         // exception, then continue execution. Else terminate the thread.
    00614         //
    00615
    00616         if (FirstChance != FALSE) {
    00617
    00618             //
    00619             // If the kernel debugger is active, the exception is a kernel
    00620             // breakpoint, and the current process is not being debugged,
    00621             // or the current process is being debugged, but the breakpoint
    00622             // is not a kernel breakpoint instruction, then give the kernel
    00623             // debugger a chance to handle the exception.
    00624             //
    00625
    00626             if ((KiDebugRoutine != NULL) &&
    00627                (ExceptionRecord->ExceptionCode == STATUS_BREAKPOINT) &&
    00628                (KdIsThisAKdTrap(ExceptionRecord,
    00629                                 &ContextFrame,
    00630                                 UserMode) != FALSE) &&
    00631                ((PsGetCurrentProcess()->DebugPort == NULL) ||
    00632                ((PsGetCurrentProcess()->DebugPort != NULL) &&
    00633                (ExceptionRecord->ExceptionInformation[0] !=
    00634                                             KERNEL_BREAKPOINT_INSTRUCTION)))) {
    00635
    00636                if (((KiDebugRoutine) (TrapFrame,
    00637                                       ExceptionFrame,
    00638                                       ExceptionRecord,
    00639                                       &ContextFrame,
    00640                                       UserMode,
    00641                                       FALSE)) != FALSE) {
    00642
    00643                     goto Handled1;
    00644                 }
    00645             }
    00646
    00647             //
    00648             // This is the first chance to handle the exception.
    00649             //
    00650
    00651             if (DbgkForwardException(ExceptionRecord, TRUE, FALSE)) {
    00652                 TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, UserMode);
    00653                 goto Handled2;
    00654             }
    00655
    00656             //
    00657             // Transfer exception information to the user stack, transition
    00658             // to user mode, and attempt to dispatch the exception to a frame
    00659             // based handler.
    00660             //
    00661
    00662         repeat:
    00663             try {
    00664
    00665                 //
    00666                 // Coerce the 64-bit integer register context to 32-bits
    00667                 // and store in the 32-bit context area of the context
    00668                 // record.
    00669                 //
    00670                 // N.B. This only works becasue the 32- and 64-bit integer
    00671                 //      register context does not overlap in the context
    00672                 //      record.
    00673                 //
    00674
    00675                 Destination = &ContextFrame.IntZero;
    00676                 Source = &ContextFrame.XIntZero;
    00677                 for (Index = 0; Index < 32; Index += 1) {
    00678                     *Destination++ = (ULONG)*Source++;
    00679                 }
    00680
    00681                 //
    00682                 // Compute length of exception record and new aligned stack
    00683                 // address.
    00684                 //
    00685
    00686                 Length = (sizeof(EXCEPTION_RECORD) + 7) & (~7);
    00687                 UserStack1 = (ULONG)(ContextFrame.XIntSp & (~7)) - Length;
    00688
    00689                 //
    00690                 // Probe user stack area for writeability and then transfer the
    00691                 // exception record to the user stack area.
    00692                 //
    00693
    00694                 ProbeForWrite((PCHAR)UserStack1, Length, sizeof(QUAD));
    00695                 RtlMoveMemory((PVOID)UserStack1, ExceptionRecord, Length);
    00696
    00697                 //
    00698                 // Compute length of context record and new aligned user stack
    00699                 // pointer.
    00700                 //
    00701
    00702                 Length = sizeof(CONTEXT);
    00703                 UserStack2 = UserStack1 - Length;
    00704
    00705                 //
    00706                 // Probe user stack area for writeability and then transfer the
    00707                 // context record to the user stack.
    00708                 //
    00709
    00710                 ProbeForWrite((PCHAR)UserStack2, Length, sizeof(QUAD));
    00711                 RtlMoveMemory((PVOID)UserStack2, &ContextFrame, sizeof(CONTEXT));
    00712
    00713                 //
    00714                 // Set address of exception record, context record, and the
    00715                 // and the new stack pointer in the current trap frame.
    00716                 //
    00717
    00718                 TrapFrame->XIntSp = (LONG)UserStack2;
    00719                 TrapFrame->XIntS8 = (LONG)UserStack2;
    00720                 TrapFrame->XIntS0 = (LONG)UserStack1;
    00721                 TrapFrame->XIntS1 = (LONG)UserStack2;
    00722
    00723                 //
    00724                 // Sanitize the floating status register so a recursive
    00725                 // exception will not occur.
    00726                 //
    00727
    00728                 TrapFrame->Fsr = SANITIZE_FSR(ContextFrame.Fsr, UserMode);
    00729
    00730                 //
    00731                 // Set the address of the exception routine that will call the
    00732                 // exception dispatcher and then return to the trap handler.
    00733                 // The trap handler will restore the exception and trap frame
    00734                 // context and continue execution in the routine that will
    00735                 // call the exception dispatcher.
    00736                 //
    00737
    00738                 TrapFrame->Fir = KeUserExceptionDispatcher;
    00739                 return;
    00740
    00741             //
    00742             // If an exception occurs, then copy the new exception information
    00743             // to an exception record and handle the exception.
    00744             //
    00745
    00746             } except (KiCopyInformation(&ExceptionRecord1,
    00747                                (GetExceptionInformation())->ExceptionRecord)) {
    00748
    00749                 //
    00750                 // If the exception is a stack overflow, then attempt
    00751                 // to raise the stack overflow exception. Otherwise,
    00752                 // the user's stack is not accessible, or is misaligned,
    00753                 // and second chance processing is performed.
    00754                 //
    00755
    00756                 if (ExceptionRecord1.ExceptionCode == STATUS_STACK_OVERFLOW) {
    00757                     ExceptionRecord1.ExceptionAddress = ExceptionRecord->ExceptionAddress;
    00758                     RtlMoveMemory((PVOID)ExceptionRecord,
    00759                                   &ExceptionRecord1, sizeof(EXCEPTION_RECORD));
    00760                     goto repeat;
    00761                 }
    00762             }
    00763         }
    00764
    00765         //
    00766         // This is the second chance to handle the exception.
    00767         //
    00768
    00769         UserApcPending = KeGetCurrentThread()->ApcState.UserApcPending;
    00770         if (DbgkForwardException(ExceptionRecord, TRUE, TRUE)) {
    00771             TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, UserMode);
    00772             goto Handled2;
    00773
    00774         } else if (DbgkForwardException(ExceptionRecord, FALSE, TRUE)) {
    00775
    00776             //
    00777             // If a user APC was not previously pending and one is now
    00778             // pending, then the thread has been terminated and the PC
    00779             // must be forced to a legal address so an infinite loop does
    00780             // not occur for the case where a jump to an unmapped address
    00781             // occured.
    00782             //
    00783
    00784             if ((UserApcPending == FALSE) &&
    00785                 (KeGetCurrentThread()->ApcState.UserApcPending != FALSE)) {
    00786                 TrapFrame->Fir = (ULONG)USPCR;
    00787             }
    00788
    00789             TrapFrame->Fsr = SANITIZE_FSR(TrapFrame->Fsr, UserMode);
    00790             goto Handled2;
    00791
    00792         } else {
    00793             ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode);
    00794             KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED,
    00795                          ExceptionRecord->ExceptionCode,
    00796                          (ULONG)ExceptionRecord->ExceptionAddress,
    00797                          ExceptionRecord->ExceptionInformation[0],
    00798                          ExceptionRecord->ExceptionInformation[1]);
    00799         }
    00800     }
    00801
    00802     //
    00803     // Move machine state from context frame to trap and exception frames and
    00804     // then return to continue execution with the restored state.
    00805     //
    00806
    00807 Handled1:
    00808     KeContextToKframes(TrapFrame, ExceptionFrame, &ContextFrame,
    00809                        ContextFrame.ContextFlags, PreviousMode);
    00810
    00811     //
    00812     // Exception was handled by the debugger or the associated subsystem
    00813     // and state was modified, if necessary, using the get state and set
    00814     // state capabilities. Therefore the context frame does not need to
    00815     // be transfered to the trap and exception frames.
    00816     //
    00817
    00818 Handled2:
    00819     return;
    00820 }