Trap handlers in C Patch 5 of X:

[NDK]:  Add FSW defines for FPU exception bits.
    [NTOS]: Convert trap 19 (XMMI exception) to C.

svn path=/trunk/; revision=45010
This commit is contained in:
Sir Richard 2010-01-08 19:24:10 +00:00
parent 733c152673
commit 8d89e2b027
5 changed files with 122 additions and 172 deletions

View file

@ -105,6 +105,17 @@ Author:
#define EFLAG_SIGN 0x8000
#define EFLAG_ZERO 0x4000
//
// Legacy floating status word bit masks.
//
#define FSW_INVALID_OPERATION 0x1
#define FSW_DENORMAL 0x2
#define FSW_ZERO_DIVIDE 0x4
#define FSW_OVERFLOW 0x8
#define FSW_UNDERFLOW 0x10
#define FSW_PRECISION 0x20
#define FSW_STACK_FAULT 0x40
//
// IPI Types
//

View file

@ -14,6 +14,22 @@
: /* no input */ \
: "memory");
FORCEINLINE
VOID
Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea)
{
extern ULONG KeI386FxsrPresent;
if (KeI386FxsrPresent)
{
__asm__ __volatile__ ("fxsave %0\n" : : "m"(SaveArea));
}
else
{
__asm__ __volatile__ ("fnsave %0\n wait\n" : : "m"(SaveArea));
}
}
FORCEINLINE
USHORT
Ke386GetLocalDescriptorTable()

View file

