diff --git a/reactos/hal/halx86/generic/pic.c b/reactos/hal/halx86/generic/pic.c index 3e1419ed401..e2f08c4a33c 100644 --- a/reactos/hal/halx86/generic/pic.c +++ b/reactos/hal/halx86/generic/pic.c @@ -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); diff --git a/reactos/hal/halx86/include/halp.h b/reactos/hal/halx86/include/halp.h index 17bb5d7a9ec..ab7e01631f0 100644 --- a/reactos/hal/halx86/include/halp.h +++ b/reactos/hal/halx86/include/halp.h @@ -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); diff --git a/reactos/ntoskrnl/include/internal/i386/asmmacro.S b/reactos/ntoskrnl/include/internal/i386/asmmacro.S index 312a1f4de73..444232850c7 100644 --- a/reactos/ntoskrnl/include/internal/i386/asmmacro.S +++ b/reactos/ntoskrnl/include/internal/i386/asmmacro.S @@ -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 diff --git a/reactos/ntoskrnl/ke/time.c b/reactos/ntoskrnl/ke/time.c index 17488acce48..11fca02ea1c 100644 --- a/reactos/ntoskrnl/ke/time.c +++ b/reactos/ntoskrnl/ke/time.c @@ -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);