https://git.reactos.org/?p=reactos.git;a=commitdiff;h=64e52088d1dd73f3540c6f644f63a54e2ded76ca

commit 64e52088d1dd73f3540c6f644f63a54e2ded76ca
Author:     Timo Kreuzer <[email protected]>
AuthorDate: Sat Jun 5 15:41:49 2021 +0200
Commit:     Timo Kreuzer <[email protected]>
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 ([email protected])
- * REFERENCES:      http://www.joseflores.com/docs/ExploringIrql.html
+ * REFERENCES:      
https://web.archive.org/web/20190407074221/http://www.joseflores.com/docs/ExploringIrql.html
  *                  
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

Reply via email to