Author: sir_richard Date: Fri Jan 8 20:24:10 2010 New Revision: 45010
URL: http://svn.reactos.org/svn/reactos?rev=45010&view=rev Log: Trap handlers in C Patch 5 of X: [NDK]: Add FSW defines for FPU exception bits. [NTOS]: Convert trap 19 (XMMI exception) to C.
Modified: trunk/reactos/include/ndk/i386/ketypes.h trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h trunk/reactos/ntoskrnl/include/internal/trap_x.h trunk/reactos/ntoskrnl/ke/i386/trap.s trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/include/ndk/i386/ketypes.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/ndk/i386/ketypes.h?... ============================================================================== --- trunk/reactos/include/ndk/i386/ketypes.h [iso-8859-1] (original) +++ trunk/reactos/include/ndk/i386/ketypes.h [iso-8859-1] Fri Jan 8 20:24:10 2010 @@ -104,6 +104,17 @@ #define EFLAGS_USER_SANITIZE 0x3F4DD7 #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
Modified: trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h [iso-8859-1] Fri Jan 8 20:24:10 2010 @@ -13,6 +13,22 @@ : "=m" (*X) \ : /* 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
Modified: trunk/reactos/ntoskrnl/include/internal/trap_x.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/t... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] Fri Jan 8 20:24:10 2010 @@ -222,6 +222,17 @@
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, IN ULONG_PTR Address, IN ULONG P1,
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?rev... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Fri Jan 8 20:24:10 2010 @@ -1524,178 +1524,7 @@ .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:
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.c... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Fri Jan 8 20:24:10 2010 @@ -595,6 +595,89 @@
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) { /* Save trap frame */