Skip to contentSkip to conversation

linux-2.4.20-pre11_clustered-apic-tweaks_A0

PATCH New john stultz 1 participant 4 messages Oct 16, 2002 – Oct 17, 2002 Documentation

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 linux-2.4.20-pre11_clustered-apic-tweaks_A0

Marcelo, all,

Originally I was going to send a larger patch that had the rest of the
needed changes for summit, but I've gone through and split that up even more. This is similar to the earlier cleanup I sent you (although this one compiles & boots on UP properly :), and just moves some code around in preparation for further changes.

Again, this code originally comes from James Cleverdon's summit patch,
which I have been chopping/crushing/blending up into hopefully more easily digestible pieces. Thus I deserve none of the credit, and all the blame for this.

please consider for acceptance.

thanks
-john

arch/i386/kernel/apic.c +9 -3
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
@@ -261,6 +261,14 @@
 	apic_write_around(APIC_LVT1, value);
 }
 
+static unsigned long calculate_ldr(unsigned long old)
+{
+	unsigned long id;
+	
+	id = 1UL << smp_processor_id();
+	return (old & ~APIC_LDR_MASK)|SET_APIC_LOGICAL_ID(id);
+}
+
 void __init setup_local_APIC (void)
 {
 	unsigned long value, ver, maxlvt;
@@ -304,9 +312,7 @@
 		 * Set up the logical destination ID.
 		 */
 		value = apic_read(APIC_LDR);
-		value &= ~APIC_LDR_MASK;
-		value |= (1<<(smp_processor_id()+24));
-		apic_write_around(APIC_LDR, value);
+		apic_write_around(APIC_LDR, calculate_ldr(value));
 	}
 
 	/*
arch/i386/kernel/io_apic.c +2 -2
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
@@ -1067,7 +1067,7 @@
 		
 		old_id = mp_ioapics[apic].mpc_apicid;
 
-		if (mp_ioapics[apic].mpc_apicid >= 0xf) {
+		if (mp_ioapics[apic].mpc_apicid >= apic_broadcast_id) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
@@ -1086,7 +1086,7 @@
 			for (i = 0; i < 0xf; i++)
 				if (!(phys_id_present_map & (1 << i)))
 					break;
-			if (i >= 0xf)
+			if (i >= apic_broadcast_id)
 				panic("Max APIC ID exceeded!\n");
 			printk(KERN_ERR "... fixing up to %d. (tell your hw vendor)\n",
 				i);
include/asm-i386/smpboot.h +3 -0
diff -Nru a/include/asm-i386/smpboot.h b/include/asm-i386/smpboot.h
@@ -41,6 +41,9 @@
 #endif /* CONFIG_X86_IO_APIC */
 #endif /* CONFIG_X86_LOCAL_APIC */
 
+#define apic_broadcast_id (APIC_BROADCAST_ID_APIC)
+
+
 #define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467)
 #define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469)
 
#1 lore raw

PATCH 1/1 linux-2.4.20-pre11_summit_A0 (1/3 - cleanups)

Marcelo, all,

I'm probably pressing my luck w/ this, but since the tree doesn't say
-rc, I might as well send this off. This is the first chunk of the clustered apic changes needed for summit (all of which comes from James Cleverdon's summit patch. Thank him, blame me). This patch is mainly cleanups, but adds some code to setup phys_cpu_present_map more generally for clustered apic systems. It is also dependent on the clustered-apic-tweaks_A0 patch I sent out earlier today.

Two more patches should follow.

please consider for acceptance.

thanks
-john

arch/i386/kernel/mpparse.c +8 -5
diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
@@ -65,9 +65,12 @@
 
 /* Bitmask of physically existing CPUs */
 unsigned long phys_cpu_present_map;
+unsigned long logical_cpu_present_map;
 
 unsigned char esr_disable = 0;
 
+unsigned char raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
+
 /*
  * Intel MP BIOS table parsing routines:
  */
@@ -231,11 +234,9 @@
 	}
 	ver = m->mpc_apicver;
 
-	if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
-		phys_cpu_present_map |= (logical_apicid&0xf) << (4*quad);
-	} else {
-		phys_cpu_present_map |= 1 << m->mpc_apicid;
-	}
+	logical_cpu_present_map |= 1 << (num_processors-1);
+ 	phys_cpu_present_map |= apicid_to_phys_cpu_present(m->mpc_apicid);
+ 
 	/*
 	 * Validate version
 	 */
