[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:
Sir Richard 2010-01-26 15:43:13 +00:00
parent 102c63a3b6
commit 12a31f1df7
4 changed files with 148 additions and 85 deletions

View file

@ -1099,13 +1099,6 @@ KiQuantumEnd(
VOID
);
VOID
KiSystemService(
IN PKTHREAD Thread,
IN PKTRAP_FRAME TrapFrame,
IN ULONG Instruction
);
VOID
FASTCALL
KiIdleLoop(

View file

@ -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

View file

@ -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

View file

@ -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 ********************************************************/
/*