[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 *****************************************************************/
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)
{
}

View file

@ -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;
}

View file

@ -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

View file

@ -16,9 +16,11 @@
#include <debug.h>
#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);

View file

@ -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 <hal.h>
#define NDEBUG
#include <debug.h>
#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