[HAL:APIC] Code fixes

* Fix some broken code
* Add some ASSERTs
* Use ApicWriteIORedirectionEntry where appropriate
* Use KeQueryInterruptHandler/KeRegisterInterruptHandler to save/restore the old handler instead of saving the KIDTENTRY
* Move HalpProfileInterruptHandler to apictimer.c and implement it
* Use READ/WRITE_REGISTER macros
* Add some symbolic names
This commit is contained in:
Timo Kreuzer 2021-06-05 15:39:22 +02:00
parent ee514e954b
commit b7a149fcec
5 changed files with 40 additions and 32 deletions

View file

@ -94,8 +94,9 @@ ULONG
IOApicRead(UCHAR Register) IOApicRead(UCHAR Register)
{ {
/* Select the register, then do the read */ /* Select the register, then do the read */
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register; ASSERT(Register <= 0x3F);
return *(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN); WRITE_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOREGSEL), Register);
return READ_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOWIN));
} }
FORCEINLINE FORCEINLINE
@ -103,8 +104,9 @@ VOID
IOApicWrite(UCHAR Register, ULONG Value) IOApicWrite(UCHAR Register, ULONG Value)
{ {
/* Select the register, then do the write */ /* Select the register, then do the write */
*(volatile UCHAR *)(IOAPIC_BASE + IOAPIC_IOREGSEL) = Register; ASSERT(Register <= 0x3F);
*(volatile ULONG *)(IOAPIC_BASE + IOAPIC_IOWIN) = Value; WRITE_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOREGSEL), Register);
WRITE_REGISTER_ULONG((PULONG)(IOAPIC_BASE + IOAPIC_IOWIN), Value);
} }
FORCEINLINE FORCEINLINE
@ -113,6 +115,7 @@ ApicWriteIORedirectionEntry(
UCHAR Index, UCHAR Index,
IOAPIC_REDIRECTION_REGISTER ReDirReg) IOAPIC_REDIRECTION_REGISTER ReDirReg)
{ {
ASSERT(Index < APIC_MAX_IRQ);
IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0); IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1); IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
} }
@ -124,6 +127,7 @@ ApicReadIORedirectionEntry(
{ {
IOAPIC_REDIRECTION_REGISTER ReDirReg; IOAPIC_REDIRECTION_REGISTER ReDirReg;
ASSERT(Index < APIC_MAX_IRQ);
ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index); ReDirReg.Long0 = IOApicRead(IOAPIC_REDTBL + 2 * Index);
ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1); ReDirReg.Long1 = IOApicRead(IOAPIC_REDTBL + 2 * Index + 1);
@ -344,7 +348,7 @@ HalpAllocateSystemInterrupt(
Vector = IrqlToTpr(Irql) & 0xF0; Vector = IrqlToTpr(Irql) & 0xF0;
/* Find an empty vector */ /* Find an empty vector */
while (HalpVectorToIndex[Vector] != 0xFF) while (HalpVectorToIndex[Vector] != APIC_FREE_VECTOR)
{ {
Vector++; Vector++;
@ -372,8 +376,7 @@ HalpAllocateSystemInterrupt(
ReDirReg.Destination = 0; ReDirReg.Destination = 0;
/* Initialize entry */ /* Initialize entry */
IOApicWrite(IOAPIC_REDTBL + 2 * Irq, ReDirReg.Long0); ApicWriteIORedirectionEntry(Irq, ReDirReg);
IOApicWrite(IOAPIC_REDTBL + 2 * Irq + 1, ReDirReg.Long1);
return Vector; return Vector;
} }
@ -410,17 +413,16 @@ ApicInitializeIOApic(VOID)
ReDirReg.Destination = 0; ReDirReg.Destination = 0;
/* Loop all table entries */ /* Loop all table entries */
for (Index = 0; Index < 24; Index++) for (Index = 0; Index < APIC_MAX_IRQ; Index++)
{ {
/* Initialize entry */ /* Initialize entry */
IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0); ApicWriteIORedirectionEntry(Index, ReDirReg);
IOApicWrite(IOAPIC_REDTBL + 2 * Index + 1, ReDirReg.Long1);
} }
/* Init the vactor to index table */ /* Init the vactor to index table */
for (Vector = 0; Vector <= 255; Vector++) for (Vector = 0; Vector <= 255; Vector++)
{ {
HalpVectorToIndex[Vector] = 0xFF; HalpVectorToIndex[Vector] = APIC_FREE_VECTOR;
} }
// HACK: Allocate all IRQs, should rather do that on demand // HACK: Allocate all IRQs, should rather do that on demand
@ -437,7 +439,7 @@ ApicInitializeIOApic(VOID)
ReDirReg.TriggerMode = APIC_TGM_Edge; ReDirReg.TriggerMode = APIC_TGM_Edge;
ReDirReg.Mask = 0; ReDirReg.Mask = 0;
ReDirReg.Destination = ApicRead(APIC_ID); ReDirReg.Destination = ApicRead(APIC_ID);
IOApicWrite(IOAPIC_REDTBL + 2 * APIC_CLOCK_INDEX, ReDirReg.Long0); ApicWriteIORedirectionEntry(APIC_CLOCK_INDEX, ReDirReg);
} }
VOID VOID
@ -457,9 +459,10 @@ HalpInitializePICs(IN BOOLEAN EnableInterrupts)
ApicInitializeIOApic(); ApicInitializeIOApic();
/* Manually reserve some vectors */ /* Manually reserve some vectors */
HalpVectorToIndex[APC_VECTOR] = APIC_RESERVED_VECTOR;
HalpVectorToIndex[DISPATCH_VECTOR] = APIC_RESERVED_VECTOR;
HalpVectorToIndex[APIC_CLOCK_VECTOR] = 8; HalpVectorToIndex[APIC_CLOCK_VECTOR] = 8;
HalpVectorToIndex[APC_VECTOR] = 99; HalpVectorToIndex[APIC_SPURIOUS_VECTOR] = APIC_RESERVED_VECTOR;
HalpVectorToIndex[DISPATCH_VECTOR] = 99;
/* Set interrupt handlers in the IDT */ /* Set interrupt handlers in the IDT */
KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt); KeRegisterInterruptHandler(APIC_CLOCK_VECTOR, HalpClockInterrupt);
@ -669,7 +672,7 @@ HalDisableSystemInterrupt(
ReDirReg.Mask = 1; ReDirReg.Mask = 1;
/* Write back lower dword */ /* Write back lower dword */
IOApicWrite(IOAPIC_REDTBL + 2 * Irql, ReDirReg.Long0); IOApicWrite(IOAPIC_REDTBL + 2 * Index, ReDirReg.Long0);
} }
#ifndef _M_AMD64 #ifndef _M_AMD64
@ -704,8 +707,8 @@ HalBeginSystemInterrupt(
/* Get the irq for this vector */ /* Get the irq for this vector */
Index = HalpVectorToIndex[Vector]; Index = HalpVectorToIndex[Vector];
/* Check if its valid */ /* Check if it's valid */
if (Index != 0xff) if (Index < APIC_MAX_IRQ)
{ {
/* Read the I/O redirection entry */ /* Read the I/O redirection entry */
RedirReg = ApicReadIORedirectionEntry(Index); RedirReg = ApicReadIORedirectionEntry(Index);
@ -715,6 +718,9 @@ HalBeginSystemInterrupt(
} }
else else
{ {
/* This should be a reserved vector! */
ASSERT(Index == APIC_RESERVED_VECTOR);
/* Re-request the interrupt to be handled later */ /* Re-request the interrupt to be handled later */
ApicRequestInterrupt(Vector, APIC_TGM_Edge); ApicRequestInterrupt(Vector, APIC_TGM_Edge);
} }

View file

@ -25,6 +25,10 @@
#define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4]) #define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4])
#endif #endif
#define APIC_MAX_IRQ 24
#define APIC_FREE_VECTOR 0xFF
#define APIC_RESERVED_VECTOR 0xFE
/* The IMCR is supported by two read/writable or write-only I/O ports, /* The IMCR is supported by two read/writable or write-only I/O ports,
22h and 23h, which receive address and data respectively. 22h and 23h, which receive address and data respectively.
To access the IMCR, write a value of 70h to I/O port 22h, which selects the IMCR. To access the IMCR, write a value of 70h to I/O port 22h, which selects the IMCR.
@ -284,14 +288,14 @@ FORCEINLINE
ULONG ULONG
ApicRead(ULONG Offset) ApicRead(ULONG Offset)
{ {
return *(volatile ULONG *)(APIC_BASE + Offset); return READ_REGISTER_ULONG((PULONG)(APIC_BASE + Offset));
} }
FORCEINLINE FORCEINLINE
VOID VOID
ApicWrite(ULONG Offset, ULONG Value) ApicWrite(ULONG Offset, ULONG Value)
{ {
*(volatile ULONG *)(APIC_BASE + Offset) = Value; WRITE_REGISTER_ULONG((PULONG)(APIC_BASE + Offset), Value);
} }
VOID VOID

View file

@ -61,6 +61,13 @@ ApicInitializeTimer(ULONG Cpu)
// KeSetTimeIncrement // KeSetTimeIncrement
} }
VOID
FASTCALL
HalpProfileInterruptHandler(_In_ PKTRAP_FRAME TrapFrame)
{
KeProfileInterruptWithSource(TrapFrame, ProfileTime);
}
/* PUBLIC FUNCTIONS ***********************************************************/ /* PUBLIC FUNCTIONS ***********************************************************/

View file

@ -167,13 +167,6 @@ HalpClockInterruptHandler(IN PKTRAP_FRAME TrapFrame)
KeUpdateSystemTime(TrapFrame, LastIncrement, Irql); KeUpdateSystemTime(TrapFrame, LastIncrement, Irql);
} }
VOID
FASTCALL
HalpProfileInterruptHandler(IN PKTRAP_FRAME TrapFrame)
{
__debugbreak();
}
ULONG ULONG
NTAPI NTAPI
HalSetTimeIncrement(IN ULONG Increment) HalSetTimeIncrement(IN ULONG Increment)

