[NTOS]: Implement the KiInterruptTemplate in C since we now have a C entrry macro. Add a new KI_HARDWARE_INT flag for the C entry macro to generate the appropriate labels for runtime patching of the KINTERRUPT pointer to work, and issue an absolute instead of relative jmp.

[NTOS]: Remove thousands of lines of assembly that are not needed anymore.
[NTOS]: Put all interrupt code in irqobj.c (platform-specific).
[NTOS]: DPC Interrupt is really the thread scheduler interrupt (DPC work happens in C), which mostly does contexts switching and scheduling decisions, so move it to ctxswitch.S

svn path=/trunk/; revision=45309
This commit is contained in:
Sir Richard 2010-01-29 01:12:08 +00:00
parent 3b6e1e135b
commit 614734706d
9 changed files with 163 additions and 1659 deletions

File diff suppressed because it is too large Load diff

View file

@ -451,6 +451,7 @@ extern UCHAR KiDebugRegisterContextOffsets[9];
extern VOID __cdecl KiTrap02(VOID);
extern VOID __cdecl KiTrap08(VOID);
extern VOID __cdecl KiTrap13(VOID);
extern VOID __cdecl KiInterruptTemplate(VOID);
extern VOID __cdecl KiFastCallEntry(VOID);
extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID);
extern VOID __cdecl CopyParams(VOID);

View file

@ -98,7 +98,6 @@ extern UCHAR KeNumberNodes;
extern UCHAR KeProcessNodeSeed;
extern ETHREAD KiInitialThread;
extern EPROCESS KiInitialProcess;
extern ULONG KiInterruptTemplate[KINTERRUPT_DISPATCH_CODES];
extern PULONG KiInterruptTemplateObject;
extern PULONG KiInterruptTemplateDispatch;
extern PULONG KiInterruptTemplate2ndDispatch;

View file

@ -755,6 +755,7 @@ KiEnterTrap(IN PKTRAP_FRAME TrapFrame)
#define KI_NONVOLATILES_ONLY 0x4
#define KI_FAST_SYSTEM_CALL 0x8
#define KI_SOFTWARE_TRAP 0x10
#define KI_HARDWARE_INT 0x20
#define KiTrap(x, y) VOID DECLSPEC_NORETURN x(VOID) { KiTrapStub(y, x##Handler); UNREACHABLE; }
#define KiTrampoline(x, y) VOID DECLSPEC_NOINLINE x(VOID) { KiTrapStub(y, x##Handler); }
@ -849,16 +850,39 @@ KiTrapStub(IN ULONG Flags,
/* 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 */
/* For Fast-V86 traps, 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))
);
else if (Flags & KI_HARDWARE_INT) __asm__ __volatile__
(
/*
* For hardware interrupts, set parameter 2 (EDX) to hold KINTERRUPT.
* This code will be dynamically patched when an interrupt is registered!
*/
".globl _KiInterruptTemplate2ndDispatch\n_KiInterruptTemplate2ndDispatch:\n"
"movl $0, %%edx\n"
".globl _KiInterruptTemplateObject\n_KiInterruptTemplateObject:\n"
::: "%edx"
);
/* Now jump to the C handler */
__asm__ __volatile__ ("jmp %c[x]\n":: [x] "i"(Handler));
if (Flags & KI_HARDWARE_INT)__asm__ __volatile__
(
/*
* For hardware interrupts, use an absolute JMP instead of a relative JMP
* since the position of this code is arbitrary in memory, and therefore
* the compiler-generated offset will not be correct.
*/
"jmp *%0\n"
".globl _KiInterruptTemplateDispatch\n_KiInterruptTemplateDispatch:\n"
:
: "a"(Handler)
);
else __asm__ __volatile__ ("jmp %c[x]\n":: [x] "i"(Handler));
}
#endif

View file

