[NTOS]: Simplify trap exit code.

[NTOS]: Move some stuff in appropriate headers.
[NTOS]: Write V86 fast entry/exit traps, needed for later.

svn path=/trunk/; revision=45028
This commit is contained in:
Sir Richard 2010-01-10 15:00:44 +00:00
parent f61b9c9113
commit ff8920ffc1
4 changed files with 146 additions and 50 deletions

View file

@ -66,6 +66,25 @@ extern ULONG Ke386CacheAlignment;
#define KeGetTrapFrameInterruptState(TrapFrame) \ #define KeGetTrapFrameInterruptState(TrapFrame) \
BooleanFlagOn((TrapFrame)->EFlags, EFLAGS_INTERRUPT_MASK) 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 // Registers an interrupt handler with an IDT vector
// //
@ -289,6 +308,25 @@ Ki386EnableXMMIExceptions(
IN ULONG_PTR Context 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
);
// //
// Global x86 only Kernel data // Global x86 only Kernel data
// //
@ -312,6 +350,10 @@ extern VOID __cdecl KiTrap2(VOID);
extern VOID __cdecl KiTrap8(VOID); extern VOID __cdecl KiTrap8(VOID);
extern VOID __cdecl KiTrap19(VOID); extern VOID __cdecl KiTrap19(VOID);
extern VOID __cdecl KiFastCallEntry(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 // Sanitizes a selector

View file

@ -72,20 +72,6 @@ typedef struct _KNMI_HANDLER_CALLBACK
PVOID Handle; PVOID Handle;
} KNMI_HANDLER_CALLBACK, *PKNMI_HANDLER_CALLBACK; } 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 typedef PCHAR
(NTAPI *PKE_BUGCHECK_UNICODE_TO_ANSI)( (NTAPI *PKE_BUGCHECK_UNICODE_TO_ANSI)(
IN PUNICODE_STRING Unicode, IN PUNICODE_STRING Unicode,

View file

@ -66,7 +66,7 @@ KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
FORCEINLINE FORCEINLINE
VOID VOID
KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame, KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
IN KTRAP_STATE_BITS StateBits) IN KTRAP_STATE_BITS SkipBits)
{ {
/* Make sure interrupts are disabled */ /* Make sure interrupts are disabled */
if (__readeflags() & EFLAGS_INTERRUPT_MASK) if (__readeflags() & EFLAGS_INTERRUPT_MASK)
@ -105,7 +105,7 @@ KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
} }
/* If we're ignoring previous mode, make sure caller doesn't actually want it */ /* 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); DPRINT1("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx", TrapFrame->PreviousPreviousMode);
while (TRUE); while (TRUE);

View file

@ -18,16 +18,19 @@
VOID VOID
FASTCALL FASTCALL
KiExitTrap(IN PKTRAP_FRAME TrapFrame, KiExitTrap(IN PKTRAP_FRAME TrapFrame,
IN UCHAR State) IN UCHAR Skip)
{ {
KTRAP_STATE_BITS StateBits = { .Bits = State }; KTRAP_EXIT_SKIP_BITS SkipBits = { .Bits = Skip };
KiExitTrapDebugChecks(TrapFrame, StateBits); 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 */ /* Restore the SEH handler chain */
KeGetPcr()->Tib.ExceptionList = TrapFrame->ExceptionList; KeGetPcr()->Tib.ExceptionList = TrapFrame->ExceptionList;
/* Check if the previous mode must be restored */ /* Check if the previous mode must be restored */
if (StateBits.PreviousMode) if (!SkipBits.SkipPreviousMode)
{ {
/* Not handled yet */ /* Not handled yet */
UNIMPLEMENTED; UNIMPLEMENTED;
@ -53,35 +56,32 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
while (TRUE); while (TRUE);
} }
/* Check if all registers must be restored */ /* Check if segments should be restored */
if (StateBits.Full) if (!SkipBits.SkipSegments)
{ {
/* Only do the restore if we made a transition from user-mode */ /* Restore segments */
if (KiUserTrap(TrapFrame)) Ke386SetGs(TrapFrame->SegGs);
{ Ke386SetEs(TrapFrame->SegEs);
/* Restore segments */ Ke386SetDs(TrapFrame->SegDs);
Ke386SetGs(TrapFrame->SegGs); Ke386SetFs(TrapFrame->SegFs);
Ke386SetEs(TrapFrame->SegEs);
Ke386SetDs(TrapFrame->SegDs);
}
} }
else if (KiUserTrap(TrapFrame))
/* 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);
}
/* Always restore FS since it goes from KPCR to TEB */ /* Always restore FS since it goes from KPCR to TEB */
Ke386SetFs(TrapFrame->SegFs); 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 */ /* Check for ABIOS code segment */
if (TrapFrame->SegCs == 0x80) if (TrapFrame->SegCs == 0x80)
{ {
@ -90,8 +90,8 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
while (TRUE); while (TRUE);
} }
/* Check for system call */ /* Check for system call -- a system call skips volatiles! */
if (StateBits.SystemCall) if (SkipBits.SkipVolatiles)
{ {
/* Not handled yet */ /* Not handled yet */
UNIMPLEMENTED; UNIMPLEMENTED;
@ -104,6 +104,50 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
} }
} }
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 VOID
FASTCALL FASTCALL
KiEoiHelper(IN PKTRAP_FRAME TrapFrame) KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
@ -115,11 +159,39 @@ KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
KiCheckForApcDelivery(TrapFrame); KiCheckForApcDelivery(TrapFrame);
/* Now exit the trap for real */ /* Now exit the trap for real */
KiExitTrap(TrapFrame, KTS_SEG_BIT | KTS_VOL_BIT); KiExitTrap(TrapFrame, KTE_SKIP_PM_BIT);
} }
/* TRAP ENTRY CODE ************************************************************/ /* 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 VOID
FASTCALL FASTCALL
KiEnterTrap(IN PKTRAP_FRAME TrapFrame) KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
@ -258,7 +330,6 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
IN PFX_SAVE_AREA SaveArea) IN PFX_SAVE_AREA SaveArea)
{ {
ULONG Cr0, Mask, Error, ErrorOffset, DataOffset; ULONG Cr0, Mask, Error, ErrorOffset, DataOffset;
extern VOID FrRestore(VOID);
/* Check for VDM trap */ /* Check for VDM trap */
ASSERT((KiVdmTrap(TrapFrame)) == FALSE); ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
@ -718,9 +789,6 @@ KiTrap14Handler(IN PKTRAP_FRAME TrapFrame)
PKTHREAD Thread; PKTHREAD Thread;
ULONG_PTR Cr2; ULONG_PTR Cr2;
NTSTATUS Status; NTSTATUS Status;
extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
extern VOID CopyParams(VOID);
extern VOID ReadBatch(VOID);
/* Save trap frame */ /* Save trap frame */
KiEnterTrap(TrapFrame); KiEnterTrap(TrapFrame);