[coreboot] Patch set updated for coreboot: 3665162 IOAPIC: Divide setup_ioapic() in two parts.

Kyösti Mälkki (kyosti.malkki@gmail.com) gerrit at coreboot.org
Sun Nov 20 22:08:18 CET 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 3665162140efa06ea97201642f6d74cb945efd87
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date:   Sun Nov 20 20:36:21 2011 +0200

    IOAPIC: 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.
    
    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 |  152 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 114 insertions(+), 38 deletions(-)

diff --git a/src/arch/x86/lib/ioapic.c b/src/arch/x86/lib/ioapic.c
index 81d964c..91e43a6 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,85 @@ 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 loud = 0;
+	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;
+
+	/* 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))
+		loud = 1;
+
+	if (!new_id) {
+		printk(loud ? BIOS_CRIT : BIOS_DEBUG,
+			"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(loud ? BIOS_CRIT : BIOS_DEBUG,
+			"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(BIOS_CRIT,
+				"IOAPIC: 0x%08x changing ID failed (%d!=%d)\n",
+				ioapic_base, active_id, new_id);
+	}
 
-	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) & 0xf0ffffff) |
-			(ioapic_id << 24));
+	/* 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 +155,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 +169,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 +179,37 @@ 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();
+	u8 ioapic_dt = CONFIG_IOAPIC_DELIVERY_TYPE;
+
+	printk(BIOS_DEBUG, "IOAPIC: Initializing IOAPIC at 0x%08x\n",
+	       ioapic_base);
+	init_ioapic(ioapic_base, new_id, ioapic_dt);
+
+	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