static void
leavecrit(void *dummy __unused)
{
- MachIntrABI.finalize();
+ MachIntrABI.stabilize();
cpu_enable_intr();
MachIntrABI.cleanup();
crit_exit();
static void ioapic_finalize(void);
static void ioapic_cleanup(void);
static void ioapic_setdefault(void);
+static void ioapic_stabilize(void);
static int ioapic_imcr_present;
.getvar = ioapic_getvar,
.finalize = ioapic_finalize,
.cleanup = ioapic_cleanup,
- .setdefault = ioapic_setdefault
+ .setdefault = ioapic_setdefault,
+ .stabilize = ioapic_stabilize
};
static int
}
/*
- * Called before interrupts are physically enabled, this routine does the
- * final configuration of the BSP's local APIC:
+ * Called from ICU's finalize if I/O APIC is enabled, after BSP's LAPIC
+ * is initialized; some of the BSP's LAPIC configuration are adjusted.
*
- * - disable 'pic mode'.
- * - disable 'virtual wire mode'.
- * - enable NMI.
+ * - disable 'pic mode'.
+ * - switch MachIntrABI.
+ * - disable 'virtual wire mode'.
+ * - enable NMI.
*/
static void
ioapic_finalize(void)
{
+ u_long ef;
uint32_t temp;
KKASSERT(MachIntrABI.type == MACHINTR_ICU);
}
/*
- * Setup lint0 (the 8259 'virtual wire' connection). We
+ * Setup LINT0 (the 8259 'virtual wire' connection). We
* mask the interrupt, completing the disconnection of the
* 8259.
*/
temp |= APIC_LVT_MASKED;
lapic.lvt_lint0 = temp;
+ crit_enter();
+
+ ef = read_eflags();
+ cpu_disable_intr();
+
/*
* 8259 is completely disconnected; switch to IOAPIC MachIntrABI
* and reconfigure the default IDT entries.
MachIntrABI = MachIntrABI_IOAPIC;
MachIntrABI.setdefault();
+ write_eflags(ef);
+
+ MachIntrABI.cleanup();
+
+ crit_exit();
+
/*
- * Setup lint1 to handle NMI
+ * Setup LINT1 to handle NMI
*/
temp = lapic.lvt_lint1;
temp &= ~APIC_LVT_MASKED;
lapic.lvt_lint1 = temp;
if (bootverbose)
- apic_dump("bsp_apic_configure()");
+ apic_dump("ioapic_finalize()");
}
/*
bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
}
+/* Must never be called */
+static void
+ioapic_stabilize(void)
+{
+ panic("ioapic_stabilize() is called\n");
+}
+
static int
ioapic_vectorctl(int op, int intr, int flags)
{
*/
mp_start(); /* fire up the APs and APICs */
mp_announce();
+#else
+ MachIntrABI.finalize();
#endif /* SMP */
cpu_setregs();
}
/* Initialize BSP's local APIC */
apic_initialize(TRUE);
+ /* Finalize PIC */
+ MachIntrABI.finalize();
+
/* install the AP 1st level boot code */
install_ap_tramp(boot_addr);
static void icu_finalize(void);
static void icu_cleanup(void);
static void icu_setdefault(void);
+static void icu_stabilize(void);
struct machintr_abi MachIntrABI_ICU = {
MACHINTR_ICU,
.getvar = icu_getvar,
.finalize = icu_finalize,
.cleanup = icu_cleanup,
- .setdefault = icu_setdefault
+ .setdefault = icu_setdefault,
+ .stabilize = icu_stabilize
};
static int icu_imcr_present;
* 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) {
- KKASSERT(MachIntrABI.type == MACHINTR_ICU);
+ /*
+ * MachIntrABI switching will happen in
+ * MachIntrABI_IOAPIC.finalize()
+ */
MachIntrABI_IOAPIC.setvar(MACHINTR_VAR_IMCR_PRESENT,
&icu_imcr_present);
MachIntrABI_IOAPIC.finalize();
return;
}
-#endif
-
- for (intr = 0; intr < ICU_HWI_VECTORS; ++intr)
- machintr_intrdis(intr);
- machintr_intren(ICU_IRQ_SLAVE);
-#ifdef 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
* in addition to the 8259.
*/
if (icu_imcr_present) {
+ u_long ef;
+
+ crit_enter();
+
+ ef = read_eflags();
+ 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)
-{
- bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
+ write_eflags(ef);
+
+ crit_exit();
+ }
+#endif /* SMP */
}
static int
static void ioapic_finalize(void);
static void ioapic_cleanup(void);
static void ioapic_setdefault(void);
+static void ioapic_stabilize(void);
static int ioapic_imcr_present;
.getvar = ioapic_getvar,
.finalize = ioapic_finalize,
.cleanup = ioapic_cleanup,
- .setdefault = ioapic_setdefault
+ .setdefault = ioapic_setdefault,
+ .stabilize = ioapic_stabilize
};
static int
}
/*
- * Called before interrupts are physically enabled, this routine does the
- * final configuration of the BSP's local APIC:
+ * Called from ICU's finalize if I/O APIC is enabled, after BSP's LAPIC
+ * is initialized; some of the BSP's LAPIC configuration are adjusted.
*
- * - disable 'pic mode'.
- * - disable 'virtual wire mode'.
- * - enable NMI.
+ * - disable 'pic mode'.
+ * - disable 'virtual wire mode'.
+ * - switch MachIntrABI
+ * - enable NMI.
*/
static void
ioapic_finalize(void)
{
+ register_t ef;
uint32_t temp;
KKASSERT(MachIntrABI.type == MACHINTR_ICU);
}
/*
- * Setup lint0 (the 8259 'virtual wire' connection). We
+ * Setup LINT0 (the 8259 'virtual wire' connection). We
* mask the interrupt, completing the disconnection of the
* 8259.
*/
temp |= APIC_LVT_MASKED;
lapic->lvt_lint0 = temp;
+ crit_enter();
+
+ ef = read_rflags();
+ cpu_disable_intr();
+
/*
* 8259 is completely disconnected; switch to IOAPIC MachIntrABI
* and reconfigure the default IDT entries.
MachIntrABI = MachIntrABI_IOAPIC;
MachIntrABI.setdefault();
+ write_rflags(ef);
+
+ MachIntrABI.cleanup();
+
+ crit_exit();
+
/*
- * Setup lint1 to handle an NMI
+ * Setup LINT1 to handle an NMI
*/
temp = lapic->lvt_lint1;
temp &= ~APIC_LVT_MASKED;
lapic->lvt_lint1 = temp;
if (bootverbose)
- apic_dump("bsp_apic_configure()");
+ apic_dump("ioapic_finalize()");
}
/*
bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
}
+/* Must never be called */
+static void
+ioapic_stabilize(void)
+{
+ panic("ioapic_stabilize is called\n");
+}
+
static int
ioapic_vectorctl(int op, int intr, int flags)
{
int vector;
int select;
uint32_t value;
- u_long ef;
+ register_t ef;
if (intr < 0 || intr >= IOAPIC_HWI_VECTORS ||
intr == IDT_OFFSET_SYSCALL - IDT_OFFSET)
static void icu_finalize(void);
static void icu_cleanup(void);
static void icu_setdefault(void);
+static void icu_stabilize(void);
struct machintr_abi MachIntrABI_ICU = {
MACHINTR_ICU,
.getvar = icu_getvar,
.finalize = icu_finalize,
.cleanup = icu_cleanup,
- .setdefault = icu_setdefault
+ .setdefault = icu_setdefault,
+ .stabilize = icu_stabilize
};
static int icu_imcr_present;
* 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) {
- KKASSERT(MachIntrABI.type == MACHINTR_ICU);
+ /*
+ * MachIntrABI switching will happen in
+ * MachIntrABI_IOAPIC.finalize()
+ */
MachIntrABI_IOAPIC.setvar(MACHINTR_VAR_IMCR_PRESENT,
&icu_imcr_present);
MachIntrABI_IOAPIC.finalize();
return;
}
-#endif
-
- for (intr = 0; intr < ICU_HWI_VECTORS; ++intr)
- machintr_intrdis(intr);
- machintr_intren(ICU_IRQ_SLAVE);
-#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
* 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)
-{
- bzero(mdcpu->gd_ipending, sizeof(mdcpu->gd_ipending));
+ write_rflags(ef);
+
+ crit_exit();
+ }
+#endif /* SMP */
}
static int
*/
mp_start(); /* fire up the APs and APICs */
mp_announce();
+#else
+ MachIntrABI.finalize();
#endif /* SMP */
cpu_setregs();
}
/* Initialize BSP's local APIC */
apic_initialize(TRUE);
+ /* Finalize PIC */
+ MachIntrABI.finalize();
+
/* install the AP 1st level boot code */
pmap_kenter(va, boot_address);
cpu_invlpg((void *)va); /* JG XXX */
static int dummy_getvar(int, void *);
static void dummy_finalize(void);
static void dummy_intrcleanup(void);
+static void dummy_stabilize(void);
struct machintr_abi MachIntrABI = {
MACHINTR_GENERIC,
.setvar = dummy_setvar,
.getvar = dummy_getvar,
.finalize = dummy_finalize,
- .cleanup = dummy_intrcleanup
+ .cleanup = dummy_intrcleanup,
+ .stabilize = dummy_stabilize
};
static void
{
}
+static void
+dummy_stabilize(void)
+{
+}
+
/*
* Process pending interrupts
*/
static int dummy_getvar(int, void *);
static void dummy_finalize(void);
static void dummy_intrcleanup(void);
+static void dummy_stabilize(void);
struct machintr_abi MachIntrABI = {
MACHINTR_GENERIC,
.setvar = dummy_setvar,
.getvar = dummy_getvar,
.finalize = dummy_finalize,
- .cleanup = dummy_intrcleanup
+ .cleanup = dummy_intrcleanup,
+ .stabilize = dummy_stabilize
};
static void
{
}
+static void
+dummy_stabilize(void)
+{
+}
+
/*
* Process pending interrupts
*/
void (*finalize)(void); /* final before ints enabled */
void (*cleanup)(void); /* cleanup */
void (*setdefault)(void); /* set default vectors */
+ void (*stabilize)(void); /* stable before ints enabled */
};
#define machintr_intren(intr) MachIntrABI.intren(intr)