[PERF]: Optimize nested interrupt cases (where a pending interrupt exists at the...
authorSir Richard <sir_richard@svn.reactos.org>
Thu, 28 Jan 2010 20:45:45 +0000 (20:45 +0000)
committerSir Richard <sir_richard@svn.reactos.org>
Thu, 28 Jan 2010 20:45:45 +0000 (20:45 +0000)
[NTOS/HAL]: Rework respective code to handle this by using the VDM Alert field in the KPCR.

svn path=/trunk/; revision=45301

reactos/hal/halx86/generic/pic.c
reactos/hal/halx86/include/halp.h
reactos/ntoskrnl/include/internal/i386/asmmacro.S
reactos/ntoskrnl/ke/time.c

index 3e1419e..e2f08c4 100644 (file)
@@ -205,6 +205,15 @@ PHAL_SW_INTERRUPT_HANDLER SWInterruptHandlerTable[3] =
     HalpDispatchInterrupt
 };
 
+/* Handlers for pending software interrupts when we already have a trap frame*/
+PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3] =
+{
+    (PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)KiUnexpectedInterrupt,
+    HalpApcInterrupt2ndEntry,
+    HalpDispatchInterrupt2ndEntry
+};
+
+
 USHORT HalpEisaELCR;
 
 /* FUNCTIONS ******************************************************************/
@@ -552,9 +561,7 @@ HalpEndSoftwareInterrupt(IN KIRQL OldIrql)
     
     /* Check for pending software interrupts and compare with current IRQL */
     PendingIrql = SWInterruptLookUpTable[Pcr->IRR];
-
-    /* NOTE: We can do better! We need to support "jumping" a frame for nested cases! */
-    if (PendingIrql > OldIrql) SWInterruptHandlerTable[PendingIrql]();
+    if (PendingIrql > OldIrql) HalpNestedTrap(PendingIrql);
 }
 
 /* INTERRUPT DISMISSAL FUNCTIONS **********************************************/
@@ -811,55 +818,56 @@ HalEndSystemInterrupt(IN KIRQL OldIrql,
     
     /* Check for pending software interrupts and compare with current IRQL */
     PendingIrql = SWInterruptLookUpTable[Pcr->IRR];
-    if (PendingIrql > OldIrql) SWInterruptHandlerTable[PendingIrql]();
+    if (PendingIrql > OldIrql) HalpNestedTrap(PendingIrql);
 }
 
 /* SOFTWARE INTERRUPT TRAPS ***************************************************/
 
 VOID
-FASTCALL
-HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+FORCEINLINE
+DECLSPEC_NORETURN
+_HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
 {
     KIRQL CurrentIrql;
     PKPCR Pcr = KeGetPcr();
     
-    /* Set up a fake INT Stack */
-    TrapFrame->EFlags = __readeflags();
-    TrapFrame->SegCs = KGDT_R0_CODE;
-    TrapFrame->Eip = TrapFrame->Eax;
-    
-    /* Build the trap frame */
-    KiEnterInterruptTrap(TrapFrame);
-    
     /* Save the current IRQL and update it */
     CurrentIrql = Pcr->Irql;
     Pcr->Irql = APC_LEVEL;
-    
+
     /* Remove DPC from IRR */
     Pcr->IRR &= ~(1 << APC_LEVEL);
-    
+
     /* Enable interrupts and call the kernel's APC interrupt handler */
     _enable();
     KiDeliverApc(((KiUserTrap(TrapFrame)) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) ?
-                 UserMode : KernelMode,
-                 NULL,
-                 TrapFrame);
+                UserMode : KernelMode,
+                NULL,
+                TrapFrame);
 
     /* Disable interrupts and end the interrupt */
     _disable();
+    Pcr->VdmAlert = (ULONG_PTR)TrapFrame;
     HalpEndSoftwareInterrupt(CurrentIrql);
-    
+
     /* Exit the interrupt */
-    KiEoiHelper(TrapFrame);
+    KiEoiHelper(TrapFrame); 
 }
 
 VOID
 FASTCALL
-HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+DECLSPEC_NORETURN
+HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)
+{
+    /* Do the work */
+    _HalpApcInterruptHandler(TrapFrame);
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
 {
-    KIRQL CurrentIrql;
-    PKPCR Pcr = KeGetPcr();
-    
     /* Set up a fake INT Stack */
     TrapFrame->EFlags = __readeflags();
     TrapFrame->SegCs = KGDT_R0_CODE;
@@ -868,6 +876,18 @@ HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
     /* Build the trap frame */
     KiEnterInterruptTrap(TrapFrame);
     
+    /* Do the work */
+    _HalpApcInterruptHandler(TrapFrame);
+}
+
+VOID
+FORCEINLINE
+DECLSPEC_NORETURN
+_HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{
+    KIRQL CurrentIrql;
+    PKPCR Pcr = KeGetPcr();
+    
     /* Save the current IRQL and update it */
     CurrentIrql = Pcr->Irql;
     Pcr->Irql = DISPATCH_LEVEL;
@@ -881,10 +901,37 @@ HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
     
     /* Disable interrupts and end the interrupt */
     _disable();
+    Pcr->VdmAlert = (ULONG_PTR)TrapFrame;
     HalpEndSoftwareInterrupt(CurrentIrql);
     
     /* Exit the interrupt */
-    KiEoiHelper(TrapFrame);
+    KiEoiHelper(TrapFrame);   
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame)
+{
+    /* Do the work */
+    _HalpDispatchInterruptHandler(TrapFrame);
+}
+
+VOID
+FASTCALL
+DECLSPEC_NORETURN
+HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
+{  
+    /* Set up a fake INT Stack */
+    TrapFrame->EFlags = __readeflags();
+    TrapFrame->SegCs = KGDT_R0_CODE;
+    TrapFrame->Eip = TrapFrame->Eax;
+    
+    /* Build the trap frame */
+    KiEnterInterruptTrap(TrapFrame);
+    
+    /* Do the work */
+    _HalpDispatchInterruptHandler(TrapFrame);
 }
 
 KiTrap(HalpApcInterrupt,      KI_SOFTWARE_TRAP);
index 17bb5d7..ab7e016 100644 (file)
@@ -22,6 +22,19 @@ typedef struct _HAL_BIOS_FRAME
     ULONG Prefix;
 } HAL_BIOS_FRAME, *PHAL_BIOS_FRAME;
 
+typedef
+VOID
+(*PHAL_SW_INTERRUPT_HANDLER)(
+    VOID
+);
+
+typedef
+FASTCALL
+VOID
+(*PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)(
+    IN PKTRAP_FRAME TrapFrame
+);
+
 #define HAL_APC_REQUEST         0
 #define HAL_DPC_REQUEST         1
 
@@ -98,6 +111,28 @@ HalpRealModeStack(IN ULONG Alignment,
     );
 }
 
+//
+// Nested Trap Trampoline
+//
+VOID
+DECLSPEC_NORETURN
+FORCEINLINE
+HalpNestedTrap(IN KIRQL PendingIrql)
+{
+    /* Use the second interrupt handler table */
+    extern PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3];
+    __asm__ __volatile__
+    (
+        "movl %c[t], %%ecx\n"
+        "jmp *%0\n"
+        :
+        : "im"(SWInterruptHandlerTable2[PendingIrql]),
+          [t] "i"(&PCR->VdmAlert)
+        : "%esp"
+    );
+    UNREACHABLE;
+}
+
 //
 // Commonly stated as being 1.19318MHz
 //
@@ -431,12 +466,6 @@ typedef struct _PIC_MASK
     };    
 } PIC_MASK, *PPIC_MASK;
 
-typedef
-VOID
-(*PHAL_SW_INTERRUPT_HANDLER)(
-    VOID
-);
-
 typedef
 BOOLEAN
 __attribute__((regparm(3)))
@@ -531,6 +560,8 @@ HalpEnableInterruptHandler(IN UCHAR Flags,
 VOID NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts);
 VOID HalpApcInterrupt(VOID);
 VOID HalpDispatchInterrupt(VOID);
+VOID FASTCALL HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame);
+VOID FASTCALL HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame);
 
 /* timer.c */
 VOID NTAPI HalpInitializeClock(VOID);
index 312a1f4..4442328 100644 (file)
@@ -1452,6 +1452,8 @@ FastExit:
     cli
 
     /* End the interrupt and do EOI */
+    lea eax, [esp+8]
+    mov PCR[KPCR_VDM_ALERT], eax
     call _HalEndSystemInterrupt@8
     jmp _Kei386EoiHelper@0
 .endif
index 17488ac..11fca02 100644 (file)
@@ -112,6 +112,9 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame,
         Prcb->InterruptCount++;
     }
     
+    /* Save the nested trap frame address */
+    KeGetPcr()->VdmAlert = (ULONG_PTR)TrapFrame;
+    
     /* Disable interrupts and end the interrupt */
     _disable();
     HalEndSystemInterrupt(Irql, CLOCK2_LEVEL);