@ -380,6 +380,124 @@ WrongCpu:
ret
.endfunc
/* DPC INTERRUPT HANDLER ******************************************************/
.globl _KiDispatchInterrupt@0
.func KiDispatchInterrupt@0
_KiDispatchInterrupt@0:
/* Preserve EBX */
push ebx
/* Get the PCR and disable interrupts */
mov ebx, PCR[KPCR_SELF]
cli
/* Check if we have to deliver DPCs, timers, or deferred threads */
mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
jz CheckQuantum
/* Save stack pointer and exception list, then clear it */
push ebp
push dword ptr [ebx+KPCR_EXCEPTION_LIST]
mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
/* Save the stack and switch to the DPC Stack */
mov edx, esp
mov esp, [ebx+KPCR_PRCB_DPC_STACK]
push edx
/* Deliver DPCs */
mov ecx, [ebx+KPCR_PRCB]
call @KiRetireDpcList@4
/* Restore stack and exception list */
pop esp
pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
pop ebp
CheckQuantum:
/* Re-enable interrupts */
sti
/* Check if we have quantum end */
cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
jnz QuantumEnd
/* Check if we have a thread to swap to */
cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
je Return
/* Make space on the stack to save registers */
sub esp, 3 * 4
mov [esp+8], esi
mov [esp+4], edi
mov [esp+0], ebp
/* Get the current thread */
mov edi, [ebx+KPCR_CURRENT_THREAD]
#ifdef CONFIG_SMP
/* Raise to synch level */
call _KeRaiseIrqlToSynchLevel@0
/* Set context swap busy */
mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1
/* Acquire the PRCB Lock */
lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
jnb GetNext
lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK]
call @KefAcquireSpinLockAtDpcLevel@4
#endif
GetNext:
/* Get the next thread and clear it */
mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
/* Set us as the current running thread */
mov [ebx+KPCR_CURRENT_THREAD], esi
mov byte ptr [esi+KTHREAD_STATE_], Running
mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
/* Put thread in ECX and get the PRCB in EDX */
mov ecx, edi
lea edx, [ebx+KPCR_PRCB_DATA]
call @KiQueueReadyThread@8
/* Set APC_LEVEL and do the swap */
mov cl, APC_LEVEL
call @KiSwapContextInternal@0
#ifdef CONFIG_SMP
/* Lower IRQL back to dispatch */
mov cl, DISPATCH_LEVEL
call @KfLowerIrql@4
#endif
/* Restore registers */
mov ebp, [esp+0]
mov edi, [esp+4]
mov esi, [esp+8]
add esp, 3*4
Return:
/* All done */
pop ebx
ret
QuantumEnd:
/* Disable quantum end and process it */
mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
call _KiQuantumEnd@0
pop ebx
ret
.endfunc
.globl @KiIdleLoop@0
.func @KiIdleLoop@0, @KiIdleLoop@0
@KiIdleLoop@0:
@ -507,6 +625,7 @@ NoNextThread:
#endif
.endfunc
/* FIXFIX: Move to C code ****/
.globl _Ki386SetupAndExitToV86Mode@4
.func Ki386SetupAndExitToV86Mode@4
_Ki386SetupAndExitToV86Mode@4:

View file

