mirror of
https://github.com/reactos/reactos.git
synced 2025-07-24 12:03:37 +00:00
[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:
parent
55c5579b1d
commit
7509f62a3b
4 changed files with 115 additions and 32 deletions
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue