[coreboot] Patch set updated for coreboot: 0bccb85 Divide setup_ioapic() in two parts.
Kyösti Mälkki (kyosti.malkki@gmail.com)
gerrit at coreboot.org
Wed Oct 19 18:41:27 CEST 2011
Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/300
-gerrit
commit 0bccb851b436f1d319494a613a477c5fe1279911
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date: Wed Oct 19 01:29:03 2011 +0300
Divide setup_ioapic() in two parts.
Currently some southbridge codes implement the init_ioapic() part
locally and do not implement the load_vectors() part at all.
I suspect that load_vectors() should always be called.
I can push cleaned i82801 variants for testing.
Revised init_ioapic() to log on a critical level if one tries to
change an already assigned (non-zero) APIC ID, or when the APIC ID
is not assigned.
Change-Id: Ic5e860b9b669ecd1e9ddac4bbb92d80bdb9c2fca
Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
src/arch/x86/lib/ioapic.c | 148 +++++++++++++++++++++++++++++++++------------
1 files changed, 110 insertions(+), 38 deletions(-)
diff --git a/src/arch/x86/lib/ioapic.c b/src/arch/x86/lib/ioapic.c
index 3f64209..94f796b 100644
--- a/src/arch/x86/lib/ioapic.c
+++ b/src/arch/x86/lib/ioapic.c
@@ -34,6 +34,11 @@ static void io_apic_write(u32 ioapic_base, u32 reg, u32 value)
write32(ioapic_base + 0x10, value);
}
+/**
+ * Clear all IOAPIC vectors.
+ *
+ * @ioapic_base IOAPIC base address
+ */
void clear_ioapic(u32 ioapic_base)
{
u32 low, high;
@@ -64,24 +69,82 @@ void clear_ioapic(u32 ioapic_base)
}
}
-void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
+/**
+ * Assign IOAPIC with an ID and set delivery type.
+ *
+ * @ioapic_base IOAPIC base address
+ * @new_id If non-zero (1-15), assign new apic ID.
+ * If zero, use previously assigned apic ID.
+ * @delivery If 0x0, deliver interrupts on APIC serial bus
+ * If 0x1, deliver interrupts on FSB
+ */
+static void init_ioapic(u32 ioapic_base, u8 new_id, u8 delivery)
{
- u32 bsp_lapicid = lapicid();
- u32 low, high;
- u32 i, ioapic_interrupts;
+ u8 loglvl = BIOS_DEBUG;
+ u8 active_id;
+ u32 reg32;
- printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%08x\n",
- ioapic_base);
- printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC = 0x%02x\n",
- bsp_lapicid);
+ reg32 = io_apic_read(ioapic_base, 0x00);
+ active_id = (reg32 >> 24) & 0xf;
- if (ioapic_id) {
- printk(BIOS_DEBUG, "IOAPIC: ID = 0x%02x\n", ioapic_id);
- /* Set IOAPIC ID if it has been specified. */
- io_apic_write(ioapic_base, 0x00,
- (io_apic_read(ioapic_base, 0x00) & 0xfff0ffff) |
- (ioapic_id << 24));
+ /* Changing a previously assigned ID and attempting
+ * to use ID=0 here are logged at a critical level.
+ */
+ if ( ((active_id && new_id) && (active_id != new_id)) ||
+ !(active_id || new_id))
+ loglvl=BIOS_CRIT;
+
+ if (!new_id) {
+ printk(loglvl, "IOAPIC: 0x%08x using old ID = %d\n",
+ ioapic_base, active_id);
+
+ } else {
+ reg32 &= 0xf0ffffff;
+ reg32 |= (new_id & 0xf) << 24;
+ io_apic_write(ioapic_base, 0x00, reg32);
+
+ printk(loglvl, "IOAPIC: 0x%08x changing ID = %d->%d\n",
+ ioapic_base, active_id, new_id);
+
+ reg32 = io_apic_read(ioapic_base, 0x00);
+ active_id = (reg32 >> 24) & 0xf;
+ if (active_id != new_id)
+ printk(loglvl, "IOAPIC: 0x%08x changing ID failed (%d!=%d)\n",
+ ioapic_base, active_id, new_id);
+ }
+
+ /* Assign interrupt delivery type */
+ reg32 = io_apic_read(ioapic_base, 0x03);
+ switch (delivery) {
+ case 0:
+ printk(BIOS_DEBUG, "IOAPIC: Delivery is on APIC serial bus\n");
+ reg32 = 0x00;
+ break;
+ case 1:
+ printk(BIOS_DEBUG, "IOAPIC: Delivery is on FSB\n");
+ reg32 = 0x01;
+ break;
+ default:
+ printk(BIOS_CRIT, "IOAPIC: Delivery is reverted to FSB\n");
+ reg32 = 0x01;
+ break;
}
+ io_apic_write(ioapic_base, 0x03, reg32);
+}
+
+/**
+ * Fill IOAPIC vectors all targeting the same processor.
+ * Virtual Wire Mode on vector 0 is enabled, others remain disabled.
+ *
+ *
+ * @ioapic_base IOAPIC base address
+ * @bsp_lapicid APIC ID of a CPU to receive the interrupts
+ *
+ */
+static void load_vectors(u32 ioapic_base, u8 bsp_lapicid)
+{
+ u32 low, high;
+ u32 i, ioapic_interrupts;
/* Read the available number of interrupts. */
ioapic_interrupts = (io_apic_read(ioapic_base, 0x01) >> 16) & 0xff;
@@ -89,28 +152,6 @@ void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
ioapic_interrupts = 24;
printk(BIOS_DEBUG, "IOAPIC: %d interrupts\n", ioapic_interrupts);
-// XXX this decision should probably be made elsewhere, and
-// it's the C3, not the EPIA this depends on.
-#if CONFIG_EPIA_VT8237R_INIT
-#define IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
-#else
-#define IOAPIC_INTERRUPTS_ON_FSB
-#endif
-
-#ifdef IOAPIC_INTERRUPTS_ON_FSB
- /*
- * For the Pentium 4 and above APICs deliver their interrupts
- * on the front side bus, enable that.
- */
- printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on FSB\n");
- io_apic_write(ioapic_base, 0x03,
- io_apic_read(ioapic_base, 0x03) | (1 << 0));
-#endif
-#ifdef IOAPIC_INTERRUPTS_ON_APIC_SERIAL_BUS
- printk(BIOS_DEBUG, "IOAPIC: Enabling interrupts on APIC serial bus\n");
- io_apic_write(ioapic_base, 0x03, 0);
-#endif
-
/* Enable Virtual Wire Mode. */
low = ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT;
high = bsp_lapicid << (56 - 32);
@@ -125,10 +166,8 @@ void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
printk(BIOS_SPEW, "IOAPIC: reg 0x%08x value 0x%08x 0x%08x\n",
0, high, low);
-
low = DISABLED;
high = NONE;
-
for (i = 1; i < ioapic_interrupts; i++) {
io_apic_write(ioapic_base, i * 2 + 0x10, low);
io_apic_write(ioapic_base, i * 2 + 0x11, high);
@@ -137,3 +176,36 @@ void setup_ioapic(u32 ioapic_base, u8 ioapic_id)
i, high, low);
}
}
+
+// XXX this decision should probably be made elsewhere, and
+// it's the C3, not the EPIA this depends on.
+
+#if CONFIG_EPIA_VT8237R_INIT
+#define CONFIG_IOAPIC_DELIVERY_TYPE 0
+#else
+#define CONFIG_IOAPIC_DELIVERY_TYPE 1
+#endif
+
+/**
+ * Assign IOAPIC with an ID
+ *
+ * Compile-time options from mainboard Kconfig can affect the
+ * chosen IOAPIC operational mode.
+ *
+ * @ioapic_base IOAPIC base address
+ * @new_id If non-zero (1-15), assign new apic ID.
+ * If zero, use previously assigned apic ID.
+ */
+void setup_ioapic(u32 ioapic_base, u8 new_id)
+{
+ u8 bsp_lapicid = lapicid();
+
+ printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%08x\n",
+ ioapic_base);
+ init_ioapic(ioapic_base, new_id, CONFIG_IOAPIC_DELIVERY_TYPE);
+
+ printk(BIOS_DEBUG, "IOAPIC: Bootstrap Processor Local APIC ID = %d\n",
+ bsp_lapicid);
+ load_vectors(ioapic_base, bsp_lapicid);
+}
+
More information about the coreboot
mailing list