@@ -244,6 +245,7 @@
 		ver = 0x10;
 	}
 	apic_version[m->mpc_apicid] = ver;
+	raw_phys_apicid[num_processors - 1] = m->mpc_apicid;
 }
 
 static void __init MP_bus_info (struct mpc_config_bus *m)
@@ -511,6 +513,7 @@
 
 	if (clustered_apic_mode){
 		esr_disable = 1;
+		phys_cpu_present_map = logical_cpu_present_map;
 	}
 
 	if (!num_processors)
arch/i386/kernel/smpboot.c +15 -15
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
@@ -525,12 +525,12 @@
 	int apicid, cpu;
 
 	for (apicid = 0; apicid < MAX_APICID; apicid++) {
-		physical_apicid_2_cpu[apicid] = -1;
-		logical_apicid_2_cpu[apicid] = -1;
+		physical_apicid_2_cpu[apicid] = BAD_APICID;
+		logical_apicid_2_cpu[apicid] = BAD_APICID;
 	}
 	for (cpu = 0; cpu < NR_CPUS; cpu++) {
-		cpu_2_physical_apicid[cpu] = -1;
-		cpu_2_logical_apicid[cpu] = -1;
+		cpu_2_physical_apicid[cpu] = BAD_APICID;
+		cpu_2_logical_apicid[cpu] = BAD_APICID;
 	}
 }
 
@@ -540,7 +540,7 @@
  * else physical apic ids
  */
 {
-	if (clustered_apic_mode) {
+	if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
 		logical_apicid_2_cpu[apicid] = cpu;	
 		cpu_2_logical_apicid[cpu] = apicid;
 	} else {
@@ -555,12 +555,12 @@
  * else physical apic ids
  */
 {
-	if (clustered_apic_mode) {
-		logical_apicid_2_cpu[apicid] = -1;	
-		cpu_2_logical_apicid[cpu] = -1;
+	if (clustered_apic_mode == CLUSTERED_APIC_NUMAQ) {
+		logical_apicid_2_cpu[apicid] = BAD_APICID;
+		cpu_2_logical_apicid[cpu] = BAD_APICID;
 	} else {
-		physical_apicid_2_cpu[apicid] = -1;	
-		cpu_2_physical_apicid[cpu] = -1;
+		physical_apicid_2_cpu[apicid] = BAD_APICID;
+		cpu_2_physical_apicid[cpu] = BAD_APICID;
 	}
 }
 
@@ -785,7 +785,7 @@
 	unsigned long boot_error = 0;
 	int timeout, cpu;
 	unsigned long start_eip;
-	unsigned short nmi_high, nmi_low;
+	unsigned short nmi_high = 0, nmi_low = 0;
 
 	cpu = ++cpucount;
 	/*
@@ -1111,7 +1111,7 @@
 		if (apicid == boot_cpu_apicid)
 			continue;
 
-		if (!(phys_cpu_present_map & (1 << bit)))
+		if (!(phys_cpu_present_map & (1ul << bit)))
 			continue;
 		if ((max_cpus >= 0) && (max_cpus <= cpucount+1))
 			continue;
@@ -1122,9 +1122,9 @@
 		 * Make sure we unmap all failed CPUs
 		 */
 		if ((boot_apicid_to_cpu(apicid) == -1) &&
-				(phys_cpu_present_map & (1 << bit)))
-			printk("CPU #%d not responding - cannot use it.\n",
-								apicid);
+				(phys_cpu_present_map & (1ul << bit)))
+			printk("CPU #%d/0x%02x not responding - cannot use it.\n",
+								bit, apicid);
 	}
 
 	/*
include/asm-i386/smpboot.h +10 -1
diff -Nru a/include/asm-i386/smpboot.h b/include/asm-i386/smpboot.h
@@ -42,13 +42,15 @@
 #endif /* CONFIG_X86_LOCAL_APIC */
 
 #define apic_broadcast_id (APIC_BROADCAST_ID_APIC)
-
+#define BAD_APICID 0xFFu
 
 #define TRAMPOLINE_LOW phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0x8:0x467)
 #define TRAMPOLINE_HIGH phys_to_virt((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?0xa:0x469)
 
 #define boot_cpu_apicid ((clustered_apic_mode == CLUSTERED_APIC_NUMAQ)?boot_cpu_logical_apicid:boot_cpu_physical_apicid)
 
+extern unsigned char raw_phys_apicid[NR_CPUS];
+
 /*
  * How to map from the cpu_present_map
  */
@@ -57,6 +59,13 @@
 	if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
 		return (mps_cpu/4)*16 + (1<<(mps_cpu%4));
 	return mps_cpu;
+}
+
+static inline unsigned long apicid_to_phys_cpu_present(int apicid)
+{
+	if(clustered_apic_mode)
+		return 1UL << (((apicid >> 4) << 2) + (apicid & 0x3));
+	return 1UL << apicid;
 }
 
 #define physical_to_logical_apicid(phys_apic) ( (1ul << (phys_apic & 0x3)) | (phys_apic & 0xF0u) )
