[NTOS]: Implement the KiInterruptTemplate in C since we now have a C entrry macro...
authorSir Richard <sir_richard@svn.reactos.org>
Fri, 29 Jan 2010 01:12:08 +0000 (01:12 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Fri, 29 Jan 2010 01:12:08 +0000 (01:12 +0000)
[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

reactos/ntoskrnl/include/internal/i386/asmmacro.S
reactos/ntoskrnl/include/internal/i386/ke.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/include/internal/trap_x.h
reactos/ntoskrnl/ke/i386/ctxswitch.S
reactos/ntoskrnl/ke/i386/irqobj.c
reactos/ntoskrnl/ke/i386/trap.s
reactos/ntoskrnl/ke/i386/traphdlr.c
reactos/ntoskrnl/ke/i386/usercall_asm.S

index 0ada3a7..d0fabe9 100644 (file)
 
 #include <ndk/asm.h>
 
-// Arguments for TRAP_EPILOG
-#define FromSystemCall              1
-#define DoRestorePreviousMode       1
-#define DoRestoreEverything         1
-#define DoRestoreSegments           1
-#define DoRestoreVolatiles          1
-#define DoPushFakeErrorCode         1
-#define DoFixupV86                  1
-#define DoFixupAbios                1
-#define NotFromSystemCall           0
-#define DoNotRestorePreviousMode    0
-#define DoNotRestoreEverything      0
-#define DoNotRestoreSegments        0
-#define DoNotRestoreVolatiles       0
-#define DoNotPushFakeErrorCode      0
-#define DoNotFixupV86               0
-#define DoNotFixupAbios             0
-
 // Arguments for idt
 #define INT_32_DPL0                 0x8E00
 #define INT_32_DPL3                 0xEE00
 
-//
-// This table contains the prefix flags that are used by V86 emulation
-//
-.equ PREFIX_FLAG_ES,                0x00000100
-.equ PREFIX_FLAG_CS,                0x00000200
-.equ PREFIX_FLAG_SS,                0x00000400
-.equ PREFIX_FLAG_DS,                0x00000800
-.equ PREFIX_FLAG_FS,                0x00001000
-.equ PREFIX_FLAG_GS,                0x00002000
-.equ PREFIX_FLAG_OPER32,            0x00004000
-.equ PREFIX_FLAG_ADDR32,            0x00008000
-.equ PREFIX_FLAG_LOCK,              0x00010000
-.equ PREFIX_FLAG_REPNE,             0x00020000
-.equ PREFIX_FLAG_REP,               0x00040000
-
 .intel_syntax noprefix
 
 //
 #define RELEASE_SPINLOCK(x) 
 #endif
 
-//
-// @name UNHANDLED_PATH
-//
-// This macro prints out that the current code path is not expected yet
-//
-// @param None
-//
-// @remark None.
-//
-.macro UNHANDLED_PATH Reason
-
-    /* Push reason */
-    push offset 1f
-
-    /* Get EIP */
-    call $+5
-
-    /* Print debug message */
-    push offset _UnhandledMsg
-    call _DbgPrint
-    add esp, 12
-
-    /* Loop indefinitely */
-    jmp $
-
-1:
-    .asciz \Reason
-.endm
-
-//
-// @name UNHANDLED_V86_PATH
-//
-// This macro prints out that the current code path is for unhandled VDM support
-//
-// @param None
-//
-// @remark None.
-//
-.macro UNHANDLED_V86_PATH
-    /* Get EIP */
-    call $+5
-
-    /* Print debug message */
-    push offset _V86UnhandledMsg
-    call _DbgPrint
-    add esp, 8
-
-    /* Loop indefinitely */
-    jmp $
-.endm
-
 //
 // @name IDT
 //
@@ -219,1331 +135,3 @@ _KiUnexpectedInterrupt&Number:
     .set i, i + 1
 .endr
 .endm
-
-//
-// @name TRAP_HANDLER_PROLOG
-//
-// This macro creates a kernel trap handler.
-//
-// @param None.
-//
-// @remark None.
-//
-.macro TRAP_HANDLER_PROLOG ErrorCode=1, Software=0
-
-    /* What kind of trap is it */
-    .if \Software
-        /* Software traps need a fake interrupt stack */
-        pop eax
-        sub esp, KTRAP_FRAME_ESP
-    .elseif \ErrorCode
-        /* Some traps generate an error code, some don't (thanks, Intel!) */
-        sub esp, KTRAP_FRAME_EIP
-    .else
-        sub esp, KTRAP_FRAME_ERROR_CODE
-    .endif
-
-    /* Make space for trap frame and save registers before we enter C code */
-    mov [esp+KTRAP_FRAME_EAX], eax
-    mov [esp+KTRAP_FRAME_EBX], ebx
-    mov [esp+KTRAP_FRAME_ECX], ecx
-    mov [esp+KTRAP_FRAME_EDX], edx
-    mov [esp+KTRAP_FRAME_ESI], esi
-    mov [esp+KTRAP_FRAME_EDI], edi
-    mov [esp+KTRAP_FRAME_EBP], ebp
-    mov ecx, esp
-.endm
-
-//
-// @name GENERATE_TRAP_HANDLER
-//
-// This macro creates a kernel trap handler.
-//
-// @param None.
-//
-// @remark None.
-//
-.macro GENERATE_TRAP_HANDLER Name, ErrorCode=1, FastV86=0, Software=0
-.globl _&Name
-.func Name
-_&Name:
-    TRAP_HANDLER_PROLOG ErrorCode, Software
-    /*
-     * The GPF and Invalid Opcode handlers are performance critical when talking
-     * about V8086 traps, because they control the main flow of execution during
-     * that mode (GPFs will be issued for any privileged instruction we need to
-     * emulate, and invalid opcode might be generated for BOPs).
-     *
-     * Because of this, we employ a fast entry/exit macro into V8086 mode since
-     * we can make certain assumptions. We detect, and use, such scenarios when
-     * the V8086 flag is enabled in EFLAGS.
-     *
-     * However, because we can land in a GPF handler with an invalid DS/ES, as
-     * some V8086 code could trample this during BIOS calls for example, we must
-     * make sure that we are on a valid DS/ES before dereferencing any pointer.
-     *
-     * We fixup DS/ES either in KiEnterTrap (for normal entry/exit) or, for V86,
-     * in KiEnterV86Trap. Notice the problem: we need to detect which of these
-     * to use early on but we can't touch the EFLAGS in the frame because DS/ES
-     * could be invalid.
-     *
-     * Thankfully SS is always guaranteed valid, so stack dereferences are game!
-     *
-     * We therefore read the EFLAGS here, in assembly, where we can touch ESP as
-     * we please. We save this in EDX, which will be used as the second argument
-     * for the FASTCALL C trap entry.
-     *
-     * When we make the fast V86 check, we use the parameter instead of the trap
-     * frame, leading us to using the correct trap entry function, which fixes
-     * up DS/ES and lets us go on our merry way...
-     */
-    .if \FastV86
-        mov edx, [esp+KTRAP_FRAME_EFLAGS]
-    .endif
-
-    /* Normally we just have one parameter, but fast V86 handlers need two */
-    .if \FastV86
-        jmp @&Name&Handler@8
-    .else
-        jmp @&Name&Handler@4
-    .endif
-.endfunc
-.endm
-
-//
-// @name GENERATE_HAL_INT_HANDLER
-//
-// This macro creates a HAL hardware interrupt handler.
-//
-// @param None.
-//
-// @remark None.
-//
-.macro GENERATE_HAL_INT_HANDLER Number
-.func HalpHardwareInterrupt&Number
-_HalpHardwareInterrupt&Number:
-    int PRIMARY_VECTOR_BASE + Number
-    ret
-.endfunc
-.endm
-
-//
-// @name GENERATE_HAL_INT_HANDLERS
-//
-// This macro creates the unexpected interrupt handlers.
-//
-// @param None.
-//
-// @remark None.
-//
-.macro GENERATE_HAL_INT_HANDLERS
-.set i, 0
-.rept 16
-    GENERATE_HAL_INT_HANDLER %i
-    .set i, i + 1
-.endr
-.endm
-
-//
-// @name INVALID_V86_OPCODE
-//
-// This macro creates one or more entries for unhandled V86 Opcodes
-// in the V86 Opcode Table.
-//
-// @param count.
-//        Number of entries to generate.
-//
-// @remark None.
-//
-.macro INVALID_V86_OPCODE count
-    .rept \count
-        .byte 0
-    .endr
-.endm
-
-//
-// @name GENERATE_PREFIX_HANDLER
-//
-// This macro creates a prefix opcode handler.
-//
-// @param None.
-//
-// @remark None.
-//
-.macro GENERATE_PREFIX_HANDLER Name
-.func Opcode&Name&PrefixV86
-_Opcode&Name&PrefixV86:
-    or ebx, PREFIX_FLAG_&Name
-    jmp _OpcodeGenericPrefixV86
-.endfunc
-.endm
-
-//
-// @name INVALID_V86_OPCODE
-//
-// This macro prints out visible message and hangs the computer.
-//
-// @param None.
-//
-// @remark Temporary debugging use.
-//
-.macro UNHANDLED_V86_OPCODE
-    /* Print debug message, breakpoint and freeze */
-    push ecx
-    push offset V86DebugMsg
-    call _DbgPrint
-    add esp, 8
-    jmp $
-.endm
-
-//
-// @name TRAP_FIXUPS
-//
-// This macro contains out-of-line code for various Trap Frame Fixups, such as:
-//
-//  - DR Fixup: Loads and restores DR registers.
-//  - V86 Fixup: Loads and restores V86 segments.
-//  - ABIOS Fixup: Loads and restores the ABIOS state and stack.
-//
-// @param None.
-//
-// @remark ebp = PKTRAP_FRAME
-//
-.macro TRAP_FIXUPS Label, EndLabel, V86Fix, AbiosFix
-Dr_&Label:
-
-    /* Check if this was V86 mode */
-    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
-    jnz 2f
-
-    /* Check if it was user mode */
-    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
-    jz Dr_&EndLabel
-
-2:
-    /* Get DR0, 1, 2 */
-    mov ebx, dr0
-    mov ecx, dr1
-    mov edi, dr2
-
-    /* Save them */
-    mov [ebp+KTRAP_FRAME_DR0], ebx
-    mov [ebp+KTRAP_FRAME_DR1], ecx
-    mov [ebp+KTRAP_FRAME_DR2], edi
-
-    /* Get DR3, 6, 7 */
-    mov ebx, dr3
-    mov ecx, dr6
-    mov edi, dr7
-
-    /* Save them */
-    mov [ebp+KTRAP_FRAME_DR3], ebx
-    mov [ebp+KTRAP_FRAME_DR6], ecx
-    mov [ebp+KTRAP_FRAME_DR7], edi
-
-    /* Clear DR7 */
-    xor ebx, ebx
-    mov dr7, ebx
-
-    /* Get the PRCB */
-    mov edi, fs:[KPCR_PRCB]
-
-    /* Get DR0, 1 */
-    mov ebx, [edi+KPRCB_DR0]
-    mov ecx, [edi+KPRCB_DR1]
-
-    /* Set them */
-    mov dr0, ebx
-    mov dr1, ecx
-
-    /* Get DR2, 3 */
-    mov ebx, [edi+KPRCB_DR2]
-    mov ecx, [edi+KPRCB_DR3]
-
-    /* Set them */
-    mov dr2, ebx
-    mov dr3, ecx
-
-    /* Get DR6, 7 */
-    mov ebx, [edi+KPRCB_DR6]
-    mov ecx, [edi+KPRCB_DR7]
-
-    /* Set them */
-    mov dr6, ebx
-    mov dr7, ecx
-    jmp Dr_&EndLabel
-
-.if \AbiosFix
-Abios_&Label:
-    UNHANDLED_PATH
-.endif
-
-.if \V86Fix
-V86_&Label:
-
-    /* Get V86 segment registers */
-    mov eax, [ebp+KTRAP_FRAME_V86_FS]
-    mov ebx, [ebp+KTRAP_FRAME_V86_GS]
-    mov ecx, [ebp+KTRAP_FRAME_V86_ES]
-    mov edx, [ebp+KTRAP_FRAME_V86_DS]
-
-    /* Restore them into Protected Mode trap frame */
-    mov [ebp+KTRAP_FRAME_FS], ax
-    mov [ebp+KTRAP_FRAME_GS], bx
-    mov [ebp+KTRAP_FRAME_ES], cx
-    mov [ebp+KTRAP_FRAME_DS], dx
-
-    /* Go back to mainline code */
-    jmp V86_&EndLabel
-.endif
-.endm
-
-//
-// @name SET_TF_DEBUG_HEADER
-//
-// This macro sets up the debug header in the trap frame.
-//
-// @param None.
-//
-// @remark ebp = PKTRAP_FRAME.
-//         edi/ebx = Have been saved and can be used.
-//
-.macro SET_TF_DEBUG_HEADER
-    /* Get the Debug Trap Frame EBP/EIP */
-    mov ebx, [ebp+KTRAP_FRAME_EBP]
-    mov edi, [ebp+KTRAP_FRAME_EIP]
-
-    /* Write the debug data */
-    mov [ebp+KTRAP_FRAME_DEBUGPOINTER], edx
-    mov dword ptr [ebp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
-    mov [ebp+KTRAP_FRAME_DEBUGEBP], ebx
-    mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
-.endm
-
-//
-// @name CHECK_FOR_APC_DELIVER
-// 
-// This macro checks if the trapframe indicates a return to user-mode,
-// and, if so, checks if user-mode APCs should be delivered.
-//
-// @param PreserveEax
-//        Determines if EAX should be preserved. Implies that the segment
-//        registers will also be saved.
-//
-// @remark ebp = PKTRAP_FRAME.
-//         ebx = Saved and will be used.
-//
-.macro CHECK_FOR_APC_DELIVER PreserveEax
-    /* Check for V86 mode */
-    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
-    jnz 1f
-
-    /* Deliver APCs only if we were called from user mode */
-    test byte ptr [ebp+KTRAP_FRAME_CS], 1
-    je 2f
-
-    /* Get the current thread */
-1:
-    mov ebx, PCR[KPCR_CURRENT_THREAD]
-
-    /* Make it non-alerted */
-    mov byte ptr [ebx+KTHREAD_ALERTED], 0
-
-    /* And only if any are actually pending */
-    cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
-    je 2f
-
-    /* Save pointer to Trap Frame */
-    mov ebx, ebp
-
-.if \PreserveEax
-    /* Save some stuff that raising IRQL will kill */
-    mov [ebx+KTRAP_FRAME_EAX], eax
-    mov dword ptr [ebx+KTRAP_FRAME_FS], KGDT_R3_TEB + RPL_MASK
-    mov dword ptr [ebx+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
-    mov dword ptr [ebx+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
-    mov dword ptr [ebx+KTRAP_FRAME_GS], 0
-.endif
-
-    /* Raise IRQL to APC_LEVEL */
-    mov ecx, 1
-    call @KfRaiseIrql@4
-
-    /* Save old IRQL */
-    push eax
-
-    /* Deliver APCs */
-    sti
-    push ebx
-    push 0
-    push UserMode
-    call _KiDeliverApc@12
-
-    /* Return to old IRQL */
-    pop ecx
-    call @KfLowerIrql@4
-
-    /* Restore EAX (only in volatile case) */
-.if \PreserveEax
-    mov eax, [ebx+KTRAP_FRAME_EAX]
-.endif
-    cli
-    jmp 1b
-2:
-.endm
-
-//
-// @name TRAP_PROLOG
-// 
-// This macro creates a standard trap entry prologue.
-// It should be used for entry into any kernel trap (KiTrapXx), but not for
-// system calls, which require special handling.
-//
-// @param Label
-//        Identifying name of the caller function; will be used to append
-//        to the name V86 and DR helper functions, which must already exist.
-//
-// @remark Use as follows:
-//          _KiTrap00:
-//              /* Push fake error code */
-//              push 0
-//
-//              /* Enter common prologue */
-//              TRAP_PROLOG(0)
-//
-//              /* Handle trap */
-//              <Your Trap Code Here>
-//
-.macro TRAP_PROLOG Label EndLabel
-    /* Just to be safe, clear out the HIWORD, since it's reserved */
-    mov word ptr [esp+2], 0
-
-    /* Save the non-volatiles */
-    push ebp
-    push ebx
-    push esi
-    push edi
-
-    /* Save FS and set it to PCR */
-    push fs
-    mov ebx, KGDT_R0_PCR
-    .byte 0x66
-    mov fs, bx
-
-    /* Save exception list and bogus previous mode */
-    push fs:[KPCR_EXCEPTION_LIST]
-    push -1
-
-    /* Save volatiles and segment registers */
-    push eax
-    push ecx
-    push edx
-    push ds
-    push es
-    push gs
-
-    /* Set the R3 data segment */
-    mov ax, KGDT_R3_DATA + RPL_MASK
-
-    /* Skip debug registers and debug stuff */
-    sub esp, 0x30
-
-    /* Load the segment registers */
-    .byte 0x66
-    mov ds, ax
-    .byte 0x66
-    mov es, ax
-
-    /* Check if this interrupt happened in 16-bit mode */
-    cmp esp, 0x10000
-    jb _Ki16BitStackException
-
-    /* Set up frame */
-    mov ebp, esp
-
-    /* Check if this was from V86 Mode */
-    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
-    jnz V86_&Label
-
-V86_&EndLabel:
-    /* Get current thread */
-    mov ecx, fs:[KPCR_CURRENT_THREAD]
-    cld
-
-    /* Flush DR7 */
-    and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
-    /* Check if the thread was being debugged */
-    test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
-    jnz Dr_&Label
-
-    /* Set the Trap Frame Debug Header */
-Dr_&EndLabel:
-    SET_TF_DEBUG_HEADER
-.endm
-
-//
-// @name INT_PROLOG
-// 
-// This macro creates a standard interrupt entry prologue.
-// It should be used for entry into any interrupt, including software.
-//
-// @param Label
-//        Identifying name of the caller function; will be used to append
-//        to the name V86, ABIOS and DR helper functions, which must exist.
-//
-// @remark For software interrupts, make sure that a fake INT stack is created.
-//
-.macro INT_PROLOG Label EndLabel FakeErrorCode
-
-.if \FakeErrorCode
-    /* Save fake error code */
-    push esp
-.endif
-
-    /* Save the non-volatiles */
-    push ebp
-    push ebx
-    push esi
-    push edi
-
-    /* Skip debug registers and other stuff */
-    sub esp, 0x54
-
-    /* Set up frame */
-    mov ebp, esp
-
-    /* Save volatiles */ 
-    mov [esp+KTRAP_FRAME_EAX], eax
-    mov [esp+KTRAP_FRAME_ECX], ecx
-    mov [esp+KTRAP_FRAME_EDX], edx
-    mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1
-
-    /* Check if this was from V86 Mode */
-    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
-    jnz V86_&Label
-
-    /* Check if this was kernel mode */
-V86_&EndLabel:
-    cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
-    jz 1f
-
-    /* Set segments */
-    mov word ptr [esp+KTRAP_FRAME_FS], fs
-    mov word ptr [esp+KTRAP_FRAME_DS], ds
-    mov word ptr [esp+KTRAP_FRAME_ES], es
-    mov [esp+KTRAP_FRAME_GS], gs
-
-    /* Load the segment registers (use OVERRIDE (0x66)) */
-    mov ebx, KGDT_R0_PCR
-    mov eax, KGDT_R3_DATA | RPL_MASK
-    .byte 0x66
-    mov fs, bx
-    .byte 0x66
-    mov ds, ax
-    .byte 0x66
-    mov es, ax
-
-1: 
-    /* Get the previous exception list */
-    mov ebx, fs:[KPCR_EXCEPTION_LIST]
-
-    /* Set the exception handler chain terminator */
-    mov dword ptr fs:[KPCR_EXCEPTION_LIST], -1
-
-    /* Save the previous exception list */
-    mov [esp+KTRAP_FRAME_EXCEPTION_LIST], ebx
-
-.ifeq \FakeErrorCode
-    /* Setup the 16-bit stack */
-    lea eax, [esp+KTRAP_FRAME_ERROR_CODE]
-    lea ecx, [esp+KTRAP_FRAME_EIP]
-    mov ebx, ss:[eax]
-    mov ss:[eax], ecx
-.endif
-
-    /* Check if this is the ABIOS stack */
-    /* cmp esp, 0x10000*/
-    /* jb Abios_Label*/
-
-    /* Delete error code */
-    and dword ptr [esp+KTRAP_FRAME_ERROR_CODE], 0
-
-    /* Get the current thread and clear direction flag */
-    mov ecx, PCR[KPCR_CURRENT_THREAD]
-    cld
-
-    /* Flush DR7 */
-    and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
-    /* Check if the thread was being debugged */
-    test byte ptr [ecx+KTHREAD_DEBUG_ACTIVE], 0xFF
-
-.ifeq \FakeErrorCode
-    /* Push parameter */
-    push ebx
-.endif
-
-    /* Save DR registers if needed */
-    jnz Dr_&Label
-
-    /* Set the trap frame debug header */
-Dr_&EndLabel:
-    SET_TF_DEBUG_HEADER
-.endm
-
-//
-// @name SYSCALL_PROLOG
-// 
-// This macro creates a system call entry prologue.
-// It should be used for entry into any fast-system call (KiGetTickCount,
-// KiCallbackReturn, KiRaiseAssertion) and the generic system call handler
-// (KiSystemService)
-//
-// @param Label
-//        Unique label identifying the name of the caller function; will be
-//        used to append to the name of the DR helper function, which must
-//        already exist.
-//
-// @remark None.
-//
-.macro SYSCALL_PROLOG Label EndLabel
-    /* Create a trap frame */
-    push 0
-    push ebp
-    push ebx
-    push esi
-    push edi
-    push fs
-
-    /* Load PCR Selector into fs */
-    mov ebx, KGDT_R0_PCR
-    .byte 0x66
-    mov fs, bx
-
-    /* Get a pointer to the current thread */
-    mov esi, PCR[KPCR_CURRENT_THREAD]
-
-    /* Save the previous exception list */
-    push PCR[KPCR_EXCEPTION_LIST]
-
-    /* Set the exception handler chain terminator */
-    mov dword ptr PCR[KPCR_EXCEPTION_LIST], -1
-
-    /* Save the old previous mode */
-    push [esi+KTHREAD_PREVIOUS_MODE]
-
-    /* Skip the other registers */
-    sub esp, 0x48
-
-    /* Set the new previous mode based on the saved CS selector */
-    mov ebx, [esp+0x6C]
-    and ebx, 1
-    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], bl
-
-    /* Go on the Kernel stack frame */
-    mov ebp, esp
-
-    /* Save the old trap frame pointer where EDX would be saved */
-    mov ebx, [esi+KTHREAD_TRAP_FRAME]
-    mov [ebp+KTRAP_FRAME_EDX], ebx
-
-    /* Flush DR7 */
-    and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
-    /* Check if the thread was being debugged */
-    test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
-
-    /* Set the thread's trap frame and clear direction flag */
-    mov [esi+KTHREAD_TRAP_FRAME], ebp
-    cld
-
-    /* Save DR registers if needed */
-    jnz Dr_&Label
-
-    /* Set the trap frame debug header */
-Dr_&EndLabel:
-    SET_TF_DEBUG_HEADER
-
-    /* Enable interrupts */
-    sti
-.endm
-
-//
-// @name FASTCALL_PROLOG
-// 
-// TODO
-//
-// @param Label
-//        Unique label identifying the name of the caller function; will be
-//        used to append to the name of the DR helper function, which must
-//        already exist.
-//
-// @remark None.
-//
-.macro FASTCALL_PROLOG Label EndLabel
-
-    /* Set user selector */
-    mov ecx, KGDT_R3_DATA | RPL_MASK
-
-    /* Set FS to PCR */
-    push KGDT_R0_PCR
-    pop fs
-
-    /* Set DS/ES to User Selector */
-    mov ds, cx
-    mov es, cx
-
-    /* Set the current stack to Kernel Stack */
-    mov ecx, PCR[KPCR_TSS]
-    mov esp, [ecx+KTSS_ESP0]
-
-    /* Set up a fake INT Stack. */
-    push KGDT_R3_DATA + RPL_MASK
-    push edx                            /* Ring 3 SS:ESP */
-    pushf                               /* Ring 3 EFLAGS */
-    push 2                              /* Ring 0 EFLAGS */
-    add edx, 8                          /* Skip user parameter list */
-    popf                                /* Set our EFLAGS */
-    or dword ptr [esp], EFLAGS_INTERRUPT_MASK   /* Re-enable IRQs in EFLAGS, to fake INT */
-    push KGDT_R3_CODE + RPL_MASK
-    push dword ptr ds:KUSER_SHARED_SYSCALL_RET
-
-    /* Setup the Trap Frame stack */
-    push 0
-    push ebp
-    push ebx
-    push esi
-    push edi
-    push KGDT_R3_TEB + RPL_MASK
-
-    /* Save pointer to our PCR */
-    mov ebx, PCR[KPCR_SELF]
-
-    /* Get a pointer to the current thread */
-    mov esi, [ebx+KPCR_CURRENT_THREAD]
-
-    /* Set the exception handler chain terminator */
-    push [ebx+KPCR_EXCEPTION_LIST]
-    mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
-
-    /* Use the thread's stack */
-    mov ebp, [esi+KTHREAD_INITIAL_STACK]
-
-    /* Push previous mode */
-    push UserMode
-
-    /* Skip the other registers */
-    sub esp, 0x48
-
-    /* Make space for us on the stack */
-    sub ebp, 0x29C
-
-    /* Write the previous mode */
-    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
-
-    /* Sanity check */
-    cmp ebp, esp
-    jnz BadStack
-
-    /* Flush DR7 */
-    and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
-    /* Check if the thread was being debugged */
-    test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
-
-    /* Set the thread's trap frame */
-    mov [esi+KTHREAD_TRAP_FRAME], ebp
-
-    /* Save DR registers if needed */
-    jnz Dr_&Label
-
-    /* Set the trap frame debug header */
-Dr_&EndLabel:
-    SET_TF_DEBUG_HEADER
-
-    /* Enable interrupts */
-    sti
-.endm
-
-//
-// @name V86_TRAP_PROLOG
-// 
-// This macro creates a V86 Trap entry prologue.
-// It should be used for entry into any fast-system call (KiGetTickCount,
-// KiCallbackReturn, KiRaiseAssertion) and the generic system call handler
-// (KiSystemService)
-//
-// @param Label
-//        Unique label identifying the name of the caller function; will be
-//        used to append to the name of the DR helper function, which must
-//        already exist.
-//
-// @remark None.
-//
-.macro V86_TRAP_PROLOG Label EndLabel
-
-    /* Skip everything to the error code */
-    sub esp, KTRAP_FRAME_ERROR_CODE
-
-    /* Clear the error code */
-    mov word ptr [esp+KTRAP_FRAME_ERROR_CODE+2], 0
-
-    /* Save the registers we'll trample */
-    mov [esp+KTRAP_FRAME_EBX], ebx
-    mov [esp+KTRAP_FRAME_EAX], eax
-    mov [esp+KTRAP_FRAME_EBP], ebp
-    mov [esp+KTRAP_FRAME_ESI], esi
-    mov [esp+KTRAP_FRAME_EDI], edi
-
-    /* Save PCR and Ring 3 segments */
-    mov ebx, KGDT_R0_PCR
-    mov eax, KGDT_R3_DATA + RPL_MASK
-
-    /* Save ECX and EDX too */
-    mov [esp+KTRAP_FRAME_ECX], ecx
-    mov [esp+KTRAP_FRAME_EDX], edx
-
-    /* Set debugging markers */
-    mov dword ptr [esp+KTRAP_FRAME_PREVIOUS_MODE], -1
-    mov dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
-
-    /* Now set segments (use OVERRIDE, 0x66) */
-    .byte 0x66
-    mov fs, bx
-    .byte 0x66
-    mov ds, ax
-    .byte 0x66
-    mov es, ax
-
-    /* Set the trap frame in the stack and clear the direction flag */
-    mov ebp, esp
-    cld
-
-    /* Save the exception list */
-    mov eax, fs:[KPCR_EXCEPTION_LIST]
-    mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax
-
-    /* Check if we need debugging */
-    mov eax, dr7
-    test eax, ~DR7_RESERVED_MASK
-    mov [esp+KTRAP_FRAME_DR7], eax
-    jnz Dr_&Label
-
-Dr_&EndLabel:
-.endm
-
-//
-// @name V86_TRAP_EPILOG
-// 
-// This macro creates an epilogue for leaving V86 traps
-//
-// @param None.
-//
-// @remark None.
-//
-.macro V86_TRAP_EPILOG
-
-    /* Get the current thread and make it unalerted */
-ExitBegin:
-    mov ebx, PCR[KPCR_CURRENT_THREAD]
-    mov byte ptr [ebx+KTHREAD_ALERTED], 0
-
-    /* Check if it has User-mode APCs pending */
-    cmp byte ptr [ebx+KTHREAD_PENDING_USER_APC], 0
-    jne PendingUserApc
-
-    /* It doesn't, pop the frame */
-    add esp, KTRAP_FRAME_EDX
-    pop edx
-    pop ecx
-    pop eax
-
-    /* Check if DR registers should be restored */
-    test dword ptr [ebp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK
-    jnz V86DebugRestore
-
-    /* Finish popping the rest of the frame, and return to P-mode */
-V86DebugContinue:
-    add esp, 12
-    pop edi
-    pop esi
-    pop ebx
-    pop ebp
-    add esp, 4
-    iretd
-
-V86DebugRestore:
-
-    /* Get DR0, 1 */
-    xor ebx, ebx
-    mov esi, [ebp+KTRAP_FRAME_DR0]
-    mov edi, [ebp+KTRAP_FRAME_DR1]
-
-    /* Clear DR 7 */
-    mov dr7, ebx
-
-    /* Get DR2 and load DR0-2 */
-    mov ebx, [ebp+KTRAP_FRAME_DR2]
-    mov dr0, esi
-    mov dr1, edi
-    mov dr2, ebx
-
-    /* Get DR3-7 */
-    mov esi, [ebp+KTRAP_FRAME_DR0]
-    mov edi, [ebp+KTRAP_FRAME_DR1]
-    mov ebx, [ebp+KTRAP_FRAME_DR7]
-
-    /* Load them */
-    mov dr3, esi
-    mov dr6, edi
-    mov dr7, ebx
-    jmp V86DebugContinue
-
-PendingUserApc:
-
-    /* Raise to APC level */
-    mov ecx, APC_LEVEL
-    call @KfRaiseIrql@4
-
-    /* Save KIRQL and deliver APCs */
-    push eax
-    sti
-    push ebp
-    push 0
-    push UserMode
-    call _KiDeliverApc@12
-
-    /* Restore IRQL */
-    pop ecx
-    call @KfLowerIrql@4
-    cli
-
-    /* Check if we're not in V86 anymore */
-    test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
-    jnz ExitBegin
-.endm
-
-//
-// @name TRAP_EPILOG
-// 
-// This macro creates an epilogue for leaving any system trap.
-// It is used for exiting system calls, exceptions, interrupts and generic
-// traps.
-//
-// @param SystemCall
-//        Specifies whether this trap will exit a system call. If so, special
-//        code will be assembled to potentially use SYSEXIT instead of IRETD.
-//
-// @param RestorePreviousMode
-//        Specifies if the previous mode should be restored.
-//
-// @param RestoreSegments
-//        Specifies if the segment registers should be restored.
-//
-// @param RestoreVolatiles
-//        Specifies if the volatile registers should be restored.
-//
-// @param RestoreAllRegs
-//        Specifies if volatiles and segments should both be restored.
-//
-// @remark
-//
-.macro TRAP_EPILOG SystemCall, RestorePreviousMode, RestoreSegments, RestoreVolatiles, RestoreAllRegs
-#if DBG
-    /* Assert the flags */
-    pushfd
-    pop edx
-    test edx, EFLAGS_INTERRUPT_MASK
-    jnz 6f
-
-    /* Assert the stack */
-    cmp esp, ebp
-    jnz 6f
-
-    /* Assert the trap frame */
-#endif
-5:
-#if DBG
-    sub dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
-    jnz 0f
-
-    /* Assert FS */
-    mov bx, fs
-    cmp bx, KGDT_R0_PCR
-    jnz 1f
-
-    /* Assert exception list */
-    cmp dword ptr PCR[KPCR_EXCEPTION_LIST], 0
-    jnz 2f
-
-1:
-    push -1
-    call _KeBugCheck@4
-#endif
-
-2:
-    /* Get exception list */
-    mov edx, [esp+KTRAP_FRAME_EXCEPTION_LIST]
-
-#if DBG
-    /* Assert the saved exception list */
-    or edx, edx
-    jnz 1f
-    UNHANDLED_PATH
-1:
-#endif
-
-    /* Restore it */
-    mov PCR[KPCR_EXCEPTION_LIST], edx
-
-.if \RestorePreviousMode
-    /* Get previous mode */
-    mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
-
-#if DBG
-    /* Assert the saved previous mode */
-    cmp ecx, -1
-    jnz 1f
-    UNHANDLED_PATH
-1:
-#endif
-
-    /* Restore the previous mode */
-    mov esi, PCR[KPCR_CURRENT_THREAD]
-    mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], cl
-.else
-
-#if DBG
-    /* Assert the saved previous mode */
-    mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
-    cmp ecx, -1
-    jz 1f
-    UNHANDLED_PATH
-1:
-#endif
-.endif
-
-    /* Check for debug registers */
-    test dword ptr [esp+KTRAP_FRAME_DR7], ~DR7_RESERVED_MASK
-    jnz 2f
-
-    /* Check for V86 */
-4:
-    test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
-    jnz V86_Exit
-
-    /* Check if the frame was edited */
-    test word ptr [esp+KTRAP_FRAME_CS], FRAME_EDITED
-    jz 7f
-
-.if \RestoreAllRegs
-    /* Check the old mode */
-    cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
-    bt word ptr [esp+KTRAP_FRAME_CS], 0
-    cmc
-    ja 8f
-.endif
-
-.if \RestoreVolatiles
-    /* Restore volatiles */
-    mov edx, [esp+KTRAP_FRAME_EDX]
-    mov ecx, [esp+KTRAP_FRAME_ECX]
-    mov eax, [esp+KTRAP_FRAME_EAX]
-.endif
-
-    /* Check if we were called from kernel mode */
-    cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R0_CODE
-    jz 9f
-
-.if \RestoreSegments
-    /* Restore segment registers */
-    lea esp, [ebp+KTRAP_FRAME_GS]
-    pop gs
-    pop es
-    pop ds
-.endif
-
-    /* Restore FS */
-3:
-    lea esp, [ebp+KTRAP_FRAME_FS]
-    pop fs
-
-9:
-    /* Skip debug information and unsaved registers */
-    lea esp, [ebp+KTRAP_FRAME_EDI]
-    pop edi
-    pop esi
-    pop ebx
-    pop ebp
-
-    /* Check for ABIOS */
-    cmp word ptr [esp+8], 0x80
-    ja AbiosExit
-
-    /* Pop error code */
-    add esp, 4
-
-.if \SystemCall
-    /* Check if previous CS is from user-mode */
-    test dword ptr [esp+4], 1
-
-    /* It is, so use Fast Exit */
-    jnz FastExit
-
-    /* Jump back to stub */
-    pop edx
-    pop ecx
-    popf
-    jmp edx
-
-.ret:
-.endif
-    iret
-
-.if \SystemCall
-FastExit:
-    /* Is SYSEXIT Supported/Wanted? */
-    cmp dword ptr ss:[_KiFastSystemCallDisable], 0
-    jnz .ret
-    test dword ptr [esp+8], EFLAGS_TF
-    jnz .ret
-
-    /* Restore FS to TIB */
-    mov ecx, KGDT_R3_TEB + RPL_MASK
-    mov fs, ecx
-
-    /* We will be cleaning up the stack ourselves */
-    pop edx                                 /* New Ring 3 EIP */
-    add esp, 4                              /* Skip Ring 3 DS */
-    and dword ptr [esp], 0xfffffdff         /* Remove EFLAGS_INTERRUPT_MASK from EFLAGS */
-    popf                                    /* Restore old EFLAGS */
-    pop ecx                                 /* Old Ring 3 SS:ESP */
-
-    /*
-     * At this point:
-     *     ECX points to the old User Stack.
-     *     EDX points to the instruction to execute in usermode after the sysenter
-     */
-    sti
-    sysexit
-.endif
-
-.if \RestoreAllRegs
-8:
-    /* Restore EAX */
-    mov eax, [esp+KTRAP_FRAME_EAX]
-
-    /* Skip registers */
-    add esp, 0x30
-
-    /* Restore segments and volatiles */
-    pop gs
-    pop es
-    pop ds
-    pop edx
-    pop ecx
-
-    /* Jump back to mainline code */
-    jmp 3b
-.endif
-
-#if DBG
-0:
-    /* Fix up the mask */
-    add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
-
-6:
-    UNHANDLED_PATH
-    jmp 5b
-#endif
-
-2:
-    /* Check if this was V86 mode */
-    test dword ptr [esp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
-    jnz 1f
-
-    /* Check if it was user mode */
-    test word ptr [esp+KTRAP_FRAME_CS], MODE_MASK
-    jz 4b
-
-1:
-    /* Clear DR7 */
-    xor ebx, ebx
-    mov dr7, ebx
-
-    /* Get DR0, 1, 2 */
-    mov esi, [ebp+KTRAP_FRAME_DR0]
-    mov edi, [ebp+KTRAP_FRAME_DR1]
-    mov ebx, [ebp+KTRAP_FRAME_DR2]
-
-    /* Set them */
-    mov dr0, esi
-    mov dr1, edi
-    mov dr2, ebx
-
-    /* Get DR3, 6, 7 */
-    mov esi, [ebp+KTRAP_FRAME_DR3]
-    mov edi, [ebp+KTRAP_FRAME_DR6]
-    mov ebx, [ebp+KTRAP_FRAME_DR7]
-
-    /* Set them */
-    mov dr3, esi
-    mov dr6, edi
-    mov dr7, ebx
-    jmp 4b
-
-7:
-    /* Restore real CS value */
-    mov ebx, [esp+KTRAP_FRAME_TEMPCS]
-    mov [esp+KTRAP_FRAME_CS], ebx
-
-    /*
-     * If ESP was modified, then a special interrupt exit stack
-     * must be created to "update" ESP's value in a legal manner
-     */
-    mov ebx, [esp+KTRAP_FRAME_TEMPESP]
-    sub ebx, 0xC
-    mov [esp+KTRAP_FRAME_ERROR_CODE], ebx
-
-    /* Copy Interrupt Stack */
-    mov esi, [esp+KTRAP_FRAME_EFLAGS]
-    mov [ebx+8], esi
-    mov esi, [esp+KTRAP_FRAME_CS]
-    mov [ebx+4], esi
-    mov esi, [esp+KTRAP_FRAME_EIP]
-    mov [ebx], esi
-
-.if \RestoreVolatiles
-    /* Restore volatiles */
-    mov eax, [esp+KTRAP_FRAME_EAX]
-    mov edx, [esp+KTRAP_FRAME_EDX]
-    mov ecx, [esp+KTRAP_FRAME_ECX]
-.endif
-
-    /* Return */
-    add esp, KTRAP_FRAME_EDI
-    pop edi
-    pop esi
-    pop ebx
-    pop ebp
-    mov esp, [esp]
-    iret
-.endm
-
-//
-// @name INT_EPILOG
-// 
-// This macro creates an epilogue for leaving any system trap.
-// It is used for exiting system calls, exceptions, interrupts and generic
-// traps.
-//
-// @param Spurious - TRUE if the interrupt was unexpected and spurious.
-//
-// @remark None.
-//
-.macro INT_EPILOG Spurious
-
-.if \Spurious
-    /* Just exit the trap */
-    jmp _Kei386EoiHelper@0
-.else
-    /* Disable interrupts */
-    cli
-
-    /* End the interrupt and do EOI */
-    lea eax, [esp+8]
-    mov PCR[KPCR_VDM_ALERT], eax
-    call _HalEndSystemInterrupt@8
-    jmp _Kei386EoiHelper@0
-.endif
-.endm
-
-#if DBG
-
-.macro VERIFY_INT Label
-    /* Get the current time and mask it to 192 ticks */
-    mov eax, _KeTickCount
-    and eax, 0xC0
-
-    /* Check if we're in the same tick area */
-    cmp eax, dword ptr [edi+KINTERRUPT_TICK_COUNT]
-    jg VfRst_&Label
-    jl VfWrap_&Label
-
-    /* If we got here, then our count is too large */
-    dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT]
-    jz VfOvr_&Label
-Vf_&Label:
-.endm
-
-.macro VERIFY_INT_END Label, Info
-VfOvr_&Label:
-
-    /* Decrement the dispatch count and check if we should bug check */
-    dec word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2]
-    jz 1f
-
-    /* Update the tick count */
-    add eax, 0x40
-    mov [edi+KINTERRUPT_TICK_COUNT], eax
-    jmp VfRstDef_&Label
-
-1:
-    /* Check if the debugger is enabled */
-    cmp byte ptr __KdDebuggerEnabled, 0
-    jnz 1f
-
-    /* It isn't, bugcheck */
-    push Info
-    push edi
-    push [edi+KINTERRUPT_SERVICE_CONTEXT]
-    push [edi+KINTERRUPT_SERVICE_ROUTINE]
-    push HARDWARE_INTERRUPT_STORM
-    call _KeBugCheckEx@20
-
-1:
-    /* Debugger enabled, do a debug print + break instead */
-    push [edi+KINTERRUPT_SERVICE_ROUTINE]
-    push offset _IsrOverflowMsg
-    call _DbgPrint
-    add esp, 8
-    int 3
-
-    /* Breakpoint handled, get the new tick count */
-    mov eax, _KeTickCount
-    and eax, 0xC0
-
-VfRst_&Label:
-    /* Reset tick count */
-    mov dword ptr [edi+KINTERRUPT_TICK_COUNT], eax
-    mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT+2], 64
-
-VfRstDef_&Label:
-    /* Put default overflow count and continue */
-    mov ax, _KiISROverflow
-    mov word ptr [edi+KINTERRUPT_DISPATCH_COUNT], ax
-    jmp Vf_&Label
-
-VfWrap_&Label:
-    /* Check if we wrapped */
-    add eax, 0x40
-    cmp eax, [edi+KINTERRUPT_TICK_COUNT]
-    je Vf_&Label
-
-    /* We did, start over */
-    mov eax, _KeTickCount
-    jmp VfRst_&Label
-.endm
-
-#else
-
-/* We don't verify interrupts on retail builds */
-.macro VERIFY_INT Label
-.endm
-.macro VERIFY_INT_END Label, Info
-.endm
-
-#endif
-
-
index 1f4ee01..ceba343 100644 (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);
index 70d743e..9169dfd 100644 (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;
index e71b1c0..f5ca8e9 100644 (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
index 3cd98b9..4af3f9b 100644 (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:
index 2c19ae4..b58b1da 100644 (file)
@@ -241,8 +241,8 @@ KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
 
 VOID
 FASTCALL
-KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
-                   IN PKINTERRUPT Interrupt)
+KiInterruptTemplateHandler(IN PKTRAP_FRAME TrapFrame,
+                           IN PKINTERRUPT Interrupt)
 {   
     /* Enter interrupt frame */
     KiEnterInterruptTrap(TrapFrame);
@@ -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 */
index 1d6ffec..293cd6f 100644 (file)
 
 #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
index df7ef3d..9e0c29c 100644 (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 */
index da0642d..017a736 100644 (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