@ -241,7 +241,7 @@ KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
VOID
FASTCALL
KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
KiInterruptTemplateHandler(IN PKTRAP_FRAME TrapFrame,
IN PKINTERRUPT Interrupt)
{
/* Enter interrupt frame */
@ -251,6 +251,7 @@ KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
((PKI_INTERRUPT_DISPATCH*)Interrupt->DispatchAddress)(TrapFrame, Interrupt);
}
KiTrap(KiInterruptTemplate, KI_PUSH_FAKE_ERROR_CODE | KI_HARDWARE_INT);
KiTrap(KiUnexpectedInterruptTail, KI_PUSH_FAKE_ERROR_CODE);
/* PUBLIC FUNCTIONS **********************************************************/
@ -308,7 +309,7 @@ KeInitializeInterrupt(IN PKINTERRUPT Interrupt,
for (i = 0; i < KINTERRUPT_DISPATCH_CODES; i++)
{
/* Copy the dispatch code */
*DispatchCode++ = KiInterruptTemplate[i];
*DispatchCode++ = ((PULONG)KiInterruptTemplate)[i];
}
/* Jump to the last 4 bytes */

View file

@ -10,12 +10,8 @@
#include <asm.h>
#include <internal/i386/asmmacro.S>
#include <internal/i386/callconv.s>
.intel_syntax noprefix
#define Running 2
#define WrDispatchInt 0x1F
/* GLOBALS *******************************************************************/
.data
@ -53,28 +49,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 */
/* System call entrypoints: */
.globl _KiFastCallEntry
.globl _KiSystemService
/* And special system-defined software traps: */
.globl _KiDispatchInterrupt@0
/* Interrupt template entrypoints */
.globl _KiInterruptTemplate
.globl _KiInterruptTemplateObject
.globl _KiInterruptTemplateDispatch
#ifndef HAL_INTERRUPT_SUPPORT_IN_C
/* Chained and Normal generic interrupt handlers for 1st and 2nd level entry*/
.globl _KiChainedDispatch2ndLvl@0
.globl _KiInterruptDispatch@0
.globl _KiChainedDispatch@0
#endif
/* We implement the following trap exit points: */
.globl _Kei386EoiHelper@0 /* Exit from interrupt or H/W trap */
.globl _KiIdtDescriptor
_KiIdtDescriptor:
.short 0
@ -85,63 +59,8 @@ _KiIdtDescriptor:
_KiUnexpectedEntrySize:
.long _KiUnexpectedInterrupt1 - _KiUnexpectedInterrupt0
_UnexpectedMsg:
.asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
_V86UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled V8086 (VDM) support at line: %lx!!!\n"
_UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx [%s]!!!\n"
_IsrTimeoutMsg:
.asciz "\n*** ISR at %lx took over .5 second\n"
_IsrOverflowMsg:
.asciz "\n*** ISR at %lx appears to have an interrupt storm\n"
/* SOFTWARE INTERRUPT SERVICES ***********************************************/
.text
.func Kei386EoiHelper@0
_Kei386EoiHelper@0:
/* Disable interrupts */
cli
/* Check for, and deliver, User-Mode APCs if needed */
CHECK_FOR_APC_DELIVER 0
/* Exit and cleanup */
_Kei386EoiHelper2ndEntry:
TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
.endfunc
V86_Exit:
/* Move to EDX position */
add esp, KTRAP_FRAME_EDX
/* Restore volatiles */
pop edx
pop ecx
pop eax
/* Move to non-volatiles */
lea esp, [ebp+KTRAP_FRAME_EDI]
pop edi
pop esi
pop ebx
pop ebp
/* Skip error code and return */
add esp, 4
iret
AbiosExit:
/* FIXME: TODO */
UNHANDLED_PATH
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/
/* HARDWARE INTERRUPT HANDLERS ************************************************/
.globl _KiStartUnexpectedRange@0
_KiStartUnexpectedRange@0:
@ -151,159 +70,3 @@ GENERATE_INT_HANDLERS
.globl _KiEndUnexpectedRange@0
_KiEndUnexpectedRange@0:
jmp _KiUnexpectedInterruptTail
/* DPC INTERRUPT HANDLER ******************************************************/
.func KiDispatchInterrupt@0
_KiDispatchInterrupt@0:
/* Preserve EBX */
push ebx
/* Get the PCR and disable interrupts */
mov ebx, PCR[KPCR_SELF]
cli
/* Check if we have to deliver DPCs, timers, or deferred threads */
mov eax, [ebx+KPCR_PRCB_DPC_QUEUE_DEPTH]
or eax, [ebx+KPCR_PRCB_TIMER_REQUEST]
or eax, [ebx+KPCR_PRCB_DEFERRED_READY_LIST_HEAD]
jz CheckQuantum
/* Save stack pointer and exception list, then clear it */
push ebp
push dword ptr [ebx+KPCR_EXCEPTION_LIST]
mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
/* Save the stack and switch to the DPC Stack */
mov edx, esp
mov esp, [ebx+KPCR_PRCB_DPC_STACK]
push edx
/* Deliver DPCs */
mov ecx, [ebx+KPCR_PRCB]
call @KiRetireDpcList@4
/* Restore stack and exception list */
pop esp
pop dword ptr [ebx+KPCR_EXCEPTION_LIST]
pop ebp
CheckQuantum:
/* Re-enable interrupts */
sti
/* Check if we have quantum end */
cmp byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
jnz QuantumEnd
/* Check if we have a thread to swap to */
cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
je Return
/* Make space on the stack to save registers */
sub esp, 3 * 4
mov [esp+8], esi
mov [esp+4], edi
mov [esp+0], ebp
/* Get the current thread */
mov edi, [ebx+KPCR_CURRENT_THREAD]
#ifdef CONFIG_SMP
/* Raise to synch level */
call _KeRaiseIrqlToSynchLevel@0
/* Set context swap busy */
mov byte ptr [edi+KTHREAD_SWAP_BUSY], 1
/* Acquire the PRCB Lock */
lock bts dword ptr [ebx+KPCR_PRCB_PRCB_LOCK], 0
jnb GetNext
lea ecx, [ebx+KPCR_PRCB_PRCB_LOCK]
call @KefAcquireSpinLockAtDpcLevel@4
#endif
GetNext:
/* Get the next thread and clear it */
mov esi, [ebx+KPCR_PRCB_NEXT_THREAD]
and dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0
/* Set us as the current running thread */
mov [ebx+KPCR_CURRENT_THREAD], esi
mov byte ptr [esi+KTHREAD_STATE_], Running
mov byte ptr [edi+KTHREAD_WAIT_REASON], WrDispatchInt
/* Put thread in ECX and get the PRCB in EDX */
mov ecx, edi
lea edx, [ebx+KPCR_PRCB_DATA]
call @KiQueueReadyThread@8
/* Set APC_LEVEL and do the swap */
mov cl, APC_LEVEL
call @KiSwapContextInternal@0
#ifdef CONFIG_SMP
/* Lower IRQL back to dispatch */
mov cl, DISPATCH_LEVEL
call @KfLowerIrql@4
#endif
/* Restore registers */
mov ebp, [esp+0]
mov edi, [esp+4]
mov esi, [esp+8]
add esp, 3*4
Return:
/* All done */
pop ebx
ret
QuantumEnd:
/* Disable quantum end and process it */
mov byte ptr [ebx+KPCR_PRCB_QUANTUM_END], 0
call _KiQuantumEnd@0
pop ebx
ret
.endfunc
/*
* We setup the stack for a trap frame in the KINTERRUPT DispatchCode itself and
* then move the stack address in ECX, since the handlers are FASTCALL. We also
* need to know the address of the KINTERRUPT. To do this, we maintain the old
* dynamic patching technique (EDX instead of EDI, however) and let the C API
* up in KeInitializeInterrupt replace the 0 with the address. Since this is in
* EDX, it becomes the second parameter for our FASTCALL function.
*
* Finally, we jump directly to the C interrupt handler, which will choose the
* appropriate dispatcher (chained, single, flat, floating) that was setup. The
* dispatchers themselves are also C FASTCALL functions. This double-indirection
* maintains the NT model should anything depend on it.
*
* Note that since we always jump to the C handler which then jumps to the C
* dispatcher, the first JMP in the template object is NOT patched anymore since
* it's static. Also, keep in mind this code is dynamically copied into nonpaged
* pool! It runs off the KINTERRUPT directly, so you can't just JMP to the code
* since JMPs are relative, and the location of the JMP below is dynamic. So we
* use EDI to store the absolute offset, and jump to that instead.
*
*/
.func KiInterruptTemplate
_KiInterruptTemplate:
TRAP_HANDLER_PROLOG 1, 0
_KiInterruptTemplate2ndDispatch:
/* Dummy code, will be replaced by the address of the KINTERRUPT */
mov edx, 0
_KiInterruptTemplateObject:
/* Jump to C code */
mov edi, offset @KiInterruptHandler@8
jmp edi
_KiInterruptTemplateDispatch:
/* Marks the end of the template so that the jump above can be edited */
.endfunc

View file

@ -1601,4 +1601,16 @@ KiTrap(KiDebugService, KI_PUSH_FAKE_ERROR_CODE);
KiTrap(KiSystemService, KI_PUSH_FAKE_ERROR_CODE | KI_NONVOLATILES_ONLY);
KiTrap(KiFastCallEntry, KI_FAST_SYSTEM_CALL);
/*
* @implemented
*/
VOID
NTAPI
Kei386EoiHelper(VOID)
{
/* We should never see this call happening */
DPRINT1("Mismatched NT/HAL version");
while (TRUE);
}
/* EOF */

View file

@ -200,9 +200,6 @@ SetEip:
/* Bring interrupts back */
sti
/* Write the debug data */
SET_TF_DEBUG_HEADER
/* Exit to user-mode */
mov ecx, esp
jmp @KiServiceExit@8