#2 lore raw

PATCH 1/1 linux-2.4.20-pre11_summit_A0 (2/3 - XAPIC code)

Marcelo, all,
Part 2 of James Cleverdon's clustered apic changes for summit. This is
the core addition of code to make summit work. Since nothing sets clustered_apic_mode to CLUSTERED_APIC_XAPIC yet, this patch shouldn't affect anything.

please consider for inclusion.

thanks
-john

arch/i386/kernel/apic.c +8 -3
diff -Nru a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
@@ -264,8 +264,10 @@
 static unsigned long calculate_ldr(unsigned long old)
 {
 	unsigned long id;
-	
-	id = 1UL << smp_processor_id();
+	if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
+		id = physical_to_logical_apicid(hard_smp_processor_id());
+	else
+		id = 1UL << smp_processor_id();
 	return (old & ~APIC_LDR_MASK)|SET_APIC_LOGICAL_ID(id);
 }
 
@@ -306,7 +308,10 @@
 		 * for us. Otherwise put the APIC into clustered or flat
 		 * delivery mode. Must be "all ones" explicitly for 82489DX.
 		 */
-		apic_write_around(APIC_DFR, APIC_DFR_FLAT);
+		if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
+			apic_write_around(APIC_DFR, APIC_DFR_CLUSTER);
+		else
+			apic_write_around(APIC_DFR, APIC_DFR_FLAT);
 
 		/*
 		 * Set up the logical destination ID.
arch/i386/kernel/io_apic.c +3 -1
diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
@@ -1079,8 +1079,10 @@
 		 * Sanity check, is the ID really free? Every APIC in a
 		 * system must have a unique ID or we get lots of nice
 		 * 'stuck on smp_invalidate_needed IPI wait' messages.
+		 * I/O APIC IDs no longer have any meaning for xAPICs and SAPICs.
 		 */
-		if (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid)) {
+		if ((clustered_apic_mode != CLUSTERED_APIC_XAPIC) &&
+		    (phys_id_present_map & (1 << mp_ioapics[apic].mpc_apicid))) {
 			printk(KERN_ERR "BIOS bug, IO-APIC#%d ID %d is already used!...\n",
 				apic, mp_ioapics[apic].mpc_apicid);
 			for (i = 0; i < 0xf; i++)
arch/i386/kernel/smp.c +4 -1
diff -Nru a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c
@@ -214,7 +214,10 @@
 			/*
 			 * prepare target chip field
 			 */
-			cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu));
+			if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
+				cfg = __prepare_ICR2(cpu_to_physical_apicid(query_cpu));
+			else
+				cfg = __prepare_ICR2(cpu_to_logical_apicid(query_cpu));
 			apic_write_around(APIC_ICR2, cfg);
 		
 			/*
arch/i386/kernel/smpboot.c +4 -1
diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
@@ -1019,7 +1019,10 @@
 	 * We have the boot CPU online for sure.
 	 */
 	set_bit(0, &cpu_online_map);
-	boot_cpu_logical_apicid = logical_smp_processor_id();
+	if (clustered_apic_mode == CLUSTERED_APIC_XAPIC)
+		boot_cpu_logical_apicid = physical_to_logical_apicid(boot_cpu_physical_apicid);
+	else
+		boot_cpu_logical_apicid = logical_smp_processor_id();
 	map_cpu_to_boot_apicid(0, boot_cpu_apicid);
 
 	global_irq_holder = 0;
