- Fix I/O APIC register access
- set APIC logical id based on Cpu (currently flat model with up to 8 cpus supported)
- In HalpInitializeTsc, setup the RTC clock, since the timer is initialized later
- in the TSC calibration ISR, send EOI and read RTC register C to get the next interrupt

svn path=/trunk/; revision=53634
This commit is contained in:
Timo Kreuzer
2011-09-08 08:15:39 +00:00
parent 7635cc18b1
commit c508185cd9
5 changed files with 67 additions and 17 deletions
+22 -4
View File
@@ -88,7 +88,7 @@ FORCEINLINE
IOApicRead(UCHAR Register)
{
/* Select the register, then do the read */
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
return *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN);
}
@@ -97,7 +97,7 @@ FORCEINLINE
IOApicWrite(UCHAR Register, ULONG Value)
{
/* Select the register, then do the write */
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register;
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value;
}
@@ -241,6 +241,12 @@ ApicInitializeLocalApic(ULONG Cpu)
SpIntRegister.FocusCPUCoreChecking = 0;
ApicWrite(APIC_SIVR, SpIntRegister.Long);
/* Set the mode to flat (max 8 CPUs supported!) */
ApicWrite(APIC_DFR, APIC_DF_Flat);
/* Set logical apic ID */
ApicWrite(APIC_LDR, ApicLogicalId(Cpu) << 24);
/* Set the spurious ISR */
KeRegisterInterruptHandler(APIC_SPURIOUS_VECTOR, ApicSpuriousService);
@@ -409,9 +415,11 @@ ApicInitializeIOApic(VOID)
/* Enable the timer interrupt */
ReDirReg.Vector = APIC_CLOCK_VECTOR;
ReDirReg.DestinationMode = APIC_DM_Logical;
ReDirReg.DeliveryMode = APIC_MT_Fixed;
ReDirReg.DestinationMode = APIC_DM_Physical;
ReDirReg.TriggerMode = APIC_TGM_Edge;
ReDirReg.Mask = 0;
ReDirReg.Destination = ApicRead(APIC_ID);
IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0);
}
@@ -519,6 +527,7 @@ HalEnableSystemInterrupt(
IN KINTERRUPT_MODE InterruptMode)
{
IOAPIC_REDIRECTION_REGISTER ReDirReg;
PKPRCB Prcb = KeGetCurrentPrcb();
UCHAR Index;
ASSERT(Irql <= HIGH_LEVEL);
ASSERT((IrqlToTpr(Irql) & 0xF0) == (Vector & 0xF0));
@@ -531,6 +540,7 @@ HalEnableSystemInterrupt(
ReDirReg.Vector = Vector;
ReDirReg.DeliveryMode = APIC_MT_LowestPriority;
ReDirReg.DestinationMode = APIC_DM_Logical;
ReDirReg.Destination |= ApicLogicalId(Prcb->Number);
ReDirReg.TriggerMode = 1 - InterruptMode;
ReDirReg.Mask = FALSE;
@@ -562,6 +572,14 @@ 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
@@ -592,7 +610,7 @@ HalEndSystemInterrupt(
/* Restore the old IRQL */
ApicSetCurrentIrql(OldIrql);
/* Write 0 to the EndOfInterruptRegister for level triggered ints */
/* Write 0 to the EndOfInterruptRegister */
ApicWrite(APIC_EOI, 0);
}
+8 -1
View File
@@ -39,6 +39,7 @@
#define IOAPIC_PHYS_BASE 0xFEC00000
#define APIC_CLOCK_INDEX 8
#define ApicLogicalId(Cpu) ((UCHAR)(1<< Cpu))
/* APIC Register Address Map */
#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */
@@ -106,6 +107,12 @@ enum
APIC_DSH_AllExclusingSelf
};
enum
{
APIC_DF_Flat = 0xFFFFFFFF,
APIC_DF_Cluster = 0x0FFFFFFF
};
enum
{
TIMER_DV_DivideBy2 = 0,
@@ -224,7 +231,7 @@ enum
IOAPIC_ID = 0x00,
IOAPIC_VER = 0x01,
IOAPIC_ARB = 0x02,
IOAPIC_REDTBL = 0x28
IOAPIC_REDTBL = 0x10
};
typedef union _IOAPIC_REDIRECTION_REGISTER
+3 -2
View File
@@ -83,7 +83,9 @@ HalpInitializeClock(VOID)
/* Release CMOS lock */
HalpReleaseCmosSpinLock();
// RtcSetClockRate(HalpCurrentRate);
RtcSetClockRate(HalpCurrentRate);
DPRINT1("Clock initialized\n");
}
VOID
@@ -95,7 +97,6 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
/* Enter trap */
KiEnterInterruptTrap(TrapFrame);
__debugbreak();
/* Start the interrupt */
if (HalBeginSystemInterrupt(CLOCK_LEVEL, PRIMARY_VECTOR_BASE, &Irql))
+19 -8
View File
@@ -18,7 +18,7 @@ LARGE_INTEGER HalpCpuClockFrequency = {INITIAL_STALL_COUNT * 1000000};
UCHAR TscCalibrationPhase;
LARGE_INTEGER TscCalibrationArray[NUM_SAMPLES];
extern const UCHAR HalpClockVector;
UCHAR HalpRtcClockVector = 0xD1;
/* PRIVATE FUNCTIONS *********************************************************/
@@ -29,6 +29,7 @@ HalpInitializeTsc()
ULONG_PTR Flags;
KIDTENTRY OldIdtEntry, *IdtPointer;
PKPCR Pcr = KeGetPcr();
UCHAR RegisterA, RegisterB;
/* Check if the CPU supports RDTSC */
if (!(KeGetCurrentPrcb()->FeatureBits & KF_RDTSC))
@@ -40,31 +41,41 @@ HalpInitializeTsc()
Flags = __readeflags();
_disable();
__debugbreak();
/* Enable the periodic interrupt in the CMOS */
RegisterB = HalpReadCmos(RTC_REGISTER_B);
HalpWriteCmos(RTC_REGISTER_B, RegisterB | RTC_REG_B_PI);
/* Initialze the PIT */
//HalpInitializePIT();
/* Modify register A to get 4096 Hz */
RegisterA = HalpReadCmos(RTC_REGISTER_A);
RegisterA = (RegisterA & 0xF0) | 9;
HalpWriteCmos(RTC_REGISTER_A, RegisterA);
/* Save old IDT entry */
IdtPointer = KiGetIdtEntry(Pcr, HalpClockVector);
IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector);
OldIdtEntry = *IdtPointer;
/* Set the calibration ISR */
KeRegisterInterruptHandler(HalpClockVector, TscCalibrationISR);
KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR);
/* Reset TSC value to 0 */
__writemsr(MSR_RDTSC, 0);
/* Enable the timer interupt */
HalEnableSystemInterrupt(HalpClockVector, CLOCK_LEVEL, Latched);
HalEnableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL, Latched);
/* Read register C, so that the next interrupt can happen */
HalpReadCmos(RTC_REGISTER_C);;
/* Wait for completion */
_enable();
while (TscCalibrationPhase < NUM_SAMPLES) _ReadWriteBarrier();
_disable();
/* Disable the periodic interrupt in the CMOS */
HalpWriteCmos(RTC_REGISTER_B, RegisterB & ~RTC_REG_B_PI);
/* Disable the timer interupt */
HalDisableSystemInterrupt(HalpClockVector, CLOCK_LEVEL);
HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL);
/* Restore old IDT entry */
*IdtPointer = OldIdtEntry;
+15 -2
View File
@@ -8,6 +8,7 @@
EXTERN _TscCalibrationPhase:BYTE
EXTERN _TscCalibrationArray:QWORD
EXTERN _HalpSendEOI@0:PROC
PUBLIC _TscCalibrationISR
_TscCalibrationISR:
@@ -26,13 +27,25 @@ _TscCalibrationISR:
jnb _CalibrationISR_Exit
/* Store the current value */
mov dword ptr _TscCalibrationArray[ecx * 2], eax
mov dword ptr _TscCalibrationArray[ecx * 2 + 4], edx
shl ecx, 3
mov dword ptr _TscCalibrationArray[ecx], eax
mov dword ptr _TscCalibrationArray[ecx + 4], edx
/* Advance phase */
inc byte ptr ds:[_TscCalibrationPhase]
_CalibrationISR_Exit:
/* Read CMOS register C */
mov al, HEX(0C)
out HEX(70), al
jmp $+2
in al, HEX(71)
jmp $+2
/* Send EOI */
call _HalpSendEOI@0
pop edx
pop ecx
pop eax