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(a)reactos.org>)g>):
[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/…
==============================================================================
--- 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?re…
==============================================================================
--- 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.…
==============================================================================
--- 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,