intr: Further delay MachIntrABI.finalize()
[dragonfly.git] / sys / platform / pc64 / icu / icu_abi.c
index 01c8d46..849834a 100644 (file)
 
 #include <machine/segments.h>
 #include <machine/md_var.h>
-#include <machine_base/isa/intr_machdep.h>
+#include <machine/intr_machdep.h>
 #include <machine/globaldata.h>
+#include <machine/smp.h>
 
 #include <sys/thread2.h>
 
+#include <machine_base/apic/ioapic_abi.h>
+
 #include "icu.h"
 #include "icu_ipl.h"
 
+extern inthand_t
+       IDTVEC(icu_intr0),      IDTVEC(icu_intr1),
+       IDTVEC(icu_intr2),      IDTVEC(icu_intr3),
+       IDTVEC(icu_intr4),      IDTVEC(icu_intr5),
+       IDTVEC(icu_intr6),      IDTVEC(icu_intr7),
+       IDTVEC(icu_intr8),      IDTVEC(icu_intr9),
+       IDTVEC(icu_intr10),     IDTVEC(icu_intr11),
+       IDTVEC(icu_intr12),     IDTVEC(icu_intr13),
+       IDTVEC(icu_intr14),     IDTVEC(icu_intr15);
+
+static inthand_t *icu_intr[ICU_HWI_VECTORS] = {
+       &IDTVEC(icu_intr0),     &IDTVEC(icu_intr1),
+       &IDTVEC(icu_intr2),     &IDTVEC(icu_intr3),
+       &IDTVEC(icu_intr4),     &IDTVEC(icu_intr5),
+       &IDTVEC(icu_intr6),     &IDTVEC(icu_intr7),
+       &IDTVEC(icu_intr8),     &IDTVEC(icu_intr9),
+       &IDTVEC(icu_intr10),    &IDTVEC(icu_intr11),
+       &IDTVEC(icu_intr12),    &IDTVEC(icu_intr13),
+       &IDTVEC(icu_intr14),    &IDTVEC(icu_intr15)
+};
+
 extern void    ICU_INTREN(int);
 extern void    ICU_INTRDIS(int);
 
-extern inthand_t
-       IDTVEC(icu_fastintr0), IDTVEC(icu_fastintr1),
-       IDTVEC(icu_fastintr2), IDTVEC(icu_fastintr3),
-       IDTVEC(icu_fastintr4), IDTVEC(icu_fastintr5),
-       IDTVEC(icu_fastintr6), IDTVEC(icu_fastintr7),
-       IDTVEC(icu_fastintr8), IDTVEC(icu_fastintr9),
-       IDTVEC(icu_fastintr10), IDTVEC(icu_fastintr11),
-       IDTVEC(icu_fastintr12), IDTVEC(icu_fastintr13),
-       IDTVEC(icu_fastintr14), IDTVEC(icu_fastintr15);
-
 static int     icu_vectorctl(int, int, int);
 static int     icu_setvar(int, const void *);
 static int     icu_getvar(int, void *);
 static void    icu_finalize(void);
 static void    icu_cleanup(void);