include/asm-i386/apicdef.h +5 -1
diff -Nru a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
@@ -32,6 +32,7 @@
 #define			SET_APIC_LOGICAL_ID(x)	(((x)<<24))
 #define			APIC_ALL_CPUS		0xFF
 #define		APIC_DFR	0xE0
+#define			APIC_DFR_CLUSTER	0x0FFFFFFFul	/* Clustered */
 #define			APIC_DFR_FLAT		0xFFFFFFFFul	/* Flat mode */
 #define		APIC_SPIV	0xF0
 #define			APIC_SPIV_FOCUS_DISABLED	(1<<9)
@@ -58,6 +59,7 @@
 #define			APIC_INT_LEVELTRIG	0x08000
 #define			APIC_INT_ASSERT		0x04000
 #define			APIC_ICR_BUSY		0x01000
+#define			APIC_DEST_PHYSICAL	0x00000
 #define			APIC_DEST_LOGICAL	0x00800
 #define			APIC_DM_FIXED		0x00000
 #define			APIC_DM_LOWEST		0x00100
@@ -111,8 +113,10 @@
 #define MAX_IO_APICS 8
 
 /*
- * The broadcast ID is 0xF for old APICs.
+ * The broadcast ID is 0xF for old APICs and 0xFF for xAPICs.  SAPICs
+ * don't broadcast (yet?), but if they did, they might use 0xFFFF.
  */
