Author: sir_richard Date: Sun Jan 10 16:00:44 2010 New Revision: 45028
URL: http://svn.reactos.org/svn/reactos?rev=45028&view=rev Log: [NTOS]: Simplify trap exit code. [NTOS]: Move some stuff in appropriate headers. [NTOS]: Write V86 fast entry/exit traps, needed for later.
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h trunk/reactos/ntoskrnl/include/internal/ke.h trunk/reactos/ntoskrnl/include/internal/trap_x.h trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h [iso-8859-1] Sun Jan 10 16:00:44 2010 @@ -65,7 +65,26 @@ // #define KeGetTrapFrameInterruptState(TrapFrame) \ BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK) - + +// +// Flags for exiting a trap +// +#define KTE_SKIP_PM_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipPreviousMode = TRUE } }).Bits) +#define KTE_SKIP_SEG_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipSegments = TRUE } }).Bits) +#define KTE_SKIP_VOL_BIT (((KTRAP_EXIT_SKIP_BITS) { { .SkipVolatiles = TRUE } }).Bits) + +typedef union _KTRAP_EXIT_SKIP_BITS +{ + struct + { + UCHAR SkipPreviousMode:1; + UCHAR SkipSegments:1; + UCHAR SkipVolatiles:1; + UCHAR Reserved:5; + }; + UCHAR Bits; +} KTRAP_EXIT_SKIP_BITS, *PKTRAP_EXIT_SKIP_BITS; + // // Registers an interrupt handler with an IDT vector // @@ -287,6 +306,25 @@ NTAPI Ki386EnableXMMIExceptions( IN ULONG_PTR Context +); + +BOOLEAN +NTAPI +VdmDispatchBop( + IN PKTRAP_FRAME TrapFrame +); + +BOOLEAN +FASTCALL +KiVdmOpcodePrefix( + IN PKTRAP_FRAME TrapFrame, + IN ULONG Flags +); + +BOOLEAN +FASTCALL +Ki386HandleOpcodeV86( + IN PKTRAP_FRAME TrapFrame );
// @@ -312,6 +350,10 @@ extern VOID __cdecl KiTrap8(VOID); extern VOID __cdecl KiTrap19(VOID); extern VOID __cdecl KiFastCallEntry(VOID); +extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID); +extern VOID __cdecl CopyParams(VOID); +extern VOID __cdecl ReadBatch(VOID); +extern VOID __cdecl FrRestore(VOID);
// // Sanitizes a selector
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Sun Jan 10 16:00:44 2010 @@ -71,20 +71,6 @@ PVOID Context; PVOID Handle; } KNMI_HANDLER_CALLBACK, *PKNMI_HANDLER_CALLBACK; - -typedef union _KTRAP_STATE_BITS -{ - struct - { - UCHAR SystemCall:1; - UCHAR PreviousMode:1; - UCHAR Segments:1; - UCHAR Volatiles:1; - UCHAR Full:1; - UCHAR Reserved:3; - }; - UCHAR Bits; -} KTRAP_STATE_BITS, *PKTRAP_STATE_BITS;
typedef PCHAR (NTAPI *PKE_BUGCHECK_UNICODE_TO_ANSI)(
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] Sun Jan 10 16:00:44 2010 @@ -66,7 +66,7 @@ FORCEINLINE VOID KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame, - IN KTRAP_STATE_BITS StateBits) + IN KTRAP_STATE_BITS SkipBits) { /* Make sure interrupts are disabled */ if (__readeflags() & EFLAGS_INTERRUPT_MASK) @@ -105,7 +105,7 @@ }
/* If we're ignoring previous mode, make sure caller doesn't actually want it */ - if (!(StateBits.PreviousMode) && (TrapFrame->PreviousPreviousMode != -1)) + if ((SkipBits.SkipPreviousMode) && (TrapFrame->PreviousPreviousMode != -1)) { DPRINT1("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx", TrapFrame->PreviousPreviousMode); while (TRUE);
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] Sun Jan 10 16:00:44 2010 @@ -18,16 +18,19 @@ VOID FASTCALL KiExitTrap(IN PKTRAP_FRAME TrapFrame, - IN UCHAR State) -{ - KTRAP_STATE_BITS StateBits = { .Bits = State }; - KiExitTrapDebugChecks(TrapFrame, StateBits); + IN UCHAR Skip) +{ + KTRAP_EXIT_SKIP_BITS SkipBits = { .Bits = Skip }; + KiExitTrapDebugChecks(TrapFrame, SkipBits); + + /* If you skip volatile reload, you must skip segment reload */ + ASSERT((SkipBits.SkipVolatiles == FALSE) || (SkipBits.SkipSegments == TRUE));
/* Restore the SEH handler chain */ KeGetPcr()->Tib.ExceptionList = TrapFrame->ExceptionList;
/* Check if the previous mode must be restored */ - if (StateBits.PreviousMode) + if (!SkipBits.SkipPreviousMode) { /* Not handled yet */ UNIMPLEMENTED; @@ -53,34 +56,31 @@ while (TRUE); }
- /* Check if all registers must be restored */ - if (StateBits.Full) - { - /* Only do the restore if we made a transition from user-mode */ - if (KiUserTrap(TrapFrame)) - { - /* Restore segments */ - Ke386SetGs(TrapFrame->SegGs); - Ke386SetEs(TrapFrame->SegEs); - Ke386SetDs(TrapFrame->SegDs); - } - } - - /* Check if we came from user-mode */ - if (KiUserTrap(TrapFrame)) - { - /* Check if the caller wants segments restored */ - if (StateBits.Segments) - { - /* Restore them */ - Ke386SetGs(TrapFrame->SegGs); - Ke386SetEs(TrapFrame->SegEs); - Ke386SetDs(TrapFrame->SegDs); - } - + /* Check if segments should be restored */ + if (!SkipBits.SkipSegments) + { + /* Restore segments */ + Ke386SetGs(TrapFrame->SegGs); + Ke386SetEs(TrapFrame->SegEs); + Ke386SetDs(TrapFrame->SegDs); + Ke386SetFs(TrapFrame->SegFs); + } + else if (KiUserTrap(TrapFrame)) + { /* Always restore FS since it goes from KPCR to TEB */ Ke386SetFs(TrapFrame->SegFs); } + + /* Check if the caller wants to skip volatiles */ + if (SkipBits.SkipVolatiles) + { + /* + * When we do the system call handler through this path, we need + * to have some sort to restore the kernel EAX instead of pushing + * back the user EAX. We'll figure it out... + */ + DPRINT1("Warning: caller doesn't want volatiles restored\n"); + }
/* Check for ABIOS code segment */ if (TrapFrame->SegCs == 0x80) @@ -90,8 +90,8 @@ while (TRUE); }
- /* Check for system call */ - if (StateBits.SystemCall) + /* Check for system call -- a system call skips volatiles! */ + if (SkipBits.SkipVolatiles) { /* Not handled yet */ UNIMPLEMENTED; @@ -106,6 +106,50 @@
VOID FASTCALL +KiExitV86Trap(IN PKTRAP_FRAME TrapFrame) +{ + PKTHREAD Thread; + KIRQL OldIrql; + + /* Get the thread */ + Thread = KeGetCurrentThread(); + while (TRUE) + { + /* Turn off the alerted state for kernel mode */ + Thread->Alerted[KernelMode] = FALSE; + + /* Are there pending user APCs? */ + if (!Thread->ApcState.UserApcPending) break; + + /* Raise to APC level and enable interrupts */ + OldIrql = KfRaiseIrql(APC_LEVEL); + _enable(); + + /* Deliver APCs */ + KiDeliverApc(UserMode, NULL, TrapFrame); + + /* Restore IRQL and disable interrupts once again */ + KfLowerIrql(OldIrql); + _disable(); + + /* Return if this isn't V86 mode anymore */ + if (TrapFrame->EFlags & EFLAGS_V86_MASK) return; + } + + /* If we got here, we're still in a valid V8086 context, so quit it */ + if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK) + { + /* Not handled yet */ + UNIMPLEMENTED; + while (TRUE); + } + + /* Return from interrupt */ + KiTrapReturn(TrapFrame); +} + +VOID +FASTCALL KiEoiHelper(IN PKTRAP_FRAME TrapFrame) { /* Disable interrupts until we return */ @@ -115,10 +159,38 @@ KiCheckForApcDelivery(TrapFrame);
/* Now exit the trap for real */ - KiExitTrap(TrapFrame, KTS_SEG_BIT | KTS_VOL_BIT); + KiExitTrap(TrapFrame, KTE_SKIP_PM_BIT); }
/* TRAP ENTRY CODE ************************************************************/ + +VOID +FASTCALL +KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame) +{ + /* Save registers */ + KiTrapFrameFromPushaStack(TrapFrame); + + /* Load correct registers */ + Ke386SetFs(KGDT_R0_PCR); + Ke386SetDs(KGDT_R3_DATA | RPL_MASK); + Ke386SetEs(KGDT_R3_DATA | RPL_MASK); + + /* Save exception list and bogus previous mode */ + TrapFrame->PreviousPreviousMode = -1; + TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList; + + /* Clear direction flag */ + Ke386ClearDirectionFlag(); + + /* Save DR7 and check for debugging */ + TrapFrame->Dr7 = __readdr(7); + if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK) + { + UNIMPLEMENTED; + while (TRUE); + } +}
VOID FASTCALL @@ -258,7 +330,6 @@ IN PFX_SAVE_AREA SaveArea) { ULONG Cr0, Mask, Error, ErrorOffset, DataOffset; - extern VOID FrRestore(VOID);
/* Check for VDM trap */ ASSERT((KiVdmTrap(TrapFrame)) == FALSE); @@ -718,9 +789,6 @@ 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);