-
-static inthand_t *icu_fastintr[ICU_HWI_VECTORS] = {
-       &IDTVEC(icu_fastintr0), &IDTVEC(icu_fastintr1),
-       &IDTVEC(icu_fastintr2), &IDTVEC(icu_fastintr3),
-       &IDTVEC(icu_fastintr4), &IDTVEC(icu_fastintr5),
-       &IDTVEC(icu_fastintr6), &IDTVEC(icu_fastintr7),
-       &IDTVEC(icu_fastintr8), &IDTVEC(icu_fastintr9),
-       &IDTVEC(icu_fastintr10), &IDTVEC(icu_fastintr11),
-       &IDTVEC(icu_fastintr12), &IDTVEC(icu_fastintr13),
-       &IDTVEC(icu_fastintr14), &IDTVEC(icu_fastintr15)
-};
+static void    icu_setdefault(void);
+static void    icu_stabilize(void);
 
 struct machintr_abi MachIntrABI_ICU = {
        MACHINTR_ICU,
@@ -94,7 +99,9 @@ struct machintr_abi MachIntrABI_ICU = {
        .setvar         = icu_setvar,
        .getvar         = icu_getvar,
        .finalize       = icu_finalize,
-       .cleanup        = icu_cleanup
+       .cleanup        = icu_cleanup,
+       .setdefault     = icu_setdefault,
+       .stabilize      = icu_stabilize
 };
 
 static int     icu_imcr_present;
@@ -140,15 +147,49 @@ icu_getvar(int varid, void *buf)
  * Called before interrupts are physically enabled
  */
 static void
-icu_finalize(void)
+icu_stabilize(void)
 {
        int intr;
 
        for (intr = 0; intr < ICU_HWI_VECTORS; ++intr)
                machintr_intrdis(intr);
        machintr_intren(ICU_IRQ_SLAVE);
+}
+
+/*
+ * Called after interrupts physically enabled but before the
+ * critical section is released.
+ */
+static void
+icu_cleanup(void)
+{
+       bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
+}
+
+/*
+ * Called after stablize and cleanup; critical section is not
+ * held and interrupts are not physically disabled.
+ *
+ * For SMP:
+ * Further delayed after BSP's LAPIC is initialized
+ */
+static void
+icu_finalize(void)
+{
+       KKASSERT(MachIntrABI.type == MACHINTR_ICU);
+
+#ifdef SMP
+       if (apic_io_enable) {
+               /*
+                * MachIntrABI switching will happen in
+                * MachIntrABI_IOAPIC.finalize()
+                */
+               MachIntrABI_IOAPIC.setvar(MACHINTR_VAR_IMCR_PRESENT,
+                                         &icu_imcr_present);
+               MachIntrABI_IOAPIC.finalize();
+               return;
+       }
 
-#if defined(SMP)
        /*
         * If an IMCR is present, programming bit 0 disconnects the 8259
         * from the BSP.  The 8259 may still be connected to LINT0 on the
@@ -159,22 +200,22 @@ icu_finalize(void)
         * in addition to the 8259.
         */
        if (icu_imcr_present) {
+               register_t ef;
+
+               crit_enter();
+
+               ef = read_rflags();
+               cpu_disable_intr();
+
                outb(0x22, 0x70);
                outb(0x23, 0x01);
-       }
-#endif
-}
 
-/*
- * Called after interrupts physically enabled but before the
- * critical section is released.
- */
-static void
-icu_cleanup(void)
-{
-       mdcpu->gd_fpending = 0;
-}
+               write_rflags(ef);
 
+               crit_exit();
+       }
+#endif /* SMP */
+}
 
 static int
 icu_vectorctl(int op, int intr, int flags)
@@ -191,16 +232,15 @@ icu_vectorctl(int op, int intr, int flags)
 
        switch(op) {
        case MACHINTR_VECTOR_SETUP:
-               setidt(IDT_OFFSET + intr, icu_fastintr[intr], SDT_SYSIGT,
+               setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYSIGT,
                       SEL_KPL, 0);
                machintr_intren(intr);
                break;
 
        case MACHINTR_VECTOR_TEARDOWN:
-       case MACHINTR_VECTOR_SETDEFAULT:
-               setidt(IDT_OFFSET + intr, icu_fastintr[intr], SDT_SYSIGT,
-                      SEL_KPL, 0);
                machintr_intrdis(intr);
+               setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYSIGT,
+                      SEL_KPL, 0);
                break;
 
        default:
@@ -210,3 +250,16 @@ icu_vectorctl(int op, int intr, int flags)
        write_rflags(ef);
        return error;
 }
+
+static void
+icu_setdefault(void)
+{
+       int intr;
+
+       for (intr = 0; intr < ICU_HWI_VECTORS; ++intr) {
+               if (intr == ICU_IRQ_SLAVE)
+                       continue;
+               setidt(IDT_OFFSET + intr, icu_intr[intr], SDT_SYSIGT,
+                      SEL_KPL, 0);
+       }
+}