mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
[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:
parent
f61b9c9113
commit
ff8920ffc1
4 changed files with 146 additions and 50 deletions
|
@ -65,7 +65,26 @@ extern ULONG Ke386CacheAlignment;
|
|||
//
|
||||
#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
|
||||
//
|
||||
|
@ -289,6 +308,25 @@ 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
|
||||
);
|
||||
|
||||
//
|
||||
// Global x86 only Kernel data
|
||||
//
|
||||
|
@ -312,6 +350,10 @@ extern VOID __cdecl KiTrap2(VOID);
|
|||
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
|
||||
|
|
|
@ -72,20 +72,6 @@ typedef struct _KNMI_HANDLER_CALLBACK
|
|||
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)(
|
||||
IN PUNICODE_STRING Unicode,
|
||||
|
|
|
@ -66,7 +66,7 @@ KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
|
|||
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 @@ KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
|
|||
}
|
||||
|
||||
/* 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);
|
||||
|
|
|
@ -18,16 +18,19 @@
|
|||
VOID
|
||||
FASTCALL
|
||||
KiExitTrap(IN PKTRAP_FRAME TrapFrame,
|
||||
IN UCHAR State)
|
||||
IN UCHAR Skip)
|
||||
{
|
||||
KTRAP_STATE_BITS StateBits = { .Bits = State };
|
||||
KiExitTrapDebugChecks(TrapFrame, StateBits);
|
||||
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 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
while (TRUE);
|
||||
}
|
||||
|
||||
/* Check if all registers must be restored */
|
||||
if (StateBits.Full)
|
||||
/* Check if segments should be restored */
|
||||
if (!SkipBits.SkipSegments)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
/* Restore segments */
|
||||
Ke386SetGs(TrapFrame->SegGs);
|
||||
Ke386SetEs(TrapFrame->SegEs);
|
||||
Ke386SetDs(TrapFrame->SegDs);
|
||||
Ke386SetFs(TrapFrame->SegFs);
|
||||
}
|
||||
|
||||
/* Check if we came from user-mode */
|
||||
if (KiUserTrap(TrapFrame))
|
||||
else 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 */
|
||||
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 @@ KiExitTrap(IN PKTRAP_FRAME TrapFrame,
|
|||
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;
|
||||
|
@ -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
|
||||
FASTCALL
|
||||
KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
|
||||
|
@ -115,11 +159,39 @@ KiEoiHelper(IN PKTRAP_FRAME TrapFrame)
|
|||
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
|
||||
KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
|
||||
|
@ -258,7 +330,6 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame,
|
|||
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 @@ 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);
|
||||
|
|
Loading…
Reference in a new issue