[PERF]: Optimize nested interrupt cases (where a pending interrupt exists at the end of a software or system interrupt) just like the old HAL did, by jumping into a second-level handler and completing the outer trap frame instead of the nested trap frame. This saves a lot of cycles in those cases, and they do happen quite often (pending DPC at the end of an interrupt, for example).

[NTOS/HAL]: Rework respective code to handle this by using the VDM Alert field in the KPCR.

svn path=/trunk/; revision=45301
This commit is contained in:
Sir Richard 2010-01-28 20:45:45 +00:00
parent 55c5579b1d
commit 7509f62a3b
4 changed files with 115 additions and 32 deletions

View 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);

View 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);

View 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

View 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);