From 459b5c212e7eabe6b73215067354764f1427a47e Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Sat, 10 Sep 2011 15:55:15 +0000 Subject: [PATCH] [HAL/APIC] - Implement HalpApcInterruptHandler, fix HalpDispatchInterruptHandler - Insert a read to the APIC version register in ApicGetCurrentIrql(). This fixes inconsistencies between the internal APIC state and register reads/writes. - Remove old hacks in ApicGetCurrentIrql() and ApicSetCurrentIrql - Fix HalpVectorToIrql() - read/write cr8 for the value of the TPR on amd64 builds - Fix amd64 build svn path=/trunk/; revision=53673 --- reactos/hal/halx86/amd64/halinit.c | 31 +++---- reactos/hal/halx86/amd64/stubs.c | 93 +-------------------- reactos/hal/halx86/amd64/systimer.S | 64 -------------- reactos/hal/halx86/apic/apic.c | 111 ++++++++++++++++++------- reactos/hal/halx86/apic/halinit_apic.c | 18 +++- 5 files changed, 113 insertions(+), 204 deletions(-) diff --git a/reactos/hal/halx86/amd64/halinit.c b/reactos/hal/halx86/amd64/halinit.c index 23c8746b345..13e94c8fbf5 100644 --- a/reactos/hal/halx86/amd64/halinit.c +++ b/reactos/hal/halx86/amd64/halinit.c @@ -20,6 +20,23 @@ BOOLEAN HalpPciLockSettings; /* FUNCTIONS *****************************************************************/ +VOID +NTAPI +HalpInitProcessor( + IN ULONG ProcessorNumber, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + DPRINT1("ApicInitializeProcessor(%ld)\n", ProcessorNumber); + + /* Initialize the local APIC for this cpu */ + ApicInitializeLocalApic(ProcessorNumber); + + /* Initialize the timer */ + //ApicInitializeTimer(ProcessorNumber); + +} + + VOID HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { @@ -32,18 +49,4 @@ HalpInitPhase1(VOID) } -VOID -INIT_FUNCTION -HalpInitializeClock(VOID) -{ -} -VOID -HalpCalibrateStallExecution() -{ -} - -VOID -HalpInitializePICs(IN BOOLEAN EnableInterrupts) -{ -} diff --git a/reactos/hal/halx86/amd64/stubs.c b/reactos/hal/halx86/amd64/stubs.c index 34495bdf9fd..f3cfd726db6 100644 --- a/reactos/hal/halx86/amd64/stubs.c +++ b/reactos/hal/halx86/amd64/stubs.c @@ -14,99 +14,8 @@ /* GLOBALS ********************************************************************/ -LARGE_INTEGER HalpPerformanceFrequency; +//LARGE_INTEGER HalpPerformanceFrequency; /* FUNCTIONS ******************************************************************/ -VOID -FASTCALL -HalClearSoftwareInterrupt( - IN KIRQL Irql) -{ - UNIMPLEMENTED; -} - -VOID -FASTCALL -HalRequestSoftwareInterrupt( - IN KIRQL Irql) -{ - UNIMPLEMENTED; -} - -BOOLEAN -NTAPI -HalBeginSystemInterrupt( - IN KIRQL Irql, - IN UCHAR Vector, - OUT PKIRQL OldIrql) -{ - UNIMPLEMENTED; - return FALSE; -} - -BOOLEAN -NTAPI -HalEnableSystemInterrupt( - IN UCHAR Vector, - IN KIRQL Irql, - IN KINTERRUPT_MODE InterruptMode) -{ - UNIMPLEMENTED; - return FALSE; -} - -VOID -NTAPI -HalDisableSystemInterrupt( - IN UCHAR Vector, - IN KIRQL Irql) -{ - UNIMPLEMENTED; -} - -VOID -NTAPI -HalEndSystemInterrupt( - IN KIRQL OldIrql, - IN PKTRAP_FRAME TrapFrame) -{ - UNIMPLEMENTED; -} - -LARGE_INTEGER -NTAPI -KeQueryPerformanceCounter( - OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL) -{ - LARGE_INTEGER Result; - -// ASSERT(HalpPerformanceFrequency.QuadPart != 0); - - /* Does the caller want the frequency? */ - if (PerformanceFrequency) - { - /* Return value */ - *PerformanceFrequency = HalpPerformanceFrequency; - } - - Result.QuadPart = __rdtsc(); - return Result; -} - -VOID -NTAPI -HalCalibratePerformanceCounter(IN volatile PLONG Count, - IN ULONGLONG NewCount) -{ - UNIMPLEMENTED; -} - -ULONG -NTAPI -HalSetTimeIncrement(IN ULONG Increment) -{ - UNIMPLEMENTED; - return 0; -} diff --git a/reactos/hal/halx86/amd64/systimer.S b/reactos/hal/halx86/amd64/systimer.S index d4ed099c968..11323eecd9b 100644 --- a/reactos/hal/halx86/amd64/systimer.S +++ b/reactos/hal/halx86/amd64/systimer.S @@ -23,70 +23,6 @@ MsgUnimplemented: .code64 -PUBLIC HalpCalibrateStallExecution@0 -HalpCalibrateStallExecution@0: -PUBLIC HalpProfileInterrupt -HalpProfileInterrupt: - - -PUBLIC KeStallExecutionProcessor -KeStallExecutionProcessor: - - /* Get the number of microseconds required */ - jecxz Done - - /* Multiply by the stall factor */ - mov eax, gs:[PcStallScaleFactor] - mul ecx - - /* Align to 16 bytes */ - .align 16 - - /* Jump to subtraction loop */ - jmp SubtractLoop - - /* Align to 16 bytes */ - .align 16 - - /* Subtract one count */ -SubtractLoop: - sub eax, 1 - jnz SubtractLoop - -Done: - /* Return */ - ret 4 - - -PUBLIC HalpQuery8254Counter -HalpQuery8254Counter: - - /* Save EFLAGS and disable interrupts */ - pushfq - cli - - /* Set timer data */ - mov al, 0 - out HEX(43), al - jmp $+2 - - /* Read current timer */ - in al, HEX(40) - jmp $+2 - movzx ecx, al - in al, HEX(40) - mov ch, al - - /* Return it and restore interrupt state */ - mov eax, ecx - popfq - ret - -PUBLIC HalpClockInterrupt -HalpClockInterrupt: - UNIMPLEMENTED _HalpClockInterrupt - iret - END diff --git a/reactos/hal/halx86/apic/apic.c b/reactos/hal/halx86/apic/apic.c index 27f5e3de706..ff51e742dab 100644 --- a/reactos/hal/halx86/apic/apic.c +++ b/reactos/hal/halx86/apic/apic.c @@ -16,9 +16,11 @@ #include #include "apic.h" +void HackEoi(void); /* GLOBALS ********************************************************************/ +ULONG ApicVersion; UCHAR HalpVectorToIndex[256]; #ifndef _M_AMD64 @@ -101,6 +103,14 @@ IOApicWrite(UCHAR Register, ULONG Value) *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value; } +VOID +FORCEINLINE +ApicSendEOI(void) +{ + //ApicWrite(APIC_EOI, 0); + HackEoi(); +} + KIRQL FORCEINLINE ApicGetProcessorIrql(VOID) @@ -113,24 +123,27 @@ KIRQL FORCEINLINE ApicGetCurrentIrql(VOID) { - // HACK: This won't work with amd64, where cr8 is modified directly, but - // VBox is broken and returns a wrong value when using a vmmcall after a - // page table modification. - return KeGetPcr()->Irql; +#ifdef _M_AMD64 + return (KIRQL)__readcr8(); +#else + // HACK: some magic to Sync VBox's APIC registers + ApicRead(APIC_VER); /* Read the TPR and convert it to an IRQL */ return TprToIrql(ApicRead(APIC_TPR)); +#endif } VOID FORCEINLINE ApicSetCurrentIrql(KIRQL Irql) { +#ifdef _M_AMD64 + __writecr8(Irql); +#else /* Convert IRQL and write the TPR */ ApicWrite(APIC_TPR, IrqlToTpr(Irql)); - - /* HACK: Keep PCR field in sync, s.a. */ - KeGetPcr()->Irql = Irql; +#endif } UCHAR @@ -150,7 +163,7 @@ KIRQL FASTCALL HalpVectorToIrql(UCHAR Vector) { - return TprToIrql(Vector >> 2); + return TprToIrql(Vector); } UCHAR @@ -249,6 +262,9 @@ ApicInitializeLocalApic(ULONG Cpu) SpIntRegister.FocusCPUCoreChecking = 0; ApicWrite(APIC_SIVR, SpIntRegister.Long); + /* Read the version and save it globally */ + if (Cpu == 0) ApicVersion = ApicRead(APIC_VER); + /* Set the mode to flat (max 8 CPUs supported!) */ ApicWrite(APIC_DFR, APIC_DF_Flat); @@ -430,6 +446,7 @@ ApicInitializeIOApic(VOID) ReDirReg.Destination = ApicRead(APIC_ID); IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0); + ApicSendEOI(); } VOID @@ -447,15 +464,23 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts) /* Initialize the I/O APIC */ ApicInitializeIOApic(); - ApicWrite(APIC_EOI, 0); - /* Register interrupt handlers */ + /* Manually reserve some vectors */ + HalpVectorToIndex[APIC_CLOCK_VECTOR] = 8; + HalpVectorToIndex[APC_VECTOR] = 99; + HalpVectorToIndex[DISPATCH_VECTOR] = 99; + + /* Set interrupt handlers in the IDT */ KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt); #ifndef _M_AMD64 KeRegisterInterruptHandler(APC_VECTOR, HalpApcInterrupt); - KeRegisterInterruptHandler(DPC_VECTOR, HalpDispatchInterrupt); + KeRegisterInterruptHandler(DISPATCH_VECTOR, HalpDispatchInterrupt); #endif + /* Register the vectors for APC and dispatch interrupts */ + HalpRegisterVector(IDT_INTERNAL, 0, APC_VECTOR, APC_LEVEL); + HalpRegisterVector(IDT_INTERNAL, 0, DISPATCH_VECTOR, DISPATCH_LEVEL); + /* Restore interrupt state */ if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK; __writeeflags(EFlags); @@ -466,11 +491,40 @@ DECLSPEC_NORETURN FASTCALL HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) { + KPROCESSOR_MODE ProcessorMode; + KIRQL OldIrql; ASSERT(ApicGetCurrentIrql() < APC_LEVEL); ASSERT(ApicGetProcessorIrql() == APC_LEVEL); - UNIMPLEMENTED; - ASSERT(FALSE); + /* Enter trap */ + KiEnterInterruptTrap(TrapFrame); + + /* Save the old IRQL */ + OldIrql = ApicGetCurrentIrql(); + + /* Set APC_LEVEL */ + ApicSetCurrentIrql(APC_LEVEL); + + /* Kernel or user APC? */ + if (KiUserTrap(TrapFrame)) ProcessorMode = UserMode; + else if (TrapFrame->EFlags & EFLAGS_V86_MASK) ProcessorMode = UserMode; + else ProcessorMode = KernelMode; + + /* Enable interrupts and call the kernel's APC interrupt handler */ + _enable(); + KiDeliverApc(ProcessorMode, NULL, TrapFrame); + + /* Disable interrupts */ + _disable(); + + /* Restore the old IRQL */ + ApicSetCurrentIrql(OldIrql); + + /* End the interrupt */ + ApicSendEOI(); + + /* Exit the interrupt */ + KiEoiHelper(TrapFrame); } #ifndef _M_AMD64 @@ -480,10 +534,13 @@ FASTCALL HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame) { KIRQL OldIrql = ApicGetCurrentIrql(); -__debugbreak(); + ASSERT(OldIrql < DISPATCH_LEVEL); ASSERT(ApicGetProcessorIrql() == DISPATCH_LEVEL); + /* Enter trap */ + KiEnterInterruptTrap(TrapFrame); + ApicSetCurrentIrql(DISPATCH_LEVEL); /* Enable interrupts and call the kernel's DPC interrupt handler */ @@ -493,13 +550,20 @@ __debugbreak(); ApicSetCurrentIrql(OldIrql); - ApicWrite(APIC_EOI, 0); + ApicSendEOI(); /* Exit the interrupt */ KiEoiHelper(TrapFrame); } #endif +VOID +NTAPI +HalpSendEOI(VOID) +{ + ApicSendEOI(); +} + /* PUBLIC FUNCTIONS ***********************************************************/ VOID @@ -580,14 +644,6 @@ HalDisableSystemInterrupt( IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0); } -VOID -NTAPI -HalpSendEOI(VOID) -{ - /* Write 0 to the EndOfInterruptRegister */ - ApicWrite(APIC_EOI, 0); -} - #ifndef _M_AMD64 BOOLEAN NTAPI @@ -609,19 +665,14 @@ HalBeginSystemInterrupt( return TRUE; } -void HackEoi(void); - VOID NTAPI HalEndSystemInterrupt( IN KIRQL OldIrql, IN PKTRAP_FRAME TrapFrame) { - /* Write 0 to the EndOfInterruptRegister */ - //ApicWrite(APIC_EOI, 0); - - // HACK! - HackEoi(); + /* Send an EOI */ + ApicSendEOI(); /* Restore the old IRQL */ ApicSetCurrentIrql(OldIrql); diff --git a/reactos/hal/halx86/apic/halinit_apic.c b/reactos/hal/halx86/apic/halinit_apic.c index 4f8caff8011..c432232e969 100644 --- a/reactos/hal/halx86/apic/halinit_apic.c +++ b/reactos/hal/halx86/apic/halinit_apic.c @@ -4,9 +4,7 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/hal/x86/halinit.c * PURPOSE: Initalize the x86 hal - * PROGRAMMER: David Welch (welch@cwcom.net) - * UPDATE HISTORY: - * 11/06/98: Created + * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) */ /* INCLUDES *****************************************************************/ @@ -14,12 +12,17 @@ #include #define NDEBUG #include +#include "apic.h" VOID NTAPI ApicInitializeLocalApic(ULONG Cpu); -/* FUNCTIONS ***************************************************************/ +/* GLOBALS ******************************************************************/ + +const USHORT HalpBuildType = HAL_BUILD_TYPE; + +/* FUNCTIONS ****************************************************************/ VOID NTAPI @@ -39,6 +42,13 @@ VOID HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { + /* Enable clock interrupt handler */ + HalpEnableInterruptHandler(IDT_INTERNAL, + 0, + APIC_CLOCK_VECTOR, + CLOCK2_LEVEL, + HalpClockInterrupt, + Latched); } VOID