bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Support up to two IOAPICs with up to 32 GSIs on each


From: Damien Zammit
Subject: [PATCH] Support up to two IOAPICs with up to 32 GSIs on each
Date: Mon, 29 Jan 2024 10:06:57 +0000

Previously, only IOAPIC[0] was supported.
Now this supports up to two IOAPICs.

---
 i386/i386/apic.c              | 13 +++++
 i386/i386/apic.h              |  6 ++-
 i386/i386/locore.S            | 43 +++++++++++++++++
 i386/i386at/acpi_parse_apic.c |  3 ++
 i386/i386at/int_init.c        |  6 ++-
 i386/i386at/ioapic.c          | 89 +++++++++++++++++++++++++++++++++--
 6 files changed, 153 insertions(+), 7 deletions(-)

diff --git a/i386/i386/apic.c b/i386/i386/apic.c
index 3a51f506..0cf7c37c 100644
--- a/i386/i386/apic.c
+++ b/i386/i386/apic.c
@@ -179,6 +179,19 @@ apic_get_num_ioapics(void)
     return apic_data.nioapics;
 }
 
+/* apic_get_total_gsis: returns the total number of GSIs in the system. */
+int
+apic_get_total_gsis(void)
+{
+    int id;
+    int gsis = 0;
+
+    for (id = 0; id < apic_get_num_ioapics(); id++)
+        gsis += apic_get_ioapic(id)->ngsis;
+
+    return gsis;
+}
+
 /*
  * apic_get_current_cpu: returns the apic_id of current cpu.
  */
