mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
5f2d67cb35
svn path=/branches/reactos-yarotows/; revision=47746
320 lines
9.1 KiB
C
320 lines
9.1 KiB
C
/*
|
|
* PROJECT: ReactOS Kernel
|
|
* LICENSE: BSD - See COPYING.ARM in the top level directory
|
|
* FILE: ntoskrnl/include/trap_x.h
|
|
* PURPOSE: Internal Inlined Functions for the Trap Handling Code
|
|
* PROGRAMMERS: ReactOS Portable Systems Group
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#define TRAP_DEBUG 0
|
|
|
|
//
|
|
// Unreachable code hint for GCC 4.5.x, older GCC versions, and MSVC
|
|
//
|
|
#ifdef __GNUC__
|
|
#if __GNUC__ * 100 + __GNUC_MINOR__ >= 405
|
|
#define UNREACHABLE __builtin_unreachable()
|
|
#else
|
|
#define UNREACHABLE __builtin_trap()
|
|
#endif
|
|
#elif _MSC_VER
|
|
#define UNREACHABLE __assume(0)
|
|
#else
|
|
#define UNREACHABLE
|
|
#endif
|
|
|
|
//
|
|
// Helper Code
|
|
//
|
|
BOOLEAN
|
|
FORCEINLINE
|
|
KiUserTrap(IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
/* Anything else but Ring 0 is Ring 3 */
|
|
return (TrapFrame->SegCs & MODE_MASK);
|
|
}
|
|
|
|
//
|
|
// Debug Macros
|
|
//
|
|
VOID
|
|
FORCEINLINE
|
|
KiDumpTrapFrame(IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
/* Dump the whole thing */
|
|
DbgPrint("DbgEbp: %x\n", TrapFrame->DbgEbp);
|
|
DbgPrint("DbgEip: %x\n", TrapFrame->DbgEip);
|
|
DbgPrint("DbgArgMark: %x\n", TrapFrame->DbgArgMark);
|
|
DbgPrint("DbgArgPointer: %x\n", TrapFrame->DbgArgPointer);
|
|
DbgPrint("TempSegCs: %x\n", TrapFrame->TempSegCs);
|
|
DbgPrint("TempEsp: %x\n", TrapFrame->TempEsp);
|
|
DbgPrint("Dr0: %x\n", TrapFrame->Dr0);
|
|
DbgPrint("Dr1: %x\n", TrapFrame->Dr1);
|
|
DbgPrint("Dr2: %x\n", TrapFrame->Dr2);
|
|
DbgPrint("Dr3: %x\n", TrapFrame->Dr3);
|
|
DbgPrint("Dr6: %x\n", TrapFrame->Dr6);
|
|
DbgPrint("Dr7: %x\n", TrapFrame->Dr7);
|
|
DbgPrint("SegGs: %x\n", TrapFrame->SegGs);
|
|
DbgPrint("SegEs: %x\n", TrapFrame->SegEs);
|
|
DbgPrint("SegDs: %x\n", TrapFrame->SegDs);
|
|
DbgPrint("Edx: %x\n", TrapFrame->Edx);
|
|
DbgPrint("Ecx: %x\n", TrapFrame->Ecx);
|
|
DbgPrint("Eax: %x\n", TrapFrame->Eax);
|
|
DbgPrint("PreviousPreviousMode: %x\n", TrapFrame->PreviousPreviousMode);
|
|
DbgPrint("ExceptionList: %x\n", TrapFrame->ExceptionList);
|
|
DbgPrint("SegFs: %x\n", TrapFrame->SegFs);
|
|
DbgPrint("Edi: %x\n", TrapFrame->Edi);
|
|
DbgPrint("Esi: %x\n", TrapFrame->Esi);
|
|
DbgPrint("Ebx: %x\n", TrapFrame->Ebx);
|
|
DbgPrint("Ebp: %x\n", TrapFrame->Ebp);
|
|
DbgPrint("ErrCode: %x\n", TrapFrame->ErrCode);
|
|
DbgPrint("Eip: %x\n", TrapFrame->Eip);
|
|
DbgPrint("SegCs: %x\n", TrapFrame->SegCs);
|
|
DbgPrint("EFlags: %x\n", TrapFrame->EFlags);
|
|
DbgPrint("HardwareEsp: %x\n", TrapFrame->HardwareEsp);
|
|
DbgPrint("HardwareSegSs: %x\n", TrapFrame->HardwareSegSs);
|
|
DbgPrint("V86Es: %x\n", TrapFrame->V86Es);
|
|
DbgPrint("V86Ds: %x\n", TrapFrame->V86Ds);
|
|
DbgPrint("V86Fs: %x\n", TrapFrame->V86Fs);
|
|
DbgPrint("V86Gs: %x\n", TrapFrame->V86Gs);
|
|
}
|
|
|
|
#if TRAP_DEBUG
|
|
VOID
|
|
FORCEINLINE
|
|
KiFillTrapFrameDebug(IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
/* Set the debug information */
|
|
TrapFrame->DbgArgPointer = TrapFrame->Edx;
|
|
TrapFrame->DbgArgMark = 0xBADB0D00;
|
|
TrapFrame->DbgEip = TrapFrame->Eip;
|
|
TrapFrame->DbgEbp = TrapFrame->Ebp;
|
|
TrapFrame->PreviousPreviousMode = -1;
|
|
}
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame,
|
|
IN KTRAP_EXIT_SKIP_BITS SkipBits)
|
|
{
|
|
/* Make sure interrupts are disabled */
|
|
if (__readeflags() & EFLAGS_INTERRUPT_MASK)
|
|
{
|
|
DbgPrint("Exiting with interrupts enabled: %lx\n", __readeflags());
|
|
__debugbreak();
|
|
}
|
|
|
|
/* Make sure this is a real trap frame */
|
|
if (TrapFrame->DbgArgMark != 0xBADB0D00)
|
|
{
|
|
DbgPrint("Exiting with an invalid trap frame? (No MAGIC in trap frame)\n");
|
|
KiDumpTrapFrame(TrapFrame);
|
|
__debugbreak();
|
|
}
|
|
|
|
/* Make sure we're not in user-mode or something */
|
|
if (Ke386GetFs() != KGDT_R0_PCR)
|
|
{
|
|
DbgPrint("Exiting with an invalid FS: %lx\n", Ke386GetFs());
|
|
__debugbreak();
|
|
}
|
|
|
|
/* Make sure we have a valid SEH chain */
|
|
if (KeGetPcr()->NtTib.ExceptionList == 0)
|
|
{
|
|
DbgPrint("Exiting with NULL exception chain: %p\n", KeGetPcr()->NtTib.ExceptionList);
|
|
__debugbreak();
|
|
}
|
|
|
|
/* Make sure we're restoring a valid SEH chain */
|
|
if (TrapFrame->ExceptionList == 0)
|
|
{
|
|
DbgPrint("Entered a trap with a NULL exception chain: %p\n", TrapFrame->ExceptionList);
|
|
__debugbreak();
|
|
}
|
|
|
|
/* If we're ignoring previous mode, make sure caller doesn't actually want it */
|
|
if ((SkipBits.SkipPreviousMode) && (TrapFrame->PreviousPreviousMode != -1))
|
|
{
|
|
DbgPrint("Exiting a trap witout restoring previous mode, yet previous mode seems valid: %lx\n", TrapFrame->PreviousPreviousMode);
|
|
__debugbreak();
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FORCEINLINE
|
|
KiExitSystemCallDebugChecks(IN ULONG SystemCall,
|
|
IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
KIRQL OldIrql;
|
|
|
|
/* Check if this was a user call */
|
|
if (KiUserTrap(TrapFrame))
|
|
{
|
|
/* Make sure we are not returning with elevated IRQL */
|
|
OldIrql = KeGetCurrentIrql();
|
|
if (OldIrql != PASSIVE_LEVEL)
|
|
{
|
|
/* Forcibly put us in a sane state */
|
|
KeGetPcr()->Irql = PASSIVE_LEVEL;
|
|
_disable();
|
|
|
|
/* Fail */
|
|
KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
|
|
SystemCall,
|
|
OldIrql,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
/* Make sure we're not attached and that APCs are not disabled */
|
|
if ((KeGetCurrentThread()->ApcStateIndex != CurrentApcEnvironment) ||
|
|
(KeGetCurrentThread()->CombinedApcDisable != 0))
|
|
{
|
|
/* Fail */
|
|
KeBugCheckEx(APC_INDEX_MISMATCH,
|
|
SystemCall,
|
|
KeGetCurrentThread()->ApcStateIndex,
|
|
KeGetCurrentThread()->CombinedApcDisable,
|
|
0);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
#define KiExitTrapDebugChecks(x, y)
|
|
#define KiFillTrapFrameDebug(x)
|
|
#define KiExitSystemCallDebugChecks(x, y)
|
|
#endif
|
|
|
|
//
|
|
// Generic Exit Routine
|
|
//
|
|
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallReturn(IN PKTRAP_FRAME TrapFrame);
|
|
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame);
|
|
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame);
|
|
DECLSPEC_NORETURN VOID FASTCALL KiEditedTrapReturn(IN PKTRAP_FRAME TrapFrame);
|
|
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturn(IN PKTRAP_FRAME TrapFrame);
|
|
DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegments(IN PKTRAP_FRAME TrapFrame);
|
|
|
|
typedef
|
|
DECLSPEC_NORETURN
|
|
VOID
|
|
(FASTCALL *PFAST_SYSTEM_CALL_EXIT)(
|
|
IN PKTRAP_FRAME TrapFrame
|
|
);
|
|
|
|
extern PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler;
|
|
|
|
//
|
|
// Virtual 8086 Mode Optimized Trap Exit
|
|
//
|
|
VOID
|
|
FORCEINLINE
|
|
DECLSPEC_NORETURN
|
|
KiExitV86Trap(IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
PKTHREAD Thread;
|
|
KIRQL OldIrql;
|
|
|
|
/* Get the thread */
|
|
Thread = KeGetCurrentThread();
|
|
while (TRUE)
|
|
{
|
|
/* Return if this isn't V86 mode anymore */
|
|
if (!(TrapFrame->EFlags & EFLAGS_V86_MASK)) KiEoiHelper(TrapFrame);
|
|
|
|
/* Turn off the alerted state for kernel mode */
|
|
Thread->Alerted[KernelMode] = FALSE;
|
|
|
|
/* Are there pending user APCs? */
|
|
if (__builtin_expect(!Thread->ApcState.UserApcPending, 1)) 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();
|
|
}
|
|
|
|
/* If we got here, we're still in a valid V8086 context, so quit it */
|
|
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
|
{
|
|
/* Not handled yet */
|
|
DbgPrint("Need Hardware Breakpoint Support!\n");
|
|
while (TRUE);
|
|
}
|
|
|
|
/* Return from interrupt */
|
|
KiTrapReturnNoSegments(TrapFrame);
|
|
}
|
|
|
|
//
|
|
// Virtual 8086 Mode Optimized Trap Entry
|
|
//
|
|
VOID
|
|
FORCEINLINE
|
|
KiEnterV86Trap(IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
/* Save exception list */
|
|
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
|
|
|
/* Save DR7 and check for debugging */
|
|
TrapFrame->Dr7 = __readdr(7);
|
|
if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0))
|
|
{
|
|
DbgPrint("Need Hardware Breakpoint Support!\n");
|
|
while (TRUE);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Interrupt Trap Entry
|
|
//
|
|
VOID
|
|
FORCEINLINE
|
|
KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
/* Save exception list and terminate it */
|
|
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
|
KeGetPcr()->NtTib.ExceptionList = EXCEPTION_CHAIN_END;
|
|
|
|
/* Flush DR7 and check for debugging */
|
|
TrapFrame->Dr7 = 0;
|
|
if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader.DebugActive & 0xFF, 0))
|
|
{
|
|
DbgPrint("Need Hardware Breakpoint Support!\n");
|
|
while (TRUE);
|
|
}
|
|
|
|
/* Set debug header */
|
|
KiFillTrapFrameDebug(TrapFrame);
|
|
}
|
|
|
|
//
|
|
// Generic Trap Entry
|
|
//
|
|
VOID
|
|
FORCEINLINE
|
|
KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
|
|
{
|
|
/* Save exception list */
|
|
TrapFrame->ExceptionList = KeGetPcr()->NtTib.ExceptionList;
|
|
|
|
/* Flush DR7 and check for debugging */
|
|
TrapFrame->Dr7 = 0;
|
|
if (__builtin_expect(KeGetCurrentThread()->DispatcherHeader.DebugActive & 0xFF, 0))
|
|
{
|
|
DbgPrint("Need Hardware Breakpoint Support!\n");
|
|
while (TRUE);
|
|
}
|
|
|
|
/* Set debug header */
|
|
KiFillTrapFrameDebug(TrapFrame);
|
|
}
|