[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
This commit is contained in:
Timo Kreuzer 2011-09-10 15:55:15 +00:00
parent ac09e360bb
commit 459b5c212e
5 changed files with 113 additions and 204 deletions

View file

@ -20,6 +20,23 @@ BOOLEAN HalpPciLockSettings;
/* FUNCTIONS *****************************************************************/ /* 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 VOID
HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{ {
@ -32,18 +49,4 @@ HalpInitPhase1(VOID)
} }
VOID
INIT_FUNCTION
HalpInitializeClock(VOID)
{
}
VOID
HalpCalibrateStallExecution()
{
}
VOID
HalpInitializePICs(IN BOOLEAN EnableInterrupts)
{
}

View file

@ -14,99 +14,8 @@
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
LARGE_INTEGER HalpPerformanceFrequency; //LARGE_INTEGER HalpPerformanceFrequency;
/* FUNCTIONS ******************************************************************/ /* 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;
}

View file

@ -23,70 +23,6 @@ MsgUnimplemented:
.code64 .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 END

View file

@ -16,9 +16,11 @@
#include <debug.h> #include <debug.h>
#include "apic.h" #include "apic.h"
void HackEoi(void);
/* GLOBALS ********************************************************************/ /* GLOBALS ********************************************************************/
ULONG ApicVersion;
UCHAR HalpVectorToIndex[256]; UCHAR HalpVectorToIndex[256];
#ifndef _M_AMD64 #ifndef _M_AMD64
@ -101,6 +103,14 @@ IOApicWrite(UCHAR Register, ULONG Value)
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value; *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value;
} }
VOID
FORCEINLINE
ApicSendEOI(void)
{
//ApicWrite(APIC_EOI, 0);
HackEoi();
}
KIRQL KIRQL
FORCEINLINE FORCEINLINE
ApicGetProcessorIrql(VOID) ApicGetProcessorIrql(VOID)
@ -113,24 +123,27 @@ KIRQL
FORCEINLINE FORCEINLINE
ApicGetCurrentIrql(VOID) ApicGetCurrentIrql(VOID)
{ {
// HACK: This won't work with amd64, where cr8 is modified directly, but #ifdef _M_AMD64
// VBox is broken and returns a wrong value when using a vmmcall after a return (KIRQL)__readcr8();
// page table modification. #else
return KeGetPcr()->Irql; // HACK: some magic to Sync VBox's APIC registers
ApicRead(APIC_VER);
/* Read the TPR and convert it to an IRQL */ /* Read the TPR and convert it to an IRQL */
return TprToIrql(ApicRead(APIC_TPR)); return TprToIrql(ApicRead(APIC_TPR));
#endif
} }
VOID VOID
FORCEINLINE FORCEINLINE
ApicSetCurrentIrql(KIRQL Irql) ApicSetCurrentIrql(KIRQL Irql)
{ {
#ifdef _M_AMD64
__writecr8(Irql);
#else
/* Convert IRQL and write the TPR */ /* Convert IRQL and write the TPR */
ApicWrite(APIC_TPR, IrqlToTpr(Irql)); ApicWrite(APIC_TPR, IrqlToTpr(Irql));
#endif
/* HACK: Keep PCR field in sync, s.a. */
KeGetPcr()->Irql = Irql;
} }
UCHAR UCHAR
@ -150,7 +163,7 @@ KIRQL
FASTCALL FASTCALL
HalpVectorToIrql(UCHAR Vector) HalpVectorToIrql(UCHAR Vector)
{ {
return TprToIrql(Vector >> 2); return TprToIrql(Vector);
} }
UCHAR UCHAR
@ -249,6 +262,9 @@ ApicInitializeLocalApic(ULONG Cpu)
SpIntRegister.FocusCPUCoreChecking = 0; SpIntRegister.FocusCPUCoreChecking = 0;
ApicWrite(APIC_SIVR, SpIntRegister.Long); 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!) */ /* Set the mode to flat (max 8 CPUs supported!) */
ApicWrite(APIC_DFR, APIC_DF_Flat); ApicWrite(APIC_DFR, APIC_DF_Flat);
@ -430,6 +446,7 @@ ApicInitializeIOApic(VOID)
ReDirReg.Destination = ApicRead(APIC_ID); ReDirReg.Destination = ApicRead(APIC_ID);
IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0); IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0);
ApicSendEOI();
} }
VOID VOID
@ -447,15 +464,23 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
/* Initialize the I/O APIC */ /* Initialize the I/O APIC */
ApicInitializeIOApic(); 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); KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt);
#ifndef _M_AMD64 #ifndef _M_AMD64
KeRegisterInterruptHandler(APC_VECTOR, HalpApcInterrupt); KeRegisterInterruptHandler(APC_VECTOR, HalpApcInterrupt);
KeRegisterInterruptHandler(DPC_VECTOR, HalpDispatchInterrupt); KeRegisterInterruptHandler(DISPATCH_VECTOR, HalpDispatchInterrupt);
#endif #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 */ /* Restore interrupt state */
if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK; if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK;
__writeeflags(EFlags); __writeeflags(EFlags);
@ -466,11 +491,40 @@ DECLSPEC_NORETURN
FASTCALL FASTCALL
HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame)
{ {
KPROCESSOR_MODE ProcessorMode;
KIRQL OldIrql;
ASSERT(ApicGetCurrentIrql() < APC_LEVEL); ASSERT(ApicGetCurrentIrql() < APC_LEVEL);
ASSERT(ApicGetProcessorIrql() == APC_LEVEL); ASSERT(ApicGetProcessorIrql() == APC_LEVEL);
UNIMPLEMENTED; /* Enter trap */
ASSERT(FALSE); 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 #ifndef _M_AMD64
@ -480,10 +534,13 @@ FASTCALL
HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame) HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame)
{ {
KIRQL OldIrql = ApicGetCurrentIrql(); KIRQL OldIrql = ApicGetCurrentIrql();
__debugbreak();
ASSERT(OldIrql < DISPATCH_LEVEL); ASSERT(OldIrql < DISPATCH_LEVEL);
ASSERT(ApicGetProcessorIrql() == DISPATCH_LEVEL); ASSERT(ApicGetProcessorIrql() == DISPATCH_LEVEL);
/* Enter trap */
KiEnterInterruptTrap(TrapFrame);
ApicSetCurrentIrql(DISPATCH_LEVEL); ApicSetCurrentIrql(DISPATCH_LEVEL);
/* Enable interrupts and call the kernel's DPC interrupt handler */ /* Enable interrupts and call the kernel's DPC interrupt handler */
@ -493,13 +550,20 @@ __debugbreak();
ApicSetCurrentIrql(OldIrql); ApicSetCurrentIrql(OldIrql);
ApicWrite(APIC_EOI, 0); ApicSendEOI();
/* Exit the interrupt */ /* Exit the interrupt */
KiEoiHelper(TrapFrame); KiEoiHelper(TrapFrame);
} }
#endif #endif
VOID
NTAPI
HalpSendEOI(VOID)
{
ApicSendEOI();
}
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/
VOID VOID
@ -580,14 +644,6 @@ HalDisableSystemInterrupt(
IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0); IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0);
} }
VOID
NTAPI
HalpSendEOI(VOID)
{
/* Write 0 to the EndOfInterruptRegister */
ApicWrite(APIC_EOI, 0);
}
#ifndef _M_AMD64 #ifndef _M_AMD64
BOOLEAN BOOLEAN
NTAPI NTAPI
@ -609,19 +665,14 @@ HalBeginSystemInterrupt(
return TRUE; return TRUE;
} }
void HackEoi(void);
VOID VOID
NTAPI NTAPI
HalEndSystemInterrupt( HalEndSystemInterrupt(
IN KIRQL OldIrql, IN KIRQL OldIrql,
IN PKTRAP_FRAME TrapFrame) IN PKTRAP_FRAME TrapFrame)
{ {
/* Write 0 to the EndOfInterruptRegister */ /* Send an EOI */
//ApicWrite(APIC_EOI, 0); ApicSendEOI();
// HACK!
HackEoi();
/* Restore the old IRQL */ /* Restore the old IRQL */
ApicSetCurrentIrql(OldIrql); ApicSetCurrentIrql(OldIrql);

View file

@ -4,9 +4,7 @@
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/hal/x86/halinit.c * FILE: ntoskrnl/hal/x86/halinit.c
* PURPOSE: Initalize the x86 hal * PURPOSE: Initalize the x86 hal
* PROGRAMMER: David Welch (welch@cwcom.net) * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
* UPDATE HISTORY:
* 11/06/98: Created
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -14,12 +12,17 @@
#include <hal.h> #include <hal.h>
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
#include "apic.h"
VOID VOID
NTAPI NTAPI
ApicInitializeLocalApic(ULONG Cpu); ApicInitializeLocalApic(ULONG Cpu);
/* FUNCTIONS ***************************************************************/ /* GLOBALS ******************************************************************/
const USHORT HalpBuildType = HAL_BUILD_TYPE;
/* FUNCTIONS ****************************************************************/
VOID VOID
NTAPI NTAPI
@ -39,6 +42,13 @@ VOID
HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{ {
/* Enable clock interrupt handler */
HalpEnableInterruptHandler(IDT_INTERNAL,
0,
APIC_CLOCK_VECTOR,
CLOCK2_LEVEL,
HalpClockInterrupt,
Latched);
} }
VOID VOID