diff --git a/i386/i386/apic.h b/i386/i386/apic.h
index 9f908159..e410e9c6 100644
--- a/i386/i386/apic.h
+++ b/i386/i386/apic.h
@@ -193,6 +193,7 @@ typedef struct ApicLocalUnit {
 
 typedef struct IoApicData {
         uint8_t  apic_id;
+        uint8_t  ngsis;
         uint32_t addr;
         uint32_t gsi_base;
         ApicIoUnit *ioapic;
@@ -239,6 +240,7 @@ int apic_get_current_cpu(void);
 void apic_print_info(void);
 int apic_refit_cpulist(void);
 void apic_generate_cpu_id_lut(void);
+int apic_get_total_gsis(void);
 void picdisable(void);
 void lapic_eoi(void);
 void ioapic_irq_eoi(int pin);
@@ -257,6 +259,8 @@ extern int cpu_id_lut[];
 
 #define APIC_IO_UNIT_ID                        0x00
 #define APIC_IO_VERSION                        0x01
+# define APIC_IO_VERSION_SHIFT         0
+# define APIC_IO_ENTRIES_SHIFT         16
 #define APIC_IO_REDIR_LOW(int_pin)     (0x10+(int_pin)*2)
 #define APIC_IO_REDIR_HIGH(int_pin)    (0x11+(int_pin)*2)
 
@@ -283,7 +287,7 @@ extern int cpu_id_lut[];
 #define LAPIC_TIMER_BASEDIV            0x100000
 #define LAPIC_HAS_DIRECTED_EOI         0x1000000
 
-#define NINTR                          24
+#define NINTR                          64 /* Max 32 GSIs on each of two 
IOAPICs */
 #define IOAPIC_FIXED                   0
 #define IOAPIC_PHYSICAL                0
 #define IOAPIC_LOGICAL                 1
diff --git a/i386/i386/locore.S b/i386/i386/locore.S
index df41722d..378297ff 100644
--- a/i386/i386/locore.S
+++ b/i386/i386/locore.S
@@ -694,6 +694,49 @@ INTERRUPT(20)
 INTERRUPT(21)
 INTERRUPT(22)
 INTERRUPT(23)
+/* Possibly 8 more GSIs */
+INTERRUPT(24)
+INTERRUPT(25)
+INTERRUPT(26)
+INTERRUPT(27)
+INTERRUPT(28)
+INTERRUPT(29)
+INTERRUPT(30)
+INTERRUPT(31)
+/* ... APIC IOAPIC #2 */
+INTERRUPT(32)
+INTERRUPT(33)
+INTERRUPT(34)
+INTERRUPT(35)
+INTERRUPT(36)
+INTERRUPT(37)
+INTERRUPT(38)
+INTERRUPT(39)
+INTERRUPT(40)
+INTERRUPT(41)
+INTERRUPT(42)
+INTERRUPT(43)
+INTERRUPT(44)
+INTERRUPT(45)
+INTERRUPT(46)
+INTERRUPT(47)
+INTERRUPT(48)
+INTERRUPT(49)
+INTERRUPT(50)
+INTERRUPT(51)
+INTERRUPT(52)
+INTERRUPT(53)
+INTERRUPT(54)
+INTERRUPT(55)
+/* Possibly 8 more GSIs */
+INTERRUPT(56)
+INTERRUPT(57)
+INTERRUPT(58)
+INTERRUPT(59)
+INTERRUPT(60)
+INTERRUPT(61)
+INTERRUPT(62)
+INTERRUPT(63)
 #endif
 #if NCPUS > 1
 INTERRUPT(CALL_AST_CHECK)
diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c
index 9cd861ed..1aef53ed 100644
--- a/i386/i386at/acpi_parse_apic.c
+++ b/i386/i386at/acpi_parse_apic.c
@@ -331,6 +331,9 @@ acpi_apic_add_ioapic(struct acpi_apic_ioapic *ioapic_entry)
     io_apic.ioapic = (ApicIoUnit *)kmem_map_aligned_table(ioapic_entry->addr,
                                                           sizeof(ApicIoUnit),
                                                           VM_PROT_READ | 
VM_PROT_WRITE);
+    io_apic.ioapic->select.r = APIC_IO_VERSION;
+    io_apic.ngsis = ((io_apic.ioapic->window.r >> APIC_IO_ENTRIES_SHIFT) & 
0xff) + 1;
+
     /* Insert IOAPIC in the list. */
     apic_add_ioapic(io_apic);
 }
diff --git a/i386/i386at/int_init.c b/i386/i386at/int_init.c
index d55d7a48..262bef1b 100644
--- a/i386/i386at/int_init.c
+++ b/i386/i386at/int_init.c
@@ -24,6 +24,10 @@
 #include <i386at/idt.h>
 #include <i386at/int_init.h>
 #include <i386/mp_desc.h>
+#include <kern/printf.h>
+#ifdef APIC
+#include <i386/apic.h>
+#endif
 
 /* defined in locore.S */
 extern vm_offset_t int_entry_table[];
@@ -37,7 +41,7 @@ int_fill(struct real_gate *myidt)
        int nirq = 16;
 #else
        int base = IOAPIC_INT_BASE;
-       int nirq = 24;
+       int nirq = NINTR;
 #endif
 
        for (i = 0; i < nirq; i++) {
diff --git a/i386/i386at/ioapic.c b/i386/i386at/ioapic.c
index fb73eab7..270362c3 100644
--- a/i386/i386at/ioapic.c
+++ b/i386/i386at/ioapic.c
@@ -46,7 +46,13 @@ int spl_init = 0;
 def_simple_lock_irq_data(static, ioapic_lock)  /* Lock for non-atomic window 
accesses to ioapic */
 
 int iunit[NINTR] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
-                    16, 17, 18, 19, 20, 21, 22, 23};
+                    16, 17, 18, 19, 20, 21, 22, 23,
+                   24, 25, 26, 27, 28, 29, 30, 31,
+                   /* 2nd IOAPIC */
+                   32, 33, 34, 35, 36, 37, 38, 39,
+                   40, 41, 42, 43, 44, 45, 46, 47,
+                   48, 49, 50, 51, 52, 53, 54, 55,
+                   56, 57, 58, 59, 60, 61, 62, 63 };
 
 interrupt_handler_fn ivect[NINTR] = {
     /* 00 */   (interrupt_handler_fn)hardclock,
@@ -77,6 +83,49 @@ interrupt_handler_fn ivect[NINTR] = {
     /* 21 */   intnull,        /* PIRQF */
     /* 22 */   intnull,        /* PIRQG */
     /* 23 */   intnull,        /* PIRQH */
+
+    /* 24 */   intnull,
+    /* 25 */   intnull,
+    /* 26 */   intnull,
+    /* 27 */   intnull,
+    /* 28 */   intnull,
+    /* 29 */   intnull,
+    /* 30 */   intnull,
+    /* 31 */   intnull,
+
+    /* 32 */   intnull,
+    /* 33 */   intnull,
+    /* 34 */   intnull,
+    /* 35 */   intnull,
+    /* 36 */   intnull,
+    /* 37 */   intnull,
+    /* 38 */   intnull,
+    /* 39 */   intnull,
+    /* 40 */   intnull,
+    /* 41 */   intnull,
+    /* 42 */   intnull,
+    /* 43 */   intnull,
+    /* 44 */   intnull,
+    /* 45 */   intnull,
+    /* 46 */   intnull,
+    /* 47 */   intnull,
+    /* 48 */   intnull,
+    /* 49 */   intnull,
+    /* 50 */   intnull,
+    /* 51 */   intnull,
+    /* 52 */   intnull,
+    /* 53 */   intnull,
+    /* 54 */   intnull,
+    /* 55 */   intnull,
+
+    /* 56 */   intnull,
+    /* 57 */   intnull,
+    /* 58 */   intnull,
+    /* 59 */   intnull,
+    /* 60 */   intnull,
+    /* 61 */   intnull,
+    /* 62 */   intnull,
+    /* 63 */   intnull,
 };
 
 void
@@ -155,7 +204,13 @@ ioapic_toggle_entry(int apic, int pin, int mask)
 static int
 ioapic_version(int apic)
 {
-    return ioapic_read(apic, APIC_IO_VERSION) & 0xff;
+    return (ioapic_read(apic, APIC_IO_VERSION) >> APIC_IO_VERSION_SHIFT) & 
0xff;
+}
+
+static int
+ioapic_gsis(int apic)
+{
+    return ((ioapic_read(apic, APIC_IO_VERSION) >> APIC_IO_ENTRIES_SHIFT) & 
0xff) + 1;
 }
 
 static void timer_expiry_callback(void *arg)
@@ -315,6 +370,8 @@ ioapic_configure(void)
     IrqOverrideData *irq_over;
     int timer_gsi;
     int version = ioapic_version(apic);
+    int ngsis = ioapic_gsis(apic);
+    int ngsis2 = 0;
 
     if (version >= 0x20) {
         has_irq_specific_eoi = 1;
@@ -362,7 +419,7 @@ ioapic_configure(void)
         }
     }
 
