diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 694581979a5..8f70db9a369 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -1099,13 +1099,6 @@ KiQuantumEnd( VOID ); -VOID -KiSystemService( - IN PKTHREAD Thread, - IN PKTRAP_FRAME TrapFrame, - IN ULONG Instruction -); - VOID FASTCALL KiIdleLoop( diff --git a/reactos/ntoskrnl/include/internal/trap_x.h b/reactos/ntoskrnl/include/internal/trap_x.h index 3672fca6e3f..1a228ec048f 100644 --- a/reactos/ntoskrnl/include/internal/trap_x.h +++ b/reactos/ntoskrnl/include/internal/trap_x.h @@ -670,4 +670,120 @@ KiEnterTrap(IN PKTRAP_FRAME TrapFrame) /* Set debug header */ KiFillTrapFrameDebug(TrapFrame); } + +// +// Generates a Trap Prolog Stub for the given name +// +#define KI_PUSH_FAKE_ERROR_CODE 0x1 +#define KI_FAST_V86_TRAP 0x2 +#define KI_NONVOLATILES_ONLY 0x4 +#define KI_FAST_SYSTEM_CALL 0x8 +#define KI_SOFTWARE_TRAP 0x10 +#define KiTrap(x, y) VOID DECLSPEC_NORETURN x(VOID) { KiTrapStub(y, x##Handler); } + +// +// Trap Prolog Stub +// +VOID +DECLSPEC_NORETURN +FORCEINLINE +KiTrapStub(IN ULONG Flags, + IN PVOID Handler) +{ + ULONG FrameSize; + + /* Is this a fast system call? They don't have a stack! */ + if (Flags & KI_FAST_SYSTEM_CALL) __asm__ __volatile__ + ( + "movl %%ss:%c[t], %%esp\n" + "movl %c[e](%%esp), %%esp\n" + : + : [e] "i"(FIELD_OFFSET(KTSS, Esp0)), + [t] "i"(&PCR->TSS) + : "%esp" + ); + + /* Check what kind of trap frame this trap requires */ + if (Flags & KI_SOFTWARE_TRAP) + { + /* Software traps need a complete non-ring transition trap frame */ + FrameSize = FIELD_OFFSET(KTRAP_FRAME, HardwareEsp); + } + else if (Flags & KI_FAST_SYSTEM_CALL) + { + /* SYSENTER requires us to build a complete ring transition trap frame */ + FrameSize = FIELD_OFFSET(KTRAP_FRAME, V86Es); + + /* And it only preserves nonvolatile registers */ + Flags |= KI_NONVOLATILES_ONLY; + } + else if (Flags & KI_PUSH_FAKE_ERROR_CODE) + { + /* If the trap doesn't have an error code, we'll make space for it */ + FrameSize = FIELD_OFFSET(KTRAP_FRAME, Eip); + } + else + { + /* The trap already has an error code, so just make space for the rest */ + FrameSize = FIELD_OFFSET(KTRAP_FRAME, ErrCode); + } + + /* Software traps need to get their EIP from the caller's frame */ + if (Flags & KI_SOFTWARE_TRAP) __asm__ __volatile__ ("popl %%eax\n":::"%esp"); + + /* Now go ahead and make space for this frame */ + __asm__ __volatile__ ("subl $%c[e],%%esp\n":: [e] "i"(FrameSize) : "%esp"); + + /* Does the caller want volatiles only? */ + if (Flags & KI_NONVOLATILES_ONLY) __asm__ __volatile__ + ( + /* Then only EBX, ESI, EDI and EBP are saved */ + "movl %%ebx, %c[b](%%esp)\n" + "movl %%esi, %c[s](%%esp)\n" + "movl %%edi, %c[i](%%esp)\n" + "movl %%ebp, %c[p](%%esp)\n" + : + : [b] "i"(FIELD_OFFSET(KTRAP_FRAME, Ebx)), + [s] "i"(FIELD_OFFSET(KTRAP_FRAME, Esi)), + [i] "i"(FIELD_OFFSET(KTRAP_FRAME, Edi)), + [p] "i"(FIELD_OFFSET(KTRAP_FRAME, Ebp)) + : "%esp" + ); + else __asm__ __volatile__ + ( + /* Otherwise, we save all the registers (except ESP) */ + "movl %%eax, %c[a](%%esp)\n" + "movl %%ebx, %c[b](%%esp)\n" + "movl %%ecx, %c[c](%%esp)\n" + "movl %%edx, %c[d](%%esp)\n" + "movl %%esi, %c[s](%%esp)\n" + "movl %%edi, %c[i](%%esp)\n" + "movl %%ebp, %c[p](%%esp)\n" + : + : [a] "i"(FIELD_OFFSET(KTRAP_FRAME, Eax)), + [b] "i"(FIELD_OFFSET(KTRAP_FRAME, Ebx)), + [c] "i"(FIELD_OFFSET(KTRAP_FRAME, Ecx)), + [d] "i"(FIELD_OFFSET(KTRAP_FRAME, Edx)), + [s] "i"(FIELD_OFFSET(KTRAP_FRAME, Esi)), + [i] "i"(FIELD_OFFSET(KTRAP_FRAME, Edi)), + [p] "i"(FIELD_OFFSET(KTRAP_FRAME, Ebp)) + : "%esp" + ); + + /* Now set parameter 1 (ECX) to point to the frame */ + __asm__ __volatile__ ("movl %%esp, %%ecx\n":::"%esp"); + + /* For Fast-V86 traps, move set parameter 2 (EDX) to hold EFlags */ + if (Flags & KI_FAST_V86_TRAP) __asm__ __volatile__ + ( + "movl %c[f](%%esp), %%edx\n" + : + : [f] "i"(FIELD_OFFSET(KTRAP_FRAME, EFlags)) + ); + + /* Now jump to the C handler */ + __asm__ __volatile__ ("jmp %c[x]\n":: [x] "i"(Handler)); + UNREACHABLE; +} + #endif diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index cc2a202cec1..53b924b8389 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -53,14 +53,6 @@ idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service Handler */ idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED */ GENERATE_IDT_STUBS /* INT 30-FF: UNEXPECTED INTERRUPTS */ -/* Trap handlers referenced from C code */ -.globl _KiTrap08 -.globl _KiTrap13 - -/* System call code referenced from C code */ -.globl _CopyParams -.globl _ReadBatch - /* System call entrypoints: */ .globl _KiFastCallEntry .globl _KiSystemService @@ -111,49 +103,6 @@ _IsrOverflowMsg: /* SOFTWARE INTERRUPT SERVICES ***********************************************/ .text -.func KiSystemService -_KiSystemService: - - /* Make space for trap frame on the stack */ - sub esp, KTRAP_FRAME_EIP - - /* Save EBP, EBX, ESI, EDI only! */ - mov [esp+KTRAP_FRAME_EBX], ebx - mov [esp+KTRAP_FRAME_ESI], esi - mov [esp+KTRAP_FRAME_EDI], edi - mov [esp+KTRAP_FRAME_EBP], ebp - - /* Call C handler -- note that EDX is the caller stack, EAX is the ID */ - mov ecx, esp - jmp _KiSystemServiceHandler -.endfunc - -.func KiFastCallEntry -_KiFastCallEntry: - - /* Sane FS segment */ - mov ecx, KGDT_R0_PCR - mov fs, cx - - /* Sane stack and frame */ - mov esp, PCR[KPCR_TSS] - mov esp, [esp+KTSS_ESP0] - - /* Make space for trap frame on the stack */ - sub esp, KTRAP_FRAME_V86_ES - - /* Save EBP, EBX, ESI, EDI only! */ - mov [esp+KTRAP_FRAME_EBX], ebx - mov [esp+KTRAP_FRAME_ESI], esi - mov [esp+KTRAP_FRAME_EDI], edi - mov [esp+KTRAP_FRAME_EBP], ebp - - /* Call C handler -- note that EDX is the user stack, and EAX the syscall */ - mov ecx, esp - add edx, 8 - jmp _KiFastCallEntryHandler -.endfunc - .func Kei386EoiHelper@0 _Kei386EoiHelper@0: @@ -192,32 +141,6 @@ AbiosExit: /* FIXME: TODO */ UNHANDLED_PATH -GENERATE_TRAP_HANDLER KiGetTickCount, 1 -GENERATE_TRAP_HANDLER KiCallbackReturn, 1 -GENERATE_TRAP_HANDLER KiRaiseAssertion, 1 -GENERATE_TRAP_HANDLER KiDebugService, 1 - -/* HARDWARE TRAP HANDLERS ****************************************************/ - -GENERATE_TRAP_HANDLER KiTrap00 -GENERATE_TRAP_HANDLER KiTrap01 -GENERATE_TRAP_HANDLER KiTrap03 -GENERATE_TRAP_HANDLER KiTrap04 -GENERATE_TRAP_HANDLER KiTrap05 -GENERATE_TRAP_HANDLER KiTrap06 -GENERATE_TRAP_HANDLER KiTrap07 -GENERATE_TRAP_HANDLER KiTrap08, 0 -GENERATE_TRAP_HANDLER KiTrap09 -GENERATE_TRAP_HANDLER KiTrap0A, 0 -GENERATE_TRAP_HANDLER KiTrap0B, 0 -GENERATE_TRAP_HANDLER KiTrap0C, 0 -GENERATE_TRAP_HANDLER KiTrap0D, 0, 1 -GENERATE_TRAP_HANDLER KiTrap0E, 0 -GENERATE_TRAP_HANDLER KiTrap0F -GENERATE_TRAP_HANDLER KiTrap10 -GENERATE_TRAP_HANDLER KiTrap11 -GENERATE_TRAP_HANDLER KiTrap13 - /* UNEXPECTED INTERRUPT HANDLERS **********************************************/ .globl _KiStartUnexpectedRange@0 diff --git a/reactos/ntoskrnl/ke/i386/traphdlr.c b/reactos/ntoskrnl/ke/i386/traphdlr.c index 96176df3f99..eb00b7fe1c6 100644 --- a/reactos/ntoskrnl/ke/i386/traphdlr.c +++ b/reactos/ntoskrnl/ke/i386/traphdlr.c @@ -1489,12 +1489,13 @@ KiFastCallEntryHandler(IN ULONG ServiceNumber, PKTHREAD Thread; /* Fixup segments */ + Ke386SetFs(KGDT_R0_PCR); Ke386SetDs(KGDT_R3_DATA | RPL_MASK); Ke386SetEs(KGDT_R3_DATA | RPL_MASK); /* Set up a fake INT Stack and enable interrupts */ TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK; - TrapFrame->HardwareEsp = (ULONG_PTR)Arguments - 8; // Stack is 2 frames down + TrapFrame->HardwareEsp = (ULONG_PTR)Arguments; TrapFrame->EFlags = __readeflags() | EFLAGS_INTERRUPT_MASK; TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK; TrapFrame->Eip = SharedUserData->SystemCallReturn; @@ -1502,6 +1503,9 @@ KiFastCallEntryHandler(IN ULONG ServiceNumber, /* Get the current thread */ Thread = KeGetCurrentThread(); + + /* Arguments are actually 2 frames down (because of the double indirection) */ + Arguments = (PVOID)(TrapFrame->HardwareEsp + 8); /* Call the shared handler (inline) */ KiSystemCallHandler(TrapFrame, @@ -1546,6 +1550,33 @@ KiSystemServiceHandler(IN ULONG ServiceNumber, SegFs); } +/* CPU AND SOFTWARE TRAPS *****************************************************/ + +KiTrap(KiTrap00, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap01, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap03, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap04, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap05, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap06, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap07, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap08, 0); +KiTrap(KiTrap09, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap0A, 0); +KiTrap(KiTrap0B, 0); +KiTrap(KiTrap0C, 0); +KiTrap(KiTrap0D, KI_FAST_V86_TRAP); +KiTrap(KiTrap0E, 0); +KiTrap(KiTrap0F, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap10, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap11, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiTrap13, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiGetTickCount, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiCallbackReturn, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiRaiseAssertion, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiDebugService, KI_PUSH_FAKE_ERROR_CODE); +KiTrap(KiSystemService, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY); +KiTrap(KiFastCallEntry, KI_FAST_SYSTEM_CALL); + /* HARDWARE INTERRUPTS ********************************************************/ /*