Author: sir_richard
Date: Mon Jan 11 18:44:09 2010
New Revision: 45045

URL: http://svn.reactos.org/svn/reactos?rev=45045&view=rev
Log:
Trap Handlers in C Patch 9 of 12:
    [NTOS]: Fix a logic bug in KiExitTrap: Always only restore segments if we 
came from user-mode (since they might be bogus on a kernel transition as 
they're not always saved), even if the caller wants segment restore.
    [NTOS]: Small perf boot: do a JMP, not a CALL into C handling code.
    [NTOS]: Make KiGetTickCount/KiCallbackReturn handled in C (as stubs).
    [NTOS]: Implement KeSynchronizeExecution in C. Move Kei386SpinOnSpinLock to 
C stub.
    [NTOS]: Implement overall architecture for handling hardware interrupts in 
C. Not used yet, since it needs C code in HAL.

Modified:
    trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
    trunk/reactos/ntoskrnl/include/internal/ke.h
    trunk/reactos/ntoskrnl/ke/i386/irqobj.c
    trunk/reactos/ntoskrnl/ke/i386/trap.s
    trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
    trunk/reactos/ntoskrnl/ke/spinlock.c

Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S?rev=45045&r1=45044&r2=45045&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] 
(original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] Mon 
Jan 11 18:44:09 2010
@@ -238,7 +238,7 @@
     pushad
     sub esp, KTRAP_FRAME_LENGTH - KTRAP_FRAME_PREVIOUS_MODE
     mov ecx, esp
-    call @&Name&hand...@4
+    jmp @&Name&hand...@4
 .endfunc
 .endm
 

Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ke.h?rev=45045&r1=45044&r2=45045&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Mon Jan 11 
18:44:09 2010
@@ -938,6 +938,7 @@
     VOID
 );
 
+#ifndef HAL_INTERRUPT_SUPPORT_IN_C
 VOID
 NTAPI
 KiInterruptDispatch(
@@ -949,6 +950,21 @@
 KiChainedDispatch(
     VOID
 );
+#else
+VOID
+FASTCALL
+KiInterruptDispatch(
+    IN PKTRAP_FRAME TrapFrame,
+    IN PKINTERRUPT Interrupt
+);
+
+VOID
+FASTCALL
+KiChainedDispatch(
+    IN PKTRAP_FRAME TrapFrame,
+    IN PKINTERRUPT Interrupt
+);
+#endif
 
 VOID
 NTAPI

Modified: trunk/reactos/ntoskrnl/ke/i386/irqobj.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/irqobj.c?rev=45045&r1=45044&r2=45045&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/irqobj.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/irqobj.c [iso-8859-1] Mon Jan 11 18:44:09 
2010
@@ -48,9 +48,9 @@
                                    KiUnexpectedEntrySize);
 
     /* Setup the handlers */
-    Dispatch->InterruptDispatch = KiInterruptDispatch;
+    Dispatch->InterruptDispatch = (PVOID)KiInterruptDispatch;
     Dispatch->FloatingDispatch = NULL; // Floating Interrupts are not supported
-    Dispatch->ChainedDispatch = KiChainedDispatch;
+    Dispatch->ChainedDispatch = (PVOID)KiChainedDispatch;
     Dispatch->FlatDispatch = NULL;
 
     /* Get the current handler */
