From 6697ef7a17854c9afe3633fe1f8a93b784682641 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sat, 19 Oct 2013 11:33:34 +0000 Subject: [PATCH] [NTOSKRNL] - Introduce a new and faster way to return to kernel mode from traps by using a ret 8 instruction instead of an iret. - Make use of KiUserTrap where appropriate - Remove some pointless toplevel volatile svn path=/trunk/; revision=60701 --- .../ntoskrnl/include/internal/i386/asmmacro.S | 25 +++++++++++---- reactos/ntoskrnl/include/internal/i386/ke.h | 4 +-- .../ntoskrnl/include/internal/i386/trap_x.h | 7 +++-- reactos/ntoskrnl/ke/i386/cpu.c | 2 +- reactos/ntoskrnl/ke/i386/exp.c | 31 ++++++++++++------- reactos/ntoskrnl/ke/i386/patpge.c | 10 +++--- reactos/ntoskrnl/ke/i386/trap.s | 1 + reactos/ntoskrnl/ke/i386/traphdlr.c | 18 +++++------ reactos/ntoskrnl/ke/i386/usercall.c | 4 +-- reactos/ntoskrnl/ke/time.c | 2 +- 10 files changed, 64 insertions(+), 40 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/i386/asmmacro.S b/reactos/ntoskrnl/include/internal/i386/asmmacro.S index cf338d32338..2ab3bdfd6ff 100644 --- a/reactos/ntoskrnl/include/internal/i386/asmmacro.S +++ b/reactos/ntoskrnl/include/internal/i386/asmmacro.S @@ -241,6 +241,7 @@ ENDM #define KI_EXIT_RET HEX(080) #define KI_EXIT_IRET HEX(100) #define KI_EDITED_FRAME HEX(200) +#define KI_EXIT_RET8 HEX(400) #define KI_RESTORE_VOLATILES (KI_RESTORE_EAX OR KI_RESTORE_ECX_EDX) MACRO(KiTrapExitStub, Name, Flags) @@ -248,16 +249,16 @@ MACRO(KiTrapExitStub, Name, Flags) PUBLIC @&Name&@4 @&Name&@4: - if (Flags AND KI_RESTORE_EFLAGS) - - /* We will pop EFlags off the stack */ - OffsetEsp = KTRAP_FRAME_EFLAGS - - elseif (Flags AND KI_EXIT_IRET) + if (Flags AND KI_EXIT_RET8) OR (Flags AND KI_EXIT_IRET) /* This is the IRET frame */ OffsetEsp = KTRAP_FRAME_EIP + elseif (Flags AND KI_RESTORE_EFLAGS) + + /* We will pop EFlags off the stack */ + OffsetEsp = KTRAP_FRAME_EFLAGS + else OffsetEsp = 0 @@ -335,6 +336,13 @@ PUBLIC @&Name&@4 if (Flags AND KI_RESTORE_EFLAGS) + if (Flags AND KI_EXIT_RET8) + + /* We are at the IRET frame, so push EFLAGS first */ + push dword ptr [esp + 8] + + endif + /* Restore EFLAGS */ popfd @@ -357,6 +365,11 @@ PUBLIC @&Name&@4 /* Return to kernel mode with a jmp */ jmp edx + elseif (Flags AND KI_EXIT_RET8) + + /* Return to kernel mode with a ret 8 */ + ret 8 + elseif (Flags AND KI_EXIT_RET) /* Return to kernel mode with a ret */ diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index 47da49fcea1..f0343c521a8 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -383,13 +383,13 @@ KeI386VdmInitialize( ULONG_PTR NTAPI Ki386EnableGlobalPage( - IN volatile ULONG_PTR Context + IN ULONG_PTR Context ); ULONG_PTR NTAPI Ki386EnableTargetLargePage( - IN volatile ULONG_PTR Context + IN ULONG_PTR Context ); BOOLEAN diff --git a/reactos/ntoskrnl/include/internal/i386/trap_x.h b/reactos/ntoskrnl/include/internal/i386/trap_x.h index d83276fb165..ec8f0ba914d 100644 --- a/reactos/ntoskrnl/include/internal/i386/trap_x.h +++ b/reactos/ntoskrnl/include/internal/i386/trap_x.h @@ -163,7 +163,7 @@ KiExitTrapDebugChecks(IN PKTRAP_FRAME TrapFrame, } /* Check DR values */ - if (TrapFrame->SegCs & MODE_MASK) + if (KiUserTrap(TrapFrame) { /* Check for active debugging */ if (KeGetCurrentThread()->Header.DebugActive) @@ -244,6 +244,7 @@ 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); +DECLSPEC_NORETURN VOID FASTCALL KiTrapReturnNoSegmentsRet8(IN PKTRAP_FRAME TrapFrame); typedef ATTRIB_NORETURN @@ -382,7 +383,7 @@ KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame) TrapFrame->Dr7 = 0; /* Check if the frame was from user mode or v86 mode */ - if ((TrapFrame->SegCs & MODE_MASK) || + if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) { /* Check for active debugging */ @@ -411,7 +412,7 @@ KiEnterTrap(IN PKTRAP_FRAME TrapFrame) TrapFrame->Dr7 = 0; /* Check if the frame was from user mode or v86 mode */ - if ((TrapFrame->SegCs & MODE_MASK) || + if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) { /* Check for active debugging */ diff --git a/reactos/ntoskrnl/ke/i386/cpu.c b/reactos/ntoskrnl/ke/i386/cpu.c index 3b8f1fad176..2d741ab6144 100644 --- a/reactos/ntoskrnl/ke/i386/cpu.c +++ b/reactos/ntoskrnl/ke/i386/cpu.c @@ -1535,7 +1535,7 @@ KeFlushEntireTb(IN BOOLEAN Invalid, if (TargetAffinity) { /* Sanity check */ - ASSERT(Prcb == (volatile PKPRCB)KeGetCurrentPrcb()); + ASSERT(Prcb == KeGetCurrentPrcb()); /* FIXME: TODO */ ASSERTMSG("Not yet implemented\n", FALSE); diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index eaacf4ea6a3..976d2ebddc7 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -137,7 +137,7 @@ NTAPI KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame) { /* Check if this is user-mode or V86 */ - if ((TrapFrame->SegCs & MODE_MASK) || + if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) { /* Return it directly */ @@ -175,7 +175,7 @@ KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame, Previous = KiEspFromTrapFrame(TrapFrame); /* Check if this is user-mode or V86 */ - if ((TrapFrame->SegCs & MODE_MASK) || + if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) { /* Write it directly */ @@ -225,7 +225,7 @@ KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame) /* Just return it */ return TrapFrame->HardwareSegSs; } - else if (TrapFrame->SegCs & MODE_MASK) + else if (KiUserTrap(TrapFrame)) { /* User mode, return the User SS */ return TrapFrame->HardwareSegSs | RPL_MASK; @@ -251,7 +251,7 @@ KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame, /* Just write it */ TrapFrame->HardwareSegSs = Ss; } - else if (TrapFrame->SegCs & MODE_MASK) + else if (KiUserTrap(TrapFrame)) { /* Usermode, save the User SS */ TrapFrame->HardwareSegSs = Ss | RPL_MASK; @@ -398,7 +398,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, TrapFrame->V86Fs = Context->SegFs; TrapFrame->V86Gs = Context->SegGs; } - else if (!(TrapFrame->SegCs & MODE_MASK)) + else if (!KiUserTrap(TrapFrame)) { /* For kernel mode, write the standard values */ TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK; @@ -429,7 +429,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, /* Handle the extended registers */ if (((ContextFlags & CONTEXT_EXTENDED_REGISTERS) == - CONTEXT_EXTENDED_REGISTERS) && (TrapFrame->SegCs & MODE_MASK)) + CONTEXT_EXTENDED_REGISTERS) && KiUserTrap(TrapFrame)) { /* Get the FX Area */ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1); @@ -463,7 +463,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, /* Handle the floating point state */ if (((ContextFlags & CONTEXT_FLOATING_POINT) == - CONTEXT_FLOATING_POINT) && (TrapFrame->SegCs & MODE_MASK)) + CONTEXT_FLOATING_POINT) && KiUserTrap(TrapFrame)) { /* Get the FX Area */ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1); @@ -692,7 +692,7 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, /* Handle extended registers */ if (((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == - CONTEXT_EXTENDED_REGISTERS) && (TrapFrame->SegCs & MODE_MASK)) + CONTEXT_EXTENDED_REGISTERS) && KiUserTrap(TrapFrame)) { /* Get the FX Save Area */ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1); @@ -712,7 +712,7 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, /* Handle Floating Point */ if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) == - CONTEXT_FLOATING_POINT) && (TrapFrame->SegCs & MODE_MASK)) + CONTEXT_FLOATING_POINT) && KiUserTrap(TrapFrame)) { /* Get the FX Save Area */ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1); @@ -1045,6 +1045,13 @@ DispatchToUser: } } _SEH2_END; + + DPRINT("First chance exception in %.16s, ExceptionCode: %lx, ExceptionAddress: %p, P0: %lx, P1: %lx\n", + PsGetCurrentProcess()->ImageFileName, + ExceptionRecord->ExceptionCode, + ExceptionRecord->ExceptionAddress, + ExceptionRecord->ExceptionInformation[0], + ExceptionRecord->ExceptionInformation[1]); } /* Try second chance */ @@ -1060,11 +1067,13 @@ DispatchToUser: } /* 3rd strike, kill the process */ - DPRINT1("Kill %.16s, ExceptionCode: %lx, ExceptionAddress: %p, BaseAddress: %p\n", + DPRINT1("Kill %.16s, ExceptionCode: %lx, ExceptionAddress: %p, BaseAddress: %p, P0: %lx, P1: %lx\n", PsGetCurrentProcess()->ImageFileName, ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress, - PsGetCurrentProcess()->SectionBaseAddress); + PsGetCurrentProcess()->SectionBaseAddress, + ExceptionRecord->ExceptionInformation[0], + ExceptionRecord->ExceptionInformation[1]); ZwTerminateProcess(NtCurrentProcess(), ExceptionRecord->ExceptionCode); KeBugCheckEx(KMODE_EXCEPTION_NOT_HANDLED, diff --git a/reactos/ntoskrnl/ke/i386/patpge.c b/reactos/ntoskrnl/ke/i386/patpge.c index 41b474ae0e9..1e598ce355a 100644 --- a/reactos/ntoskrnl/ke/i386/patpge.c +++ b/reactos/ntoskrnl/ke/i386/patpge.c @@ -20,9 +20,9 @@ ULONG_PTR NTAPI INIT_FUNCTION -Ki386EnableGlobalPage(IN volatile ULONG_PTR Context) +Ki386EnableGlobalPage(IN ULONG_PTR Context) { - volatile PLONG Count = (PLONG)Context; + PLONG Count = (PLONG)Context; ULONG Cr4, Cr3; /* Disable interrupts */ @@ -144,7 +144,7 @@ Ki386IdentityMapMakeValid(PLARGE_IDENTITY_MAP IdentityMap, if (PageTable) *PageTable = (PHARDWARE_PTE)(Pde->PageFrameNumber << PAGE_SHIFT); } - + return TRUE; } @@ -172,7 +172,7 @@ Ki386MapAddress(PLARGE_IDENTITY_MAP IdentityMap, /* Get PTE of VirtualPtr, make it valid, and map PhysicalPtr there */ Pte = &PageTable[(VirtualPtr >> 12) & ((1 << PTE_BITS) - 1)]; Pte->Valid = 1; - Pte->PageFrameNumber = PhysicalPtr.QuadPart >> PAGE_SHIFT; + Pte->PageFrameNumber = (PFN_NUMBER)(PhysicalPtr.QuadPart >> PAGE_SHIFT); return TRUE; } @@ -189,7 +189,7 @@ Ki386ConvertPte(PHARDWARE_PTE Pte) PhysicalPtr = MmGetPhysicalAddress(VirtualPtr); /* Map its physical address in the page table provided by the caller */ - Pte->PageFrameNumber = PhysicalPtr.QuadPart >> PAGE_SHIFT; + Pte->PageFrameNumber = (PFN_NUMBER)(PhysicalPtr.QuadPart >> PAGE_SHIFT); } BOOLEAN diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index 6817995ca35..272886d4891 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -166,6 +166,7 @@ KiTrapExitStub KiSystemCallTrapReturn, (KI_RESTORE_EAX OR KI_RESTORE_FS OR KI KiTrapExitStub KiEditedTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EDITED_FRAME OR KI_EXIT_RET) KiTrapExitStub KiTrapReturn, (KI_RESTORE_VOLATILES OR KI_RESTORE_SEGMENTS OR KI_EXIT_IRET) KiTrapExitStub KiTrapReturnNoSegments, (KI_RESTORE_VOLATILES OR KI_EXIT_IRET) +KiTrapExitStub KiTrapReturnNoSegmentsRet8,(KI_RESTORE_VOLATILES OR KI_RESTORE_EFLAGS OR KI_EXIT_RET8) #ifdef _MSC_VER EXTERN _PsConvertToGuiThread@0:PROC diff --git a/reactos/ntoskrnl/ke/i386/traphdlr.c b/reactos/ntoskrnl/ke/i386/traphdlr.c index 46b925aab24..e761cd0d82a 100644 --- a/reactos/ntoskrnl/ke/i386/traphdlr.c +++ b/reactos/ntoskrnl/ke/i386/traphdlr.c @@ -100,7 +100,7 @@ KiCommonExit(IN PKTRAP_FRAME TrapFrame, BOOLEAN SkipPreviousMode) if (__builtin_expect(TrapFrame->Dr7 & ~DR7_RESERVED_MASK, 0)) { /* Check if the frame was from user mode or v86 mode */ - if ((TrapFrame->SegCs & MODE_MASK) || + if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) { /* Handle debug registers */ @@ -124,13 +124,13 @@ KiEoiHelper(IN PKTRAP_FRAME TrapFrame) if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame); /* Check for user mode exit */ - if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame); + if (KiUserTrap(TrapFrame)) KiTrapReturn(TrapFrame); /* Check for edited frame */ if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame); /* Exit the trap to kernel mode */ - KiTrapReturnNoSegments(TrapFrame); + KiTrapReturnNoSegmentsRet8(TrapFrame); } DECLSPEC_NORETURN @@ -152,7 +152,7 @@ KiServiceExit(IN PKTRAP_FRAME TrapFrame, KeGetCurrentThread()->PreviousMode = (CCHAR)TrapFrame->PreviousPreviousMode; /* Check for user mode exit */ - if (TrapFrame->SegCs & MODE_MASK) + if (KiUserTrap(TrapFrame)) { /* Check if we were single stepping */ if (TrapFrame->EFlags & EFLAGS_TF) @@ -186,13 +186,13 @@ KiServiceExit2(IN PKTRAP_FRAME TrapFrame) if (TrapFrame->EFlags & EFLAGS_V86_MASK) KiTrapReturnNoSegments(TrapFrame); /* Check for user mode exit */ - if (TrapFrame->SegCs & MODE_MASK) KiTrapReturn(TrapFrame); + if (KiUserTrap(TrapFrame)) KiTrapReturn(TrapFrame); /* Check for edited frame */ if (KiIsFrameEdited(TrapFrame)) KiEditedTrapReturn(TrapFrame); /* Exit the trap to kernel mode */ - KiTrapReturnNoSegments(TrapFrame); + KiTrapReturnNoSegmentsRet8(TrapFrame); } @@ -1250,10 +1250,10 @@ KiTrap0EHandler(IN PKTRAP_FRAME TrapFrame) /* Call the access fault handler */ Status = MmAccessFault(TrapFrame->ErrCode & 1, (PVOID)Cr2, - TrapFrame->SegCs & MODE_MASK, + KiUserTrap(TrapFrame), TrapFrame); if (NT_SUCCESS(Status)) KiEoiHelper(TrapFrame); - + /* Check for syscall fault */ #if 0 if ((TrapFrame->Eip == (ULONG_PTR)CopyParams) || @@ -1541,7 +1541,7 @@ KiSystemCall(IN PKTRAP_FRAME TrapFrame, TrapFrame->Dr7 = 0; /* Check if the frame was from user mode */ - if (TrapFrame->SegCs & MODE_MASK) + if (KiUserTrap(TrapFrame)) { /* Check for active debugging */ if (KeGetCurrentThread()->Header.DebugActive & 0xFF) diff --git a/reactos/ntoskrnl/ke/i386/usercall.c b/reactos/ntoskrnl/ke/i386/usercall.c index 9363c6fed5f..91bd672ae4a 100644 --- a/reactos/ntoskrnl/ke/i386/usercall.c +++ b/reactos/ntoskrnl/ke/i386/usercall.c @@ -67,7 +67,7 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame, _SEH2_TRY { /* Sanity check */ - ASSERT((TrapFrame->SegCs & MODE_MASK) != KernelMode); + ASSERT(KiUserTrap(TrapFrame)); /* Get the aligned size */ AlignedEsp = Context.Esp & ~3; @@ -210,7 +210,7 @@ KeUserModeCallback(IN ULONG RoutineIndex, } -/* +/* * Stack layout for KiUserModeCallout: * ---------------------------------- * KCALLOUT_FRAME.ResultLength <= 2nd Parameter to KiCallUserMode diff --git a/reactos/ntoskrnl/ke/time.c b/reactos/ntoskrnl/ke/time.c index 531cc85bb0f..e6bdd9ed4d9 100644 --- a/reactos/ntoskrnl/ke/time.c +++ b/reactos/ntoskrnl/ke/time.c @@ -153,7 +153,7 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, /* Check if we came from user mode */ #ifndef _M_ARM - if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) + if (KiUserTrap(TrapFrame) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) #else if (TrapFrame->PreviousMode == UserMode) #endif