+#define APIC_BROADCAST_ID_XAPIC (0xFF)
 #define APIC_BROADCAST_ID_APIC  (0x0F)
 
 /*
include/asm-i386/smpboot.h +2 -0
diff -Nru a/include/asm-i386/smpboot.h b/include/asm-i386/smpboot.h
@@ -56,6 +56,8 @@
  */
 static inline int cpu_present_to_apicid(int mps_cpu)
 {
+	if (clustered_apic_mode == CLUSTERED_APIC_XAPIC)
+		return raw_phys_apicid[mps_cpu];
 	if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
 		return (mps_cpu/4)*16 + (1<<(mps_cpu%4));
 	return mps_cpu;
#3 lore raw

PATCH 1/1 linux-2.4.20-pre11_summit_A0 (3/3 - Integration)

Marcelo, all,
Better late then never, here is the final patch needed to get the
summit based x440 booting w/ all CPUs. This patch (originally by James Cleverdon)introduces config options similar to 2.5, enables autodetection of x440 and NUMAQ hardware, and adds the last bit of required changes (enlarged MAX_IO_APICS, etc - all wrapped in CONFIG_X86_CLUSTERED_APIC).

Compiles and boots on:
o NUMAQ
o x440
o SMP
o UP

please consider for inclusion.

thanks
-john

Documentation/Configure.help +10 -2
diff -Nru a/Documentation/Configure.help b/Documentation/Configure.help
@@ -246,13 +246,21 @@
 
   If unsure, say N.
 
-Multiquad support for NUMA systems
-CONFIG_MULTIQUAD
+Multiquad support for NUMAQ systems
+CONFIG_X86_NUMAQ
   This option is used for getting Linux to run on a (IBM/Sequent) NUMA 
   multiquad box. This changes the way that processors are bootstrapped,
   and uses Clustered Logical APIC addressing mode instead of Flat Logical.
   You will need a new lynxer.elf file to flash your firmware with - send
   email to [email protected]
+
+Support for IBM Summit (EXA) systems
+CONFIG_X86_SUMMIT
+  This option is needed for IBM systems that use the Summit/EXA chipset.
+  (EXA: Extendable Xseries Architecture)In particular, it is needed for 
+  the x440 (even for the 4-CPU model).
+
+  If you don't have this computer, you may safely say N.
 
 IO-APIC support on uniprocessors
 CONFIG_X86_UP_IOAPIC
arch/i386/config.in +13 -1
diff -Nru a/arch/i386/config.in b/arch/i386/config.in
@@ -216,7 +216,19 @@
       define_bool CONFIG_X86_IO_APIC y
    fi
 else
-   bool 'Multiquad NUMA system' CONFIG_MULTIQUAD
+   bool 'Multi-node NUMA system support' CONFIG_X86_NUMA
+   if [ "$CONFIG_X86_NUMA" = "y" ]; then
+      #Platform Choices
+      bool ' Multiquad (IBM/Sequent) NUMAQ support' CONFIG_X86_NUMAQ
+      if [ "$CONFIG_X86_NUMAQ" = "y" ]; then
+         define_bool CONFIG_X86_CLUSTERED_APIC y
+		 define_bool CONFIG_MULTIQUAD y
+      fi
+      bool ' IBM x440 (Summit/EXA) support' CONFIG_X86_SUMMIT
+      if [ "$CONFIG_X86_SUMMIT" = "y" ]; then
+         define_bool CONFIG_X86_CLUSTERED_APIC y
+      fi
+   fi
 fi
 
 bool 'Unsynced TSC support' CONFIG_X86_TSC_DISABLE
arch/i386/kernel/mpparse.c +24 -10
diff -Nru a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
@@ -67,8 +67,11 @@
 unsigned long phys_cpu_present_map;
 unsigned long logical_cpu_present_map;
 
+#ifdef CONFIG_X86_CLUSTERED_APIC
 unsigned char esr_disable = 0;
-
+unsigned char clustered_apic_mode = CLUSTERED_APIC_NONE;
+unsigned int apic_broadcast_id = APIC_BROADCAST_ID_APIC;
+#endif
 unsigned char raw_phys_apicid[NR_CPUS] = { [0 ... NR_CPUS-1] = BAD_APICID };
 
 /*
@@ -400,7 +403,7 @@
 
 static int __init smp_read_mpc(struct mp_config_table *mpc)
 {
-	char str[16];
+	char oem[16], prod[14];
 	int count=sizeof(*mpc);
 	unsigned char *mpt=((unsigned char *)mpc)+count;
 
@@ -425,14 +428,16 @@
 		printk(KERN_ERR "SMP mptable: null local APIC address!\n");
 		return 0;
 	}
-	memcpy(str,mpc->mpc_oem,8);
-	str[8]=0;
-	printk("OEM ID: %s ",str);
-
-	memcpy(str,mpc->mpc_productid,12);
-	str[12]=0;
-	printk("Product ID: %s ",str);
+	memcpy(oem,mpc->mpc_oem,8);
+	oem[8]=0;
+	printk("OEM ID: %s ",oem);
+
+	memcpy(prod,mpc->mpc_productid,12);
+	prod[12]=0;
+	printk("Product ID: %s ",prod);
 
+	detect_clustered_apic(oem, prod);
+	
 	printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
 
 	/* save the local APIC address, it might be non-default,
@@ -512,9 +517,18 @@
 	}
 
 	if (clustered_apic_mode){
-		esr_disable = 1;
 		phys_cpu_present_map = logical_cpu_present_map;
 	}
+
+
+	printk("Enabling APIC mode: ");
+	if(clustered_apic_mode == CLUSTERED_APIC_NUMAQ)
+		printk("Clustered Logical.	");
+	else if(clustered_apic_mode == CLUSTERED_APIC_XAPIC)
+		printk("Physical.	");
+	else
+		printk("Flat.	");
+	printk("Using %d I/O APICs\n",nr_ioapics);
 
 	if (!num_processors)
 		printk(KERN_ERR "SMP mptable: no processors registered!\n");
include/asm-i386/apicdef.h +5 -0
diff -Nru a/include/asm-i386/apicdef.h b/include/asm-i386/apicdef.h
@@ -110,7 +110,12 @@
 
 #define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
 
+#ifdef CONFIG_X86_CLUSTERED_APIC
+#define MAX_IO_APICS 32
+#else
 #define MAX_IO_APICS 8
+#endif
+
 
 /*
  * The broadcast ID is 0xF for old APICs and 0xFF for xAPICs.  SAPICs
include/asm-i386/mpspec.h +4 -3
diff -Nru a/include/asm-i386/mpspec.h b/include/asm-i386/mpspec.h
@@ -15,12 +15,13 @@
 
 /*
  * a maximum of 16 APICs with the current APIC ID architecture.
+ * xAPICs can have up to 256.  SAPICs have 16 ID bits.
  */
-#ifdef CONFIG_MULTIQUAD
+#ifdef CONFIG_X86_CLUSTERED_APIC
 #define MAX_APICS 256
-#else /* !CONFIG_MULTIQUAD */
+#else
 #define MAX_APICS 16
-#endif /* CONFIG_MULTIQUAD */
+#endif
 
 #define MAX_MPC_ENTRY 1024
 
include/asm-i386/smpboot.h +28 -15

63 lines not on this page · raw message