@ -220,6 +220,17 @@ KiDispatchException0Args(IN NTSTATUS Code,
KiDispatchExceptionFromTrapFrame(Code, Address, 0, 0, 0, 0, TrapFrame);
}
VOID
FORCEINLINE
KiDispatchException1Args(IN NTSTATUS Code,
IN ULONG_PTR Address,
IN ULONG P1,
IN PKTRAP_FRAME TrapFrame)
{
/* Helper for exceptions with no arguments */
KiDispatchExceptionFromTrapFrame(Code, Address, 1, P1, 0, 0, TrapFrame);
}
VOID
FORCEINLINE
KiDispatchException2Args(IN NTSTATUS Code,

View file

@ -1524,178 +1524,7 @@ _KiTrap16:
.endfunc
GENERATE_TRAP_HANDLER KiTrap17, 1
.func KiTrap19
TRAP_FIXUPS kit19_a, kit19_t, DoFixupV86, DoNotFixupAbios
_KiTrap19:
/* Push error code */
push 0
/* Enter trap */
TRAP_PROLOG kit19_a, kit19_t
/* Check if this is the NPX Thread */
mov eax, PCR[KPCR_CURRENT_THREAD]
cmp eax, PCR[KPCR_NPX_THREAD]
/* If this is a valid fault, handle it */
jz HandleXmmiFault
/* Otherwise, bugcheck */
mov eax, 19
jmp _KiSystemFatalException
HandleXmmiFault:
/* Get the initial stack and NPX frame */
mov ecx, [eax+KTHREAD_INITIAL_STACK]
lea ecx, [ecx-NPX_FRAME_LENGTH]
/* Check if the trap came from V86 mode */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz V86Xmmi
/* Check if it came from kernel mode */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz KernelXmmi
/* Check if it came from a VDM */
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jne VdmXmmi
HandleUserXmmi:
/* Set new CR0 */
mov ebx, cr0
and ebx, ~(CR0_MP + CR0_EM + CR0_TS)
mov cr0, ebx
/* Check if we have FX support */
test byte ptr _KeI386FxsrPresent, 1
jz XmmiFnSave2
/* Save the state */
fxsave [ecx]
jmp XmmiMakeCr0Dirty
XmmiFnSave2:
fnsave [ecx]
wait
XmmiMakeCr0Dirty:
/* Make CR0 state not loaded */
or ebx, NPX_STATE_NOT_LOADED
or ebx, [ecx+FN_CR0_NPX_STATE]
mov cr0, ebx
/* Update NPX state */
mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
mov dword ptr PCR[KPCR_NPX_THREAD], 0
/* Clear the TS bit and re-enable interrupts */
and dword ptr [ecx+FN_CR0_NPX_STATE], ~CR0_TS
/* Re-enable interrupts for user-mode and send the exception */
sti
mov ebx, [ebp+KTRAP_FRAME_EIP]
/* Get MxCSR and get current mask (bits 7-12) */
movzx eax, word ptr [ecx+FX_MXCSR]
mov edx, eax
shr edx, 7
not edx
/* Set faulting opcode address to 0 */
mov esi, 0
/* Apply legal exceptions mask */
and eax, 0x3f
/* Apply the mask we got in MXCSR itself */
and eax, edx
/* Check for invalid operation */
test al, 1
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
jmp _DispatchOneParamZero
1:
/* Check for zero divide */
test al, 2
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
jmp _DispatchOneParamZero
1:
/* Check for denormal */
test al, 4
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_MULTIPLE_TRAPS
jmp _DispatchOneParamZero
1:
/* Check for overflow*/
test al, 8
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
jmp _DispatchOneParamZero
1:
/* Check for denormal */
test al, 16
jz 1f
/* Raise exception */
mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
jmp _DispatchOneParamZero
1:
/* Check for Precision */
test al, 32
jz UnexpectedXmmi
/* Raise exception */
mov eax, STATUS_FLOAT_MULTIPLE_FAULTS
jmp _DispatchOneParamZero
UnexpectedXmmi:
/* Strange result, bugcheck the OS */
sti
push ebp
push 1
push 0
push eax
push 13
push TRAP_CAUSE_UNKNOWN
call _KeBugCheckWithTf@24
VdmXmmi:
/* Check if this is a VDM */
mov eax, PCR[KPCR_CURRENT_THREAD]
mov ebx, [eax+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz HandleUserXmmi
V86Xmmi:
/* V86 XMMI not handled */
UNHANDLED_V86_PATH
KernelXmmi:
/* Another weird situation */
push ebp
push 2
push 0
push eax
push 13
push TRAP_CAUSE_UNKNOWN
call _KeBugCheckWithTf@24
.endfunc
GENERATE_TRAP_HANDLER KiTrap19, 1
.func KiSystemFatalException
_KiSystemFatalException:

View file

@ -593,6 +593,89 @@ KiTrap17Handler(IN PKTRAP_FRAME TrapFrame)
KiSystemFatalException(EXCEPTION_ALIGNMENT_CHECK, TrapFrame);
}
VOID
FASTCALL
KiTrap19Handler(IN PKTRAP_FRAME TrapFrame)
{
PKTHREAD Thread;
PFX_SAVE_AREA SaveArea;
ULONG Cr0, MxCsrMask, Error;
/* Save trap frame */
KiEnterTrap(TrapFrame);
/* Check if this is the NPX thrad */
Thread = KeGetCurrentThread();
if (Thread != KeGetCurrentPrcb()->NpxThread)
{
/* It isn't, kill the system */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, (ULONG_PTR)Thread, 0, 0, TrapFrame);
}
/* Get the NPX frame */
SaveArea = (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack - sizeof(FX_SAVE_AREA));
/* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
/* Check for user trap */
if (!KiUserTrap(TrapFrame))
{
/* Kernel should not fault on XMMI */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, 0, 0, 2, TrapFrame);
}
/* Update CR0 */
Cr0 = __readcr0();
Cr0 &= ~(CR0_MP | CR0_EM | CR0_TS);
__writecr0(Cr0);
/* Save FPU state */
Ke386SaveFpuState(SaveArea);
/* Mark CR0 state dirty */
Cr0 |= NPX_STATE_NOT_LOADED;
Cr0 |= SaveArea->Cr0NpxState;
/* Update NPX state */
Thread->NpxState = NPX_STATE_NOT_LOADED;
KeGetCurrentPrcb()->NpxThread = NULL;
/* Clear the TS bit and re-enable interrupts */
SaveArea->Cr0NpxState &= ~CR0_TS;
_enable();
/* Now look at MxCsr to get the mask of errors we should care about */
MxCsrMask = ~((USHORT)SaveArea->U.FxArea.MXCsr >> 7);
/* Get legal exceptions that software should handle */
Error = (USHORT)SaveArea->U.FxArea.MXCsr & (FSW_INVALID_OPERATION |
FSW_DENORMAL |
FSW_ZERO_DIVIDE |
FSW_OVERFLOW |
FSW_UNDERFLOW |
FSW_PRECISION);
Error &= MxCsrMask;
/* Now handle any of those legal errors */
if (Error & (FSW_INVALID_OPERATION |
FSW_DENORMAL |
FSW_ZERO_DIVIDE |
FSW_OVERFLOW |
FSW_UNDERFLOW |
FSW_PRECISION))
{
/* By issuing an exception */
KiDispatchException1Args(STATUS_FLOAT_MULTIPLE_TRAPS,
TrapFrame->Eip,
0,
TrapFrame);
}
/* Unknown XMMI fault */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, 0, 0, 1, TrapFrame);
}
VOID
FASTCALL
KiRaiseAssertionHandler(IN PKTRAP_FRAME TrapFrame)