View file

@ -55,8 +55,7 @@ NTAPI
HalpInitializeTsc(VOID) HalpInitializeTsc(VOID)
{ {
ULONG_PTR Flags; ULONG_PTR Flags;
KIDTENTRY OldIdtEntry, *IdtPointer; PVOID PreviousHandler;
PKPCR Pcr = KeGetPcr();
UCHAR RegisterA, RegisterB; UCHAR RegisterA, RegisterB;
/* Check if the CPU supports RDTSC */ /* Check if the CPU supports RDTSC */
@ -79,8 +78,7 @@ HalpInitializeTsc(VOID)
HalpWriteCmos(RTC_REGISTER_A, RegisterA); HalpWriteCmos(RTC_REGISTER_A, RegisterA);
/* Save old IDT entry */ /* Save old IDT entry */
IdtPointer = KiGetIdtEntry(Pcr, HalpRtcClockVector); PreviousHandler = KeQueryInterruptHandler(HalpRtcClockVector);
OldIdtEntry = *IdtPointer;
/* Set the calibration ISR */ /* Set the calibration ISR */
KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR); KeRegisterInterruptHandler(HalpRtcClockVector, TscCalibrationISR);
@ -105,8 +103,8 @@ HalpInitializeTsc(VOID)
/* Disable the timer interrupt */ /* Disable the timer interrupt */
HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL); HalDisableSystemInterrupt(HalpRtcClockVector, CLOCK_LEVEL);
/* Restore old IDT entry */ /* Restore the previous handler */
*IdtPointer = OldIdtEntry; KeRegisterInterruptHandler(HalpRtcClockVector, PreviousHandler);
/* Calculate an average, using simplified linear regression */ /* Calculate an average, using simplified linear regression */
HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1, HalpCpuClockFrequency.QuadPart = DoLinearRegression(NUM_SAMPLES - 1,