[patch] SMP boot hang fixed, io-apic-2.1.92-A

MOLNAR Ingo (mingo@chiara.csoma.elte.hu)
Thu, 2 Apr 1998 09:58:02 +0200 (CEST)


This 2.1.92 patch fixes the SMP boot hangs reported by Ted Serreyn and
Hubert Tonneau. The problem was that we did not deal with 'default MP
configurations' properly. In such cases the IO-APIC's APIC ID is not set
up properly and clashes with the CPU's local APIC's ID, creating all kinds
of fun effects. Also we have to create our own mptable instead of the
BIOS. The patch was tested on different kinds of SMP systems and Ted
Serreyn gave it some heavy testing also, so it really solves the problem.

with this patch we are back to '100% of all SMP Linux systems boot under
2.1.92' status. [if someone still has problems, please mail me]

-- mingo

--- linux/arch/i386/kernel/io_apic.c.orig Thu Mar 26 00:25:04 1998
+++ linux/arch/i386/kernel/io_apic.c Tue Apr 7 13:23:28 1998
@@ -96,6 +96,8 @@
int mp_irq_entries = 0; /* # of MP IRQ source entries */
struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES];
/* MP IRQ source entries */
+int mpc_default_type = 0; /* non-0 if default (table-less)
+ MP configuration */

unsigned int io_apic_read (unsigned int reg)
{
@@ -516,16 +518,16 @@
static void init_sym_mode (void)
{
printk("enabling Symmetric IO mode ... ");
- outb (0x70, 0x22);
- outb (0x01, 0x23);
+ outb_p (0x70, 0x22);
+ outb_p (0x01, 0x23);
printk("...done.\n");
}

void init_pic_mode (void)
{
printk("disabling Symmetric IO mode ... ");
- outb (0x70, 0x22);
- outb (0x00, 0x23);
+ outb_p (0x70, 0x22);
+ outb_p (0x00, 0x23);
printk("...done.\n");
}

@@ -579,7 +581,78 @@
return in_ioapic_list(ioapic_blacklist);
}

+static void setup_ioapic_id (void)
+{
+ struct IO_APIC_reg_00 reg_00;
+
+ /*
+ * 'default' mptable configurations mean a hardwired setup,
+ * 2 CPUs, 16 APIC registers. IO-APIC ID is usually set to 0,
+ * setting it to ID 2 should be fine.
+ */
+
+ /*
+ * Sanity check, is ID 2 really free? Every APIC in the
+ * system must have a unique ID or we get lots of nice
+ * 'stuck on smp_invalidate_needed IPI wait' messages.
+ */
+ if (cpu_present_map & (1<<0x2))
+ panic("APIC ID 2 already used");
+
+ /*
+ * set the ID
+ */
+ *(int *)&reg_00 = io_apic_read(0);
+ printk("... changing IO-APIC physical APIC ID to 2 ...\n");
+ reg_00.ID = 0x2;
+ io_apic_write(0, *(int *)&reg_00);
+
+ /*
+ * Sanity check
+ */
+ *(int *)&reg_00 = io_apic_read(0);
+ if (reg_00.ID != 0x2)
+ panic("could not set ID");
+}

+static void construct_default_ISA_mptable (void)
+{
+ int i, pos=0;
+
+ for (i=0; i<16; i++) {
+ if (!IO_APIC_IRQ(i))
+ continue;
+
+ mp_irqs[pos].mpc_irqtype = 0;
+ mp_irqs[pos].mpc_irqflag = 0;
+ mp_irqs[pos].mpc_srcbus = 0;
+ mp_irqs[pos].mpc_srcbusirq = i;
+ mp_irqs[pos].mpc_dstapic = 0;
+ mp_irqs[pos].mpc_dstirq = i;
+ pos++;
+ }
+ mp_irq_entries = pos;
+ mp_bus_id_to_type[0] = MP_BUS_ISA;
+
+ /*
+ * MP specification 1.4 defines some extra rules for default
+ * configurations, fix them up here:
+ */
+
+ switch (mpc_default_type)
+ {
+ case 2:
+ break;
+ default:
+ /*
+ * pin 2 is IRQ0:
+ */
+ mp_irqs[0].mpc_dstirq = 2;
+ }
+
+ setup_ioapic_id();
+}
+
void setup_IO_APIC (void)
{
int i;
@@ -605,12 +678,6 @@
for (i=0; i<nr_ioapic_registers; i++)
clear_IO_APIC_irq (i);

-#if DEBUG_1
- for (i=0; i<16; i++)
- if (IO_APIC_IRQ(i))
- setup_IO_APIC_irq_ISA_default (i);
-#endif
-
/*
* the following IO-APIC's can be enabled:
*
@@ -634,7 +701,18 @@
io_apic_irqs = 0;
}

+ /*
+ * If there are no explicit mp irq entries: it's either one of the
+ * default configuration types or we are broken. In both cases it's
+ * fine to set up most of the low 16 IOAPIC pins to ISA defaults.
+ */
+ if (!mp_irq_entries) {
+ printk("no explicit IRQ entries, using default mptable\n");
+ construct_default_ISA_mptable();
+ }
+
init_IO_APIC_traps();
+
setup_IO_APIC_irqs ();

if (!timer_irq_works ()) {
@@ -644,9 +722,9 @@
printk("..MP-BIOS bug: i8254 timer not connected to IO-APIC\n");
printk("..falling back to 8259A-based timer interrupt\n");
}
-
- printk("nr of MP irq sources: %d.\n", mp_irq_entries);
- printk("nr of IOAPIC registers: %d.\n", nr_ioapic_registers);
+
+ printk("nr of MP irq sources: %d.\n", mp_irq_entries);
+ printk("nr of IOAPIC registers: %d.\n", nr_ioapic_registers);
print_IO_APIC();
}

--- linux/arch/i386/kernel/smp.c.orig Tue Apr 7 13:05:37 1998
+++ linux/arch/i386/kernel/smp.c Tue Apr 7 13:09:26 1998
@@ -150,6 +150,7 @@
int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
+extern int mpc_default_type;
int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
int mp_current_pci_id = 0;

@@ -477,6 +478,14 @@
cpu_present_map=3;
num_processors=2;
printk("I/O APIC at 0xFEC00000.\n");
+
+ /*
+ * Save the default type number, we
+ * need it later to set the IO-APIC
+ * up properly:
+ */
+ mpc_default_type = mpf->mpf_feature1;
+
printk("Bus #0 is ");
}
switch(mpf->mpf_feature1)

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu