Author: sir_richard Date: Fri Jan 8 19:21:47 2010 New Revision: 45005
URL: http://svn.reactos.org/svn/reactos?rev=45005&view=rev Log: Trap Handlers in C Patch 3 of X (Patch by Sir_Richard ros.arm@reactos.org): [NTOS]: Fix a bug in the assertion handler. [NTOS]: Implement page fault trap (14) in C instead of ASM. [NTOS]: Implement V8086 trap entry/exit, we were hitting these during page faults in Ke386CallBios for video reset during GUI boot.
Modified: 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/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 19:21:47 2010 @@ -9,7 +9,6 @@ // // Debug Macros // -#if YDEBUG VOID NTAPI KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame) @@ -52,6 +51,7 @@ DPRINT1("V86Gs: %x\n", TrapFrame->V86Gs); }
+#if YDEBUG FORCEINLINE VOID KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame) @@ -220,6 +220,18 @@ KiDispatchExceptionFromTrapFrame(Code, Address, 0, 0, 0, 0, TrapFrame); }
+VOID +FORCEINLINE +KiDispatchException2Args(IN NTSTATUS Code, + IN ULONG_PTR Address, + IN ULONG P1, + IN ULONG P2, + IN PKTRAP_FRAME TrapFrame) +{ + /* Helper for exceptions with no arguments */ + KiDispatchExceptionFromTrapFrame(Code, Address, 2, P1, P2, 0, TrapFrame); +} + FORCEINLINE VOID KiTrapReturn(IN PKTRAP_FRAME TrapFrame)
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 19:21:47 2010 @@ -58,6 +58,10 @@ .globl _KiTrap8 .globl _KiTrap19
+/* System call code referenced from C code */ +.globl _CopyParams +.globl _ReadBatch + /* System call entrypoints: */ .globl _KiFastCallEntry .globl _KiSystemService @@ -193,7 +197,7 @@
/* Check if we should flush the User Batch */ xor ebx, ebx -ReadBatch: +_ReadBatch: or ebx, [ecx+TEB_GDI_BATCH_COUNT] jz NotWin32K
@@ -239,7 +243,7 @@ cmp esi, _MmUserProbeAddress jnb AccessViolation
-CopyParams: +_CopyParams: /* Copy the parameters */ rep movsd
@@ -359,7 +363,7 @@ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
/* It's fine, go ahead with it */ - jz CopyParams + jz _CopyParams
/* Caller sent invalid parameters, fail here */ mov eax, STATUS_ACCESS_VIOLATION @@ -1219,9 +1223,9 @@ test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK jnz UserModeGpf
- /* Check if we have a VDM alert */ - cmp dword ptr PCR[KPCR_VDM_ALERT], 0 - jnz VdmAlertGpf + ///* Check if we have a VDM alert */ + //cmp dword ptr PCR[KPCR_VDM_ALERT], 0 // BUGBUG: Add this back later + //jnz VdmAlertGpf
/* Check for GPF during GPF */ mov eax, [ebp+KTRAP_FRAME_EIP] @@ -1607,203 +1611,7 @@ UNHANDLED_V86_PATH .endfunc
-.func KiTrap14 -TRAP_FIXUPS kite_a, kite_t, DoFixupV86, DoNotFixupAbios -_KiTrap14: - - /* Enter trap */ - TRAP_PROLOG kite_a, kite_t - - /* Check if we have a VDM alert */ - cmp dword ptr PCR[KPCR_VDM_ALERT], 0 - jnz VdmAlertGpf - - /* Get the current thread */ - mov edi, PCR[KPCR_CURRENT_THREAD] - - /* Get the stack address of the frame */ - lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH] - sub eax, [edi+KTHREAD_INITIAL_STACK] - jz NoFixUp - - /* This isn't the base frame, check if it's the second */ - cmp eax, -KTRAP_FRAME_EFLAGS - jb NoFixUp - - /* Check if we have a TEB */ - mov eax, PCR[KPCR_TEB] - or eax, eax - jle NoFixUp - - /* Fixup the frame */ - call _KiFixupFrame - - /* Save CR2 */ -NoFixUp: - mov edi, cr2 - - /* Check if this processor has the cmpxchg8b lock errata */ - cmp byte ptr _KiI386PentiumLockErrataPresent, 0 - jnz HandleLockErrata - -NotLockErrata: - /* HACK: Handle page faults with interrupts disabled */ - test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK - je HandlePf - - /* Enable interrupts and check if we got here with interrupts disabled */ - sti -#ifdef HACK_ABOVE_FIXED - test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK - jz IllegalState -#endif - -HandlePf: - /* Send trap frame and check if this is kernel-mode or usermode */ - push ebp - mov eax, [ebp+KTRAP_FRAME_CS] - and eax, MODE_MASK - push eax - - /* Send faulting address and check if this is read or write */ - push edi - mov eax, [ebp+KTRAP_FRAME_ERROR_CODE] - and eax, 1 - push eax - - /* Call the access fault handler */ - call _MmAccessFault@16 - test eax, eax - jl AccessFail - - /* Access fault handled, return to caller */ - jmp _Kei386EoiHelper@0 - -AccessFail: - /* First check if this is a fault in the S-LIST functions */ - mov ecx, offset _ExpInterlockedPopEntrySListFault@0 - cmp [ebp+KTRAP_FRAME_EIP], ecx - jz SlistFault - - /* Check if this is a fault in the syscall handler */ - mov ecx, offset CopyParams - cmp [ebp+KTRAP_FRAME_EIP], ecx - jz SysCallCopyFault - mov ecx, offset ReadBatch - cmp [ebp+KTRAP_FRAME_EIP], ecx - jnz CheckVdmPf - - /* FIXME: TODO */ - UNHANDLED_PATH "SYSENTER Fault" - jmp _Kei386EoiHelper@0 - -SysCallCopyFault: - /* FIXME: TODO */ - UNHANDLED_PATH "SYSENTER Fault" - jmp _Kei386EoiHelper@0 - - /* Check if the fault occured in a V86 mode */ -CheckVdmPf: - mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE] - shr ecx, 1 - and ecx, 1 - test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK - jnz VdmPF - - /* Check if the fault occured in a VDM */ - mov esi, PCR[KPCR_CURRENT_THREAD] - mov esi, [esi+KTHREAD_APCSTATE_PROCESS] - cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0 - jz CheckStatus - - /* Check if we this was in kernel-mode */ - test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK - jz CheckStatus - cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK - jz CheckStatus - -VdmPF: - /* FIXME: TODO */ - UNHANDLED_V86_PATH - - /* Save EIP and check what kind of status failure we got */ -CheckStatus: - mov esi, [ebp+KTRAP_FRAME_EIP] - cmp eax, STATUS_ACCESS_VIOLATION - je AccessViol - cmp eax, STATUS_GUARD_PAGE_VIOLATION - je SpecialCode - cmp eax, STATUS_STACK_OVERFLOW - je SpecialCode - - /* Setup an in-page exception to dispatch */ - mov edx, ecx - mov ebx, esi - mov esi, edi - mov ecx, 3 - mov edi, eax - mov eax, STATUS_IN_PAGE_ERROR - call _CommonDispatchException - -AccessViol: - /* Use more proper status code */ - mov eax, KI_EXCEPTION_ACCESS_VIOLATION - -SpecialCode: - /* Setup a normal page fault exception */ - mov ebx, esi - mov edx, ecx - mov esi, edi - jmp _DispatchTwoParam - -SlistFault: - /* FIXME: TODO */ - UNHANDLED_PATH "SLIST Fault" - -IllegalState: - - /* This is completely illegal, bugcheck the system */ - push ebp - push esi - push ecx - push eax - push edi - push IRQL_NOT_LESS_OR_EQUAL - call _KeBugCheckWithTf@24 - -VdmAlertGpf: - - /* FIXME: NOT SUPPORTED */ - UNHANDLED_V86_PATH - -HandleLockErrata: - - /* Fail if this isn't a write fault */ - test word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0x4 - jnz NotLockErrata - - /* Also make sure the page fault is for IDT entry 6 */ - mov eax, PCR[KPCR_IDT] - add eax, 0x30 - cmp eax, edi - jne NotLockErrata - - /* - * This is a write fault to the Invalid Opcode handler entry. - * We assume this is the lock errata and not a real write fault. - */ - - /* Clear the error code */ - and dword ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0 - - /* Check if this happened in V86 mode */ - test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK - jnz VdmOpCodeFault - - /* Dispatch this to the invalid opcode handler */ - jmp DispatchLockErrata -.endfunc - +GENERATE_TRAP_HANDLER KiTrap14, 0 GENERATE_TRAP_HANDLER KiTrap0F, 1
.func KiTrap16
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 19:21:47 2010 @@ -43,13 +43,8 @@ }
/* Check if this was a V8086 trap */ - if (TrapFrame->EFlags & EFLAGS_V86_MASK) - { - /* Not handled yet */ - UNIMPLEMENTED; - while (TRUE); - } - + if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturn(TrapFrame); + /* Check if the trap frame was edited */ if (!(TrapFrame->SegCs & FRAME_EDITED)) { @@ -155,8 +150,11 @@ /* Check for V86 mode */ if (TrapFrame->EFlags & EFLAGS_V86_MASK) { - UNIMPLEMENTED; - while (TRUE); + /* Restore V8086 segments into Protected Mode segments */ + TrapFrame->SegFs = TrapFrame->V86Fs; + TrapFrame->SegGs = TrapFrame->V86Gs; + TrapFrame->SegDs = TrapFrame->V86Ds; + TrapFrame->SegEs = TrapFrame->V86Es; }
/* Clear direction flag */ @@ -404,6 +402,130 @@
VOID FASTCALL +KiTrap14Handler(IN PKTRAP_FRAME TrapFrame) +{ + PKTHREAD Thread; + ULONG_PTR Cr2; + NTSTATUS Status; + extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID); + extern VOID CopyParams(VOID); + extern VOID ReadBatch(VOID); + + /* Save trap frame */ + KiEnterTrap(TrapFrame); + + /* Check for custom VDM trap handler */ + if (KeGetPcr()->VdmAlert) + { + /* Not implemented */ + UNIMPLEMENTED; + while (TRUE); + } + + /* Check if this is the base frame */ + Thread = KeGetCurrentThread(); + if (KeGetTrapFrame(Thread) != TrapFrame) + { + /* It isn't, check if this is a second nested frame */ + if (((ULONG_PTR)KeGetTrapFrame(Thread) - (ULONG_PTR)TrapFrame) <= + FIELD_OFFSET(KTRAP_FRAME, EFlags)) + { + /* The stack is somewhere in between frames, we need to fix it */ + UNIMPLEMENTED; + while (TRUE); + } + } + + /* Save CR2 */ + Cr2 = __readcr2(); + + /* Check for Pentium LOCK errata */ + if (KiI386PentiumLockErrataPresent) + { + /* Not yet implemented */ + UNIMPLEMENTED; + while (TRUE); + } + + /* HACK: Check if interrupts are disabled and enable them */ + if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK)) + { + /* Enable interupts */ + _enable(); +#ifdef HACK_ABOVE_FIXED + if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK)) + { + /* This is illegal */ + KeBugCheckWithTf(IRQL_NOT_LESS_OR_EQUAL, + Cr2, + -1, + TrapFrame->ErrCode & 1, + TrapFrame->Eip, + TrapFrame); + } +#endif + } + + /* Call the access fault handler */ + Status = MmAccessFault(TrapFrame->ErrCode & 1, + (PVOID)Cr2, + TrapFrame->SegCs & MODE_MASK, + TrapFrame); + if (Status == STATUS_SUCCESS) KiEoiHelper(TrapFrame); + + /* Check for S-LIST fault */ + if (TrapFrame->Eip == (ULONG_PTR)ExpInterlockedPopEntrySListFault) + { + /* Not yet implemented */ + UNIMPLEMENTED; + while (TRUE); + } + + /* Check for syscall fault */ + if ((TrapFrame->Eip == (ULONG_PTR)CopyParams) || + (TrapFrame->Eip == (ULONG_PTR)ReadBatch)) + { + /* Not yet implemented */ + UNIMPLEMENTED; + while (TRUE); + } + + /* Check for VDM trap */ + ASSERT((KiVdmTrap(TrapFrame)) == FALSE); + + /* Either kernel or user trap (non VDM) so dispatch exception */ + if (Status == STATUS_ACCESS_VIOLATION) + { + /* This status code is repurposed so we can recognize it later */ + KiDispatchException2Args(KI_EXCEPTION_ACCESS_VIOLATION, + TrapFrame->Eip, + TrapFrame->ErrCode & 1, + Cr2, + TrapFrame); + } + else if ((Status == STATUS_GUARD_PAGE_VIOLATION) || + (Status == STATUS_STACK_OVERFLOW)) + { + /* These faults only have two parameters */ + KiDispatchException2Args(Status, + TrapFrame->Eip, + TrapFrame->ErrCode & 1, + Cr2, + TrapFrame); + } + + /* Only other choice is an in-page error, with 3 parameters */ + KiDispatchExceptionFromTrapFrame(STATUS_IN_PAGE_ERROR, + TrapFrame->Eip, + 3, + TrapFrame->ErrCode & 1, + Cr2, + Status, + TrapFrame); +} + +VOID +FASTCALL KiTrap0FHandler(IN PKTRAP_FRAME TrapFrame) { /* Save trap frame */ @@ -433,8 +555,8 @@ /* Save trap frame */ KiEnterTrap(TrapFrame);
- /* Increment EIP to skip the INT2C instruction (2 bytes, not 1 like INT3) */ - TrapFrame->Eip += 2; + /* Decrement EIP to point to the INT2C instruction (2 bytes, not 1 like INT3) */ + TrapFrame->Eip -= 2;
/* Dispatch the exception */ KiDispatchException0Args(STATUS_ASSERTION_FAILURE,