@@ -97,7 +97,9 @@
 {
     DISPATCH_INFO Dispatch;
     PKINTERRUPT_ROUTINE Handler;
+#ifndef HAL_INTERRUPT_SUPPORT_IN_C
     PULONG Patch = &Interrupt->DispatchCode[0];
+#endif
 
     /* Get vector data */
     KiGetVectorDispatch(Interrupt->Vector, &Dispatch);
@@ -119,6 +121,8 @@
         /* Set the handler */
         Interrupt->DispatchAddress = Handler;
 
+        /* Read note in trap.s -- patching not needed since JMP is static */
+#ifndef HAL_INTERRUPT_SUPPORT_IN_C
         /* Jump to the last 4 bytes */
         Patch = (PULONG)((ULONG_PTR)Patch +
                          ((ULONG_PTR)&KiInterruptTemplateDispatch -
@@ -126,6 +130,7 @@
 
         /* Apply the patch */
         *Patch = (ULONG)((ULONG_PTR)Handler - ((ULONG_PTR)Patch + 4));
+#endif
 
         /* Now set the final handler address */
         ASSERT(Dispatch.FlatDispatch == NULL);
@@ -195,8 +200,10 @@
     }
 
     /* Sanity check */
+#ifndef HAL_INTERRUPT_SUPPORT_IN_C
     ASSERT((ULONG_PTR)&KiChainedDispatch2ndLvl -
            (ULONG_PTR)KiInterruptTemplate <= (KINTERRUPT_DISPATCH_CODES * 4));
+#endif
 
     /* Jump to the last 4 bytes */
     Patch = (PULONG)((ULONG_PTR)Patch +
@@ -390,4 +397,35 @@
     return State;
 }
 
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+KeSynchronizeExecution(IN OUT PKINTERRUPT Interrupt,
+                       IN PKSYNCHRONIZE_ROUTINE SynchronizeRoutine,
+                       IN PVOID SynchronizeContext OPTIONAL)
+{
+    NTSTATUS Status;
+    KIRQL OldIrql;
+    
+    /* Raise IRQL */
+    OldIrql = KfRaiseIrql(Interrupt->SynchronizeIrql);
+    
+    /* Acquire interrupt spinlock */
+    KeAcquireSpinLockAtDpcLevel(Interrupt->ActualLock);
+    
+    /* Call the routine */
+    Status = SynchronizeRoutine(SynchronizeContext);
+    
+    /* Release lock */
+    KeReleaseSpinLockFromDpcLevel(Interrupt->ActualLock);
+    
+    /* Lower IRQL */
+    KfLowerIrql(OldIrql);
+    
+    /* Return status */
+    return Status;
+}
+
 /* EOF */

Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?rev=45045&r1=45044&r2=45045&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Mon Jan 11 18:44:09 2010
@@ -54,7 +54,6 @@
 GENERATE_IDT_STUBS                  /* INT 30-FF: UNEXPECTED INTERRUPTS     */
 
 /* Trap handlers referenced from C code                                     */
-.globl _KiTrap2
 .globl _KiTrap8
 .globl _KiTrap19
 
@@ -69,7 +68,6 @@
 /* And special system-defined software traps:                               */
 .globl _ntraiseexcept...@12
 .globl _ntconti...@8
-.globl _kicoprocessorer...@0
 .globl _kidispatchinterr...@0
 
 /* Interrupt template entrypoints                                           */
@@ -77,10 +75,12 @@
 .globl _KiInterruptTemplateObject
 .globl _KiInterruptTemplateDispatch
 
+#ifndef HAL_INTERRUPT_SUPPORT_IN_C
 /* Chained and Normal generic interrupt handlers for 1st and 2nd level entry*/
 .globl _kichaineddispatch2nd...@0
 .globl _kiinterruptdispa...@0
 .globl _kichaineddispa...@0
+#endif
 
 /* We implement the following trap exit points:                             */
 .globl _KiServiceExit               /* Exit from syscall                    */
@@ -143,10 +143,6 @@
 /* SOFTWARE INTERRUPT SERVICES ***********************************************/
 .text
 
-_KiGetTickCount:
-_KiCallbackReturn:
-    /* FIXME: TODO */
-    UNHANDLED_PATH "TickCount/Callback Interrupts\n"
 
 .func KiSystemService
 TRAP_FIXUPS kss_a, kss_t, DoNotFixupV86, DoNotFixupAbios
@@ -473,6 +469,8 @@
     /* FIXME: TODO */
     UNHANDLED_PATH "ABIOS Exit"
 
+GENERATE_TRAP_HANDLER KiGetTickCount, 1
+GENERATE_TRAP_HANDLER KiCallbackReturn, 1        
 GENERATE_TRAP_HANDLER KiRaiseAssertion, 1
 GENERATE_TRAP_HANDLER KiDebugService, 1
 
@@ -768,6 +766,52 @@
     ret
 .endfunc
 
+/*
+ * This is how the new-style interrupt template will look like.
+ *
+ * We setup the stack for a trap frame in the KINTERRUPT DispatchCode itself 
and
+ * then mov 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.
+ *
+ */
+#ifdef HAL_INTERRUPT_SUPPORT_IN_C
+.func KiInterruptTemplate
+_KiInterruptTemplate:
+    push 0
+    pushad
+    sub esp, KTRAP_FRAME_LENGTH - KTRAP_FRAME_PREVIOUS_MODE
+    mov ecx, esp
+
+_KiInterruptTemplate2ndDispatch:
+    /* Dummy code, will be replaced by the address of the KINTERRUPT */
+    mov edx, 0
+
+_KiInterruptTemplateObject:
+    /* Jump to C code */
+    mov edi, offset @kiinterrupthand...@8
+    jmp edi
+
+_KiInterruptTemplateDispatch:
+    /* Marks the end of the template so that the jump above can be edited */
+.endfunc
+
+#else
+
 .func KiInterruptTemplate
 _KiInterruptTemplate:
 
@@ -982,74 +1026,4 @@
     /* Cleanup verification */
     VERIFY_INT_END kid, 0
 .endfunc
-
-.globl _kesynchronizeexecut...@12
-.func kesynchronizeexecut...@12
-_kesynchronizeexecut...@12:
-
-    /* Save EBX and put the interrupt object in it */
-    push ebx
-    mov ebx, [esp+8]
-
-    /* Go to DIRQL */
-    mov cl, [ebx+KINTERRUPT_SYNCHRONIZE_IRQL]
-    call @kfraisei...@4
-    push eax
-
-#ifdef CONFIG_SMP
-    /* Acquire the interrupt spinlock FIXME: Write this in assembly */
-    mov ecx, [ebx+KINTERRUPT_ACTUAL_LOCK]
-    call @kefacquirespinlockatdpcle...@4
 #endif
-
-    /* Call the routine */
-    push [esp+20]
-    call [esp+20]
-
-#ifdef CONFIG_SMP
-    /* Release the interrupt spinlock FIXME: Write this in assembly */
-    push eax
-    mov ecx, [ebx+KINTERRUPT_ACTUAL_LOCK]
-    call @kefreleasespinlockfromdpcle...@4
-    pop eax
-#endif
-
-    /* Lower IRQL */
-    mov ebx, eax
-    pop ecx
-    call @kfloweri...@4
-
-    /* Return status */
-    mov eax, ebx
-    pop ebx
-    ret 12
-.endfunc
-
-/*++
- * Kii386SpinOnSpinLock 
- *
- *     FILLMEIN
- *
- * Params:
- *     SpinLock - FILLMEIN
- *
- *     Flags - FILLMEIN
- *
- * Returns:
- *     None.
- *
- * Remarks:
- *     FILLMEIN
- *
- *--*/
-.globl _kii386spinonspinl...@8
-.func kii386spinonspinl...@8
-_kii386spinonspinl...@8:
-
-#ifdef CONFIG_SMP
-    /* FIXME: TODO */
-    int 3
-#endif
-
-    ret 8
-.endfunc

Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.c?rev=45045&r1=45044&r2=45045&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Mon Jan 11 18:44:09 
2010
@@ -89,17 +89,19 @@
         while (TRUE);
     }
     
-    /* Check if segments should be restored */
-    if (!SkipBits.SkipSegments)
-    {
-        /* Restore segments */
-        Ke386SetGs(TrapFrame->SegGs);
-        Ke386SetEs(TrapFrame->SegEs);
-        Ke386SetDs(TrapFrame->SegDs);
-        Ke386SetFs(TrapFrame->SegFs);
-    }
-    else if (KiUserTrap(TrapFrame))
-    {
+    /* Check if this is a user trap */
+    if (KiUserTrap(TrapFrame))
+    {
+        /* Check if segments should be restored */
+        if (!SkipBits.SkipSegments)
+        {
+            /* Restore segments */
+            Ke386SetGs(TrapFrame->SegGs);
+            Ke386SetEs(TrapFrame->SegEs);
+            Ke386SetDs(TrapFrame->SegDs);
+            Ke386SetFs(TrapFrame->SegFs);
+        }
+        
         /* Always restore FS since it goes from KPCR to TEB */
         Ke386SetFs(TrapFrame->SegFs);
     }
@@ -223,6 +225,58 @@
         UNIMPLEMENTED;
         while (TRUE);
     }
+}
+
+VOID
+FASTCALL
+KiEnterInterruptTrap(IN PKTRAP_FRAME TrapFrame)
+{
+    /* Save registers */
+    KiTrapFrameFromPushaStack(TrapFrame);
+    
+    /* Set bogus previous mode */
+    TrapFrame->PreviousPreviousMode = -1;
+    
+    /* Check for V86 mode */
+    if (TrapFrame->EFlags & EFLAGS_V86_MASK)
+    {
+        UNIMPLEMENTED;
+        while (TRUE);
+    }
+    
+    /* Check if this wasn't kernel code */
+    if (TrapFrame->SegCs != KGDT_R0_CODE)
+    {
+        /* Save segments and then switch to correct ones */
+        TrapFrame->SegFs = Ke386GetFs();
+        TrapFrame->SegGs = Ke386GetGs();
+        TrapFrame->SegDs = Ke386GetDs();
+        TrapFrame->SegEs = Ke386GetEs();
+        Ke386SetFs(KGDT_R0_PCR);
+        Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
+        Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
+    }
+    
+    /* Save exception list and terminate it */
+    TrapFrame->ExceptionList = KeGetPcr()->Tib.ExceptionList;
+    KeGetPcr()->Tib.ExceptionList = EXCEPTION_CHAIN_END;
+    
+    /* FIXME: This doesn't support 16-bit ABIOS interrupts */
+    TrapFrame->ErrCode = 0;
+    
+    /* Clear direction flag */
+    Ke386ClearDirectionFlag();
+    
+    /* Flush DR7 and check for debugging */
+    TrapFrame->Dr7 = 0;
+    if (KeGetCurrentThread()->DispatcherHeader.DebugActive & 0xFF)
+    {
+        UNIMPLEMENTED;
+        while (TRUE);
+    }
+    
+    /* Set debug header */
+    KiFillTrapFrameDebug(TrapFrame);
 }
 
 VOID
