From: Andrew Theurer <habanero@us.ibm.com>

The patch allows you to not boot a cpu with a specific apicid.  This is an
enhancement over maxcpus.  The problem with max cpus is that it does not
give you control over which specific cpus are not booted.  This becomes a
problem with hyperthreading in situations when you only want the logical
processors from the N out of 8 physical cpus.  The problem is that smp
ordering on some arches is not ideal for this, and can cause a cpu sibling
map like:

0:8
1:9
2:10
2:11
3:12
4:13
5:14
6:15
7:16

If you wanted both siblings on the the first 4 cpus in this system, maxcpus
will not work.  Specifying maxcpus=8 would get you one sibling from all 8
physical cpus.  

To fix this, simply use skip_apicids=x,y,z kernel parameter.  This allows
basically any combination of cpus.  You can even boot physical cpus with
different sibling counts on the same system for kicks.  




 Documentation/kernel-parameters.txt |    4 ++++
 arch/i386/kernel/smpboot.c          |   16 ++++++++++++++++
 init/main.c                         |   14 ++++++++++++++
 3 files changed, 34 insertions(+)

diff -puN arch/i386/kernel/smpboot.c~skip-apic-ids-on-boot arch/i386/kernel/smpboot.c
--- 25/arch/i386/kernel/smpboot.c~skip-apic-ids-on-boot	2003-06-26 18:38:18.000000000 -0700
+++ 25-akpm/arch/i386/kernel/smpboot.c	2003-06-26 18:38:18.000000000 -0700
@@ -82,6 +82,10 @@ extern unsigned char trampoline_data [];
 extern unsigned char trampoline_end  [];
 static unsigned char *trampoline_base;
 
+/* used to selectively not boot certain CPUs with apicids */
+extern int skip_apic_ids[NR_CPUS];
+
+
 /*
  * Currently trivial. Write the real->protected mode
  * bootstrap into the page concerned. The caller
@@ -934,6 +938,16 @@ void *xquad_portio;
 
 int cpu_sibling_map[NR_CPUS] __cacheline_aligned;
 
+static int skip_this_apicid(int apicid)
+{
+	int i;
+
+	for (i = 1; i < (skip_apic_ids[0] + 1); i++)
+		if (apicid == skip_apic_ids[i])
+			return 1;
+	return 0;
+}
+
 static void __init smp_boot_cpus(unsigned int max_cpus)
 {
 	int apicid, cpu, bit, kicked;
@@ -1032,6 +1046,8 @@ static void __init smp_boot_cpus(unsigne
 			continue;
 		if (max_cpus <= cpucount+1)
 			continue;
+		if (skip_this_apicid(apicid))
+			continue;
 
 		if (do_boot_cpu(apicid))
 			printk("CPU #%d not responding - cannot use it.\n",
diff -puN Documentation/kernel-parameters.txt~skip-apic-ids-on-boot Documentation/kernel-parameters.txt
--- 25/Documentation/kernel-parameters.txt~skip-apic-ids-on-boot	2003-06-26 18:38:18.000000000 -0700
+++ 25-akpm/Documentation/kernel-parameters.txt	2003-06-26 18:38:18.000000000 -0700
@@ -886,6 +886,10 @@ running once the system is up.
 			Format: <io>,<irq>,<dma>
 			See header of drivers/cdrom/sjcd.c.
 
+	skip_apicids=	[SMP]
+			Format: <apic1>[,<apic2>[,...,<apicN>]]
+			Do not boot cpus with matching apicid.
+
 	slram=		[HW,MTD]
 
 	smart2=		[HW]
diff -puN init/main.c~skip-apic-ids-on-boot init/main.c
--- 25/init/main.c~skip-apic-ids-on-boot	2003-06-26 18:38:18.000000000 -0700
+++ 25-akpm/init/main.c	2003-06-26 18:38:18.000000000 -0700
@@ -115,6 +115,8 @@ char *execute_command;
 
 /* Setup configured maximum number of CPUs to activate */
 static unsigned int max_cpus = NR_CPUS;
+/* Don't boot apicids in this list */
+int skip_apic_ids[NR_CPUS];
 
 /*
  * Setup routine for controlling SMP activation
@@ -142,6 +144,18 @@ static int __init maxcpus(char *str)
 
 __setup("maxcpus=", maxcpus);
 
+static int __init skip_apicids(char *str)
+{
+	int i;
+
+	get_options(str, NR_CPUS, skip_apic_ids);
+	for (i = 1; i < (skip_apic_ids[0]+1); i++)
+		printk( "CPU with apicid %i will not be booted\n", skip_apic_ids[i]);
+	return 1;
+}
+
+__setup("skip_apicids=", skip_apicids);
+
 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
 

_