-    for (pin = 16; pin < 24; pin++) {
+    for (pin = 16; pin < ngsis; pin++) {
         gsi = pin;
 
         /* PCI IRQs PIRQ A-H */
@@ -376,8 +433,30 @@ ioapic_configure(void)
         ioapic_write_entry(apic, pin, entry.both);
     }
 
+    printf("IOAPIC 0 configured with GSI 0-%d\n", ngsis - 1);
+
+    /* Second IOAPIC */
+    if (apic_get_num_ioapics() > 1) {
+        apic = 1;
+        ngsis2 = ioapic_gsis(apic);
+
+        for (pin = 0; pin < ngsis2; pin++) {
+            gsi = pin + ngsis;
+
+            /* Defaults */
+            entry.both.trigger = IOAPIC_LEVEL_TRIGGERED;
+            entry.both.polarity = IOAPIC_ACTIVE_LOW;
+
+            if ((irq_over = acpi_get_irq_override(pin + ngsis))) {
+                gsi = override_irq(irq_over, &entry);
+            }
+            entry.both.vector = IOAPIC_INT_BASE + gsi;
+            ioapic_write_entry(apic, pin, entry.both);
+        }
+
+        printf("IOAPIC 1 configured with GSI %d-%d\n", ngsis, ngsis + ngsis2 - 
1);
+    }
+
     /* Start the IO APIC receiving interrupts */
     lapic_enable();
-
-    printf("IOAPIC 0 configured\n");
 }
-- 
2.43.0





reply via email to

[Prev in Thread] Current Thread [Next in Thread]