@@ -1499,6 +1553,24 @@
     KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 13, 0, 0, 1, TrapFrame);
 }
 
+/* SOFTWARE SERVICES 
**********************************************************/
+
+VOID
+FASTCALL
+KiGetTickCountHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    UNIMPLEMENTED;
+    while (TRUE);
+}
+
+VOID
+FASTCALL
+KiCallbackReturnHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    UNIMPLEMENTED;
+    while (TRUE);
+}
+
 VOID
 FASTCALL
 KiRaiseAssertionHandler(IN PKTRAP_FRAME TrapFrame)
@@ -1529,4 +1601,104 @@
     KiDebugHandler(TrapFrame, TrapFrame->Eax, TrapFrame->Ecx, TrapFrame->Edx);
 }
 
+/* HARDWARE INTERRUPTS 
********************************************************/
+
+/*
+ * This code can only be used once the HAL handles system interrupt code in C.
+ *
+ * This is because the HAL, when ending a system interrupt, might see pending
+ * DPC or APC interrupts, and attempt to piggyback on the interrupt context in
+ * order to deliver them. Once they have been devlivered, it will then "end" 
the
+ * interrupt context by doing a call to the ASM EOI Handler which naturally 
will
+ * throw up on our C-style KTRAP_FRAME.
+ *
+ * Once it works, expect a noticeable speed boost during hardware interrupts.
+ */
+#ifdef HAL_INTERRUPT_SUPPORT_IN_C
+
+typedef
+FASTCALL
+VOID
+(PKI_INTERRUPT_DISPATCH)(
+    IN PKTRAP_FRAME TrapFrame,
+    IN PKINTERRUPT Interrupt
+);
+
+VOID
+FORCEINLINE
+KiExitInterrupt(IN PKTRAP_FRAME TrapFrame,
+                IN KIRQL OldIrql,
+                IN BOOLEAN Spurious)
+{
+    if (Spurious) KiEoiHelper(TrapFrame);
+    
+    _disable();
+    
+    DPRINT1("Calling HAL to restore IRQL to: %d\n", OldIrql);
+    HalEndSystemInterrupt(OldIrql, 0);
+    
+    DPRINT1("Exiting trap\n");
+    KiEoiHelper(TrapFrame);
+}
+
+VOID
+FASTCALL
+KiInterruptDispatch(IN PKTRAP_FRAME TrapFrame,
+                    IN PKINTERRUPT Interrupt)
+{       
+    KIRQL OldIrql;
+
+    KeGetCurrentPrcb()->InterruptCount++;
+    
+    DPRINT1("Calling HAL with %lx %lx\n", Interrupt->SynchronizeIrql, 
Interrupt->Vector);
+    if (HalBeginSystemInterrupt(Interrupt->SynchronizeIrql,
+                                Interrupt->Vector,
+                                &OldIrql))
+    {
+        /* Acquire interrupt lock */
+        KxAcquireSpinLock(Interrupt->ActualLock);
+        
+        /* Call the ISR */
+        DPRINT1("Calling ISR: %p with context: %p\n", 
Interrupt->ServiceRoutine, Interrupt->ServiceContext);
+        Interrupt->ServiceRoutine(Interrupt, Interrupt->ServiceContext);
+        
+        /* Release interrupt lock */
+        KxReleaseSpinLock(Interrupt->ActualLock);
+        
+        /* Now call the epilogue code */
+        DPRINT1("Exiting interrupt\n");
+        KiExitInterrupt(TrapFrame, OldIrql, FALSE);
+    }
+    else
+    {
+        /* Now call the epilogue code */
+        DPRINT1("Exiting Spurious interrupt\n");
+        KiExitInterrupt(TrapFrame, OldIrql, TRUE);
+    }
+}
+
+VOID
+FASTCALL
+KiChainedDispatch(IN PKTRAP_FRAME TrapFrame,
+                  IN PKINTERRUPT Interrupt)
+{   
+    KeGetCurrentPrcb()->InterruptCount++;
+    
+    UNIMPLEMENTED;
+    while (TRUE);
+}
+
+VOID
+FASTCALL
+KiInterruptHandler(IN PKTRAP_FRAME TrapFrame,
+                   IN PKINTERRUPT Interrupt)
+{   
+    /* Enter interrupt frame */
+    KiEnterInterruptTrap(TrapFrame);
+
+    /* Call the correct dispatcher */
+    ((PKI_INTERRUPT_DISPATCH*)Interrupt->DispatchAddress)(TrapFrame, 
Interrupt);
+}
+#endif
+
 /* EOF */

Modified: trunk/reactos/ntoskrnl/ke/spinlock.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/spinlock.c?rev=45045&r1=45044&r2=45045&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/spinlock.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/spinlock.c [iso-8859-1] Mon Jan 11 18:44:09 2010
@@ -454,3 +454,17 @@
     /* Spinlock appears to be free */
     return TRUE;
 }
+
+#ifdef _M_IX86
+/*
+ * @unimplemented
+ */
+VOID
+NTAPI
+Kii386SpinOnSpinLock(IN PKSPIN_LOCK SpinLock,
+                     IN ULONG Flags)
+{
+    UNIMPLEMENTED;
+    while (TRUE);
+}
+#endif


Reply via email to