https://git.reactos.org/?p=reactos.git;a=commitdiff;h=64e52088d1dd73f3540c6…
commit 64e52088d1dd73f3540c6f644f63a54e2ded76ca
Author: Timo Kreuzer <timo.kreuzer(a)reactos.org>
AuthorDate: Sat Jun 5 15:41:49 2021 +0200
Commit: Timo Kreuzer <timo.kreuzer(a)reactos.org>
CommitDate: Thu Jun 17 23:27:44 2021 +0200
[HAL:APIC] Fix interrupt assignment
This is probably not how it is supposed to work, but the results are somewhat similar
to what Windows has.
---
hal/halx86/acpi/busemul.c | 23 ++--------
hal/halx86/apic/apic.c | 100 ++++++++++++++++++++++++++++-------------
hal/halx86/apic/apicp.h | 44 ++++++++++++------
hal/halx86/include/bus.h | 12 +++--
hal/halx86/legacy/bus/sysbus.c | 29 ------------
hal/halx86/pic/pic.c | 29 ++++++++++++
6 files changed, 139 insertions(+), 98 deletions(-)
diff --git a/hal/halx86/acpi/busemul.c b/hal/halx86/acpi/busemul.c
index e26600a984b..eb45c450e36 100644
--- a/hal/halx86/acpi/busemul.c
+++ b/hal/halx86/acpi/busemul.c
@@ -85,20 +85,6 @@ HalpTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
return TRUE;
}
-ULONG
-NTAPI
-HalpGetSystemInterruptVector_Acpi(IN ULONG BusNumber,
- IN ULONG BusInterruptLevel,
- IN ULONG BusInterruptVector,
- OUT PKIRQL Irql,
- OUT PKAFFINITY Affinity)
-{
- UCHAR Vector = IRQ2VECTOR((UCHAR)BusInterruptLevel);
- *Irql = VECTOR2IRQL(Vector);
- *Affinity = 0xFFFFFFFF;
- return Vector;
-}
-
BOOLEAN
NTAPI
HalpFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
@@ -254,11 +240,10 @@ HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
OUT PKAFFINITY Affinity)
{
/* Call the system bus translator */
- return HalpGetSystemInterruptVector_Acpi(BusNumber,
- BusInterruptLevel,
- BusInterruptVector,
- Irql,
- Affinity);
+ return HalpGetRootInterruptVector(BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity);
}
/*
diff --git a/hal/halx86/apic/apic.c b/hal/halx86/apic/apic.c
index 25bd4e4b4c3..eae012d61b2 100644
--- a/hal/halx86/apic/apic.c
+++ b/hal/halx86/apic/apic.c
@@ -4,9 +4,11 @@
* FILE: hal/halx86/apic/apic.c
* PURPOSE: HAL APIC Management and Control Code
* PROGRAMMERS: Timo Kreuzer (timo.kreuzer(a)reactos.org)
- * REFERENCES:
http://www.joseflores.com/docs/ExploringIrql.html
+ * REFERENCES:
https://web.archive.org/web/20190407074221/http://www.joseflores.com/docs/E…
*
http://www.codeproject.com/KB/system/soviet_kernel_hack.aspx
*
http://bbs.unixmap.net/thread-2022-1-1.html
+ *
https://www.codemachine.com/article_interruptdispatching.html
+ *
https://www.osronline.com/article.cfm%5Earticle=211.htm
*/
/* INCLUDES *******************************************************************/
@@ -17,7 +19,7 @@
#include <debug.h>
#ifndef _M_AMD64
-//#define APIC_LAZY_IRQL //FIXME: Disabled due to bug.
+#define APIC_LAZY_IRQL
#endif
/* GLOBALS ********************************************************************/
@@ -329,30 +331,13 @@ ApicInitializeLocalApic(ULONG Cpu)
UCHAR
NTAPI
HalpAllocateSystemInterrupt(
- IN UCHAR Irq,
- IN KIRQL Irql)
+ _In_ UCHAR Irq,
+ _In_ UCHAR Vector)
{
IOAPIC_REDIRECTION_REGISTER ReDirReg;
- IN UCHAR Vector;
-
- /* Start with lowest vector */
- Vector = IrqlToTpr(Irql) & 0xF0;
- /* Find an empty vector */
- while (HalpVectorToIndex[Vector] != APIC_FREE_VECTOR)
- {
- Vector++;
-
- /* Check if we went over the edge */
- if (TprToIrql(Vector) > Irql)
- {
- /* Nothing free, return failure */
- return 0;
- }
- }
-
- /* Save irq in the table */
- HalpVectorToIndex[Vector] = Irq;
+ ASSERT(Irq < 24);
+ ASSERT(HalpVectorToIndex[Vector] == APIC_FREE_VECTOR);
/* Setup a redirection entry */
ReDirReg.Vector = Vector;
@@ -369,6 +354,68 @@ HalpAllocateSystemInterrupt(
/* Initialize entry */
ApicWriteIORedirectionEntry(Irq, ReDirReg);
+ /* Save irq in the table */
+ HalpVectorToIndex[Vector] = Irq;
+
+ return Vector;
+}
+
+ULONG
+NTAPI
+HalpGetRootInterruptVector(
+ _In_ ULONG BusInterruptLevel,
+ _In_ ULONG BusInterruptVector,
+ _Out_ PKIRQL OutIrql,
+ _Out_ PKAFFINITY OutAffinity)
+{
+ UCHAR Vector;
+ KIRQL Irql;
+
+ /* Get the vector currently registered */
+ Vector = HalpIrqToVector(BusInterruptLevel);
+
+ /* Check if it's used */
+ if (Vector != 0xFF)
+ {
+ /* Calculate IRQL */
+ NT_ASSERT(HalpVectorToIndex[Vector] == BusInterruptLevel);
+ *OutIrql = HalpVectorToIrql(Vector);
+ }
+ else
+ {
+ ULONG Offset;
+
+ /* Outer loop to find alternative slots, when all IRQLs are in use */
+ for (Offset = 0; Offset < 15; Offset++)
+ {
+ /* Loop allowed IRQL range */
+ for (Irql = CLOCK_LEVEL - 1; Irql >= CMCI_LEVEL; Irql--)
+ {
+ /* Calculate the vactor */
+ Vector = IrqlToTpr(Irql) + Offset;
+
+ /* Check if the vector is free */
+ if (HalpVectorToIrq(Vector) == APIC_FREE_VECTOR)
+ {
+ /* Found one, allocate the interrupt */
+ Vector = HalpAllocateSystemInterrupt(BusInterruptLevel, Vector);
+ *OutIrql = Irql;
+ goto Exit;
+ }
+ }
+ }
+
+ DPRINT1("Failed to get an interrupt vector for IRQ %lu\n",
BusInterruptLevel);
+ *OutAffinity = 0;
+ *OutIrql = 0;
+ return 0;
+ }
+
+Exit:
+
+ *OutAffinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+
return Vector;
}
@@ -416,13 +463,6 @@ ApicInitializeIOApic(VOID)
HalpVectorToIndex[Vector] = APIC_FREE_VECTOR;
}
- // HACK: Allocate all IRQs, should rather do that on demand
- for (Index = 0; Index <= 15; Index++)
- {
- /* Map the IRQs to IRQLs like with the PIC */
- HalpAllocateSystemInterrupt(Index, 27 - Index);
- }
-
/* Enable the timer interrupt */
ReDirReg.Vector = APIC_CLOCK_VECTOR;
ReDirReg.DeliveryMode = APIC_MT_Fixed;
diff --git a/hal/halx86/apic/apicp.h b/hal/halx86/apic/apicp.h
index d3e1ece84aa..bd06a3a0cf6 100644
--- a/hal/halx86/apic/apicp.h
+++ b/hal/halx86/apic/apicp.h
@@ -11,7 +11,23 @@
#ifdef _M_AMD64
#define LOCAL_APIC_BASE 0xFFFFFFFFFFFE0000ULL
#define IOAPIC_BASE 0xFFFFFFFFFFFE1000ULL
- #define APIC_SPURIOUS_VECTOR 0x3f
+
+ /* Vectors */
+ #define APC_VECTOR 0x1F // IRQL 01 (APC_LEVEL) - KiApcInterrupt
+ #define DISPATCH_VECTOR 0x2F // IRQL 02 (DISPATCH_LEVEL) - KiDpcInterrupt
+ #define CMCI_VECTOR 0x35 // IRQL 05 (CMCI_LEVEL) - HalpInterruptCmciService
+ #define APIC_CLOCK_VECTOR 0xD1 // IRQL 13 (CLOCK_LEVEL), IRQ 8 -
HalpTimerClockInterrupt
+ #define CLOCK_IPI_VECTOR 0xD2 // IRQL 13 (CLOCK_LEVEL) -
HalpTimerClockIpiRoutine
+ #define REBOOT_VECTOR 0xD7 // IRQL 15 (PROFILE_LEVEL) -
HalpInterruptRebootService
+ #define STUB_VECTOR 0xD8 // IRQL 15 (PROFILE_LEVEL) -
HalpInterruptStubService
+ #define APIC_SPURIOUS_VECTOR 0xDF // IRQL 13 (CLOCK_LEVEL) -
HalpInterruptSpuriousService
+ #define APIC_IPI_VECTOR 0xE1 // IRQL 14 (IPI_LEVEL) - KiIpiInterrupt
+ #define APIC_ERROR_VECTOR 0xE2 // IRQL 14 (IPI_LEVEL) -
HalpInterruptLocalErrorService
+ #define POWERFAIL_VECTOR 0xE3 // IRQL 14 (POWER_LEVEL) :
HalpInterruptDeferredRecoveryService
+ #define APIC_PROFILE_VECTOR 0xFD // IRQL 15 (PROFILE_LEVEL) -
HalpTimerProfileInterrupt
+ #define APIC_PERF_VECTOR 0xFE // IRQL 15 (PROFILE_LEVEL) - HalpPerfInterrupt
+ #define APIC_NMI_VECTOR 0xFF
+
#define IrqlToTpr(Irql) (Irql << 4)
#define IrqlToSoftVector(Irql) ((Irql << 4)|0xf)
#define TprToIrql(Tpr) ((KIRQL)(Tpr >> 4))
@@ -19,7 +35,21 @@
#else
#define LOCAL_APIC_BASE 0xFFFE0000
#define IOAPIC_BASE 0xFFFE1000
+
+ /* Vectors */
#define APIC_SPURIOUS_VECTOR 0x1f
+ #define APC_VECTOR 0x3D // IRQL 01
+ #define DISPATCH_VECTOR 0x41 // IRQL 02
+ #define APIC_GENERIC_VECTOR 0xC1 // IRQL 27
+ #define APIC_CLOCK_VECTOR 0xD1 // IRQL 28
+ #define APIC_SYNCH_VECTOR 0xD1 // IRQL 28
+ #define APIC_IPI_VECTOR 0xE1 // IRQL 29
+ #define APIC_ERROR_VECTOR 0xE3
+ #define POWERFAIL_VECTOR 0xEF // IRQL 30
+ #define APIC_PROFILE_VECTOR 0xFD // IRQL 31
+ #define APIC_PERF_VECTOR 0xFE
+ #define APIC_NMI_VECTOR 0xFF
+
#define IrqlToTpr(Irql) (HalpIRQLtoTPR[Irql])
#define IrqlToSoftVector(Irql) IrqlToTpr(Irql)
#define TprToIrql(Tpr) (HalVectorToIRQL[Tpr >> 4])
@@ -42,18 +72,6 @@
#define IMCR_PIC_DIRECT 0x00
#define IMCR_PIC_VIA_APIC 0x01
-#define ZERO_VECTOR 0x00 // IRQL 00
-#define APC_VECTOR 0x3D // IRQL 01
-#define DISPATCH_VECTOR 0x41 // IRQL 02
-#define APIC_GENERIC_VECTOR 0xC1 // IRQL 27
-#define APIC_CLOCK_VECTOR 0xD1 // IRQL 28
-#define APIC_SYNCH_VECTOR 0xD1 // IRQL 28
-#define APIC_IPI_VECTOR 0xE1 // IRQL 29
-#define APIC_ERROR_VECTOR 0xE3
-#define POWERFAIL_VECTOR 0xEF // IRQL 30
-#define APIC_PROFILE_VECTOR 0xFD // IRQL 31
-#define APIC_PERF_VECTOR 0xFE
-#define APIC_NMI_VECTOR 0xFF
/* APIC Register Address Map */
#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */
diff --git a/hal/halx86/include/bus.h b/hal/halx86/include/bus.h
index 443d649fc9c..75a106a4328 100644
--- a/hal/halx86/include/bus.h
+++ b/hal/halx86/include/bus.h
@@ -400,13 +400,11 @@ HalpAssignPCISlotResources(
ULONG
NTAPI
-HalpGetSystemInterruptVector_Acpi(
- ULONG BusNumber,
- ULONG BusInterruptLevel,
- ULONG BusInterruptVector,
- PKIRQL Irql,
- PKAFFINITY Affinity
-);
+HalpGetRootInterruptVector(
+ _In_ ULONG BusInterruptLevel,
+ _In_ ULONG BusInterruptVector,
+ _Out_ PKIRQL Irql,
+ _Out_ PKAFFINITY Affinity);
ULONG
NTAPI
diff --git a/hal/halx86/legacy/bus/sysbus.c b/hal/halx86/legacy/bus/sysbus.c
index baaecee51e8..56d286c3464 100644
--- a/hal/halx86/legacy/bus/sysbus.c
+++ b/hal/halx86/legacy/bus/sysbus.c
@@ -110,35 +110,6 @@ HalpTranslateSystemBusAddress(IN PBUS_HANDLER BusHandler,
return FALSE;
}
-ULONG
-NTAPI
-HalpGetRootInterruptVector(IN ULONG BusInterruptLevel,
- IN ULONG BusInterruptVector,
- OUT PKIRQL Irql,
- OUT PKAFFINITY Affinity)
-{
- UCHAR SystemVector;
-
- /* Validate the IRQ */
- if (BusInterruptLevel > 23)
- {
- /* Invalid vector */
- DPRINT1("IRQ %lx is too high!\n", BusInterruptLevel);
- return 0;
- }
-
- /* Get the system vector */
- SystemVector = HalpIrqToVector((UCHAR)BusInterruptLevel);
-
- /* Return the IRQL and affinity */
- *Irql = HalpVectorToIrql(SystemVector);
- *Affinity = HalpDefaultInterruptAffinity;
- ASSERT(HalpDefaultInterruptAffinity);
-
- /* Return the vector */
- return SystemVector;
-}
-
ULONG
NTAPI
HalpGetSystemInterruptVector(IN PBUS_HANDLER BusHandler,
diff --git a/hal/halx86/pic/pic.c b/hal/halx86/pic/pic.c
index f46a72bc80f..e0b46ce7056 100644
--- a/hal/halx86/pic/pic.c
+++ b/hal/halx86/pic/pic.c
@@ -1233,6 +1233,35 @@ HalpDispatchInterrupt2(VOID)
return NULL;
}
+ULONG
+NTAPI
+HalpGetRootInterruptVector(IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity)
+{
+ UCHAR SystemVector;
+
+ /* Validate the IRQ */
+ if (BusInterruptLevel > 23)
+ {
+ /* Invalid vector */
+ DPRINT1("IRQ %lx is too high!\n", BusInterruptLevel);
+ return 0;
+ }
+
+ /* Get the system vector */
+ SystemVector = HalpIrqToVector((UCHAR)BusInterruptLevel);
+
+ /* Return the IRQL and affinity */
+ *Irql = HalpVectorToIrql(SystemVector);
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+
+ /* Return the vector */
+ return SystemVector;
+}
+
#else /* _MINIHAL_ */
KIRQL