mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 18:35:32 +00:00
[NTOS]: Implement a C/Extended ASM macro for generating trap stubs, removing the need to do this in ASM. The macro covers all possible entries, from SYSENTER to a fake sotware interrupt (needed for HAL changes later). By being somewhat in C, it makes the code cleaner to read and uses C expressions to make its decisions, making the code more maintanable as well. It also removes the need for separate assembly files.
[NTOS]: Modify the semantics of how a fast system call (SYSENTER) is processed in the stub, by moving more work in the C handler, such as setting up FS and getting the correct argument stack. Saves us some cycles too (and allows the trap stub macro to be more generic). svn path=/trunk/; revision=45266
This commit is contained in:
parent
102c63a3b6
commit
12a31f1df7
|
@ -1099,13 +1099,6 @@ KiQuantumEnd(
|
|||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
KiSystemService(
|
||||
IN PKTHREAD Thread,
|
||||
IN PKTRAP_FRAME TrapFrame,
|
||||
IN ULONG Instruction
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KiIdleLoop(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ********************************************************/
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue