mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 09:25:10 +00:00
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:
parent
733c152673
commit
8d89e2b027
5 changed files with 122 additions and 172 deletions
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue