aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2005-11-05 11:25:54 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-14 22:55:15 -0500
commit420f8f68c9c5148dddf946bebdbc7eacde2172cb (patch)
tree59cf49ac38e0c7560bb57d988869f67b1ff20342
parent485832a5d928facd82f1525270d9f048da2063a1 (diff)
[PATCH] x86_64: New heuristics to find out hotpluggable CPUs.
With a NR_CPUS==128 kernel with CPU hotplug enabled we would waste 4MB on per CPU data of all possible CPUs. The reason was that HOTPLUG always set up possible map to NR_CPUS cpus and then we need to allocate that much (each per CPU data is roughly ~32k now) The underlying problem is that ACPI didn't tell us how many hotplug CPUs the platform supports. So the old code just assumed all, which would lead to this memory wastage. This implements some new heuristics: - If the BIOS specified disabled CPUs in the ACPI/mptables assume they can be enabled later (this is bending the ACPI specification a bit, but seems like a obvious extension) - The user can overwrite it with a new additionals_cpus=NUM option - Otherwise use half of the available CPUs or 2, whatever is more. Cc: ashok.raj@intel.com Cc: len.brown@intel.com Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--Documentation/x86_64/boot-options.txt3
-rw-r--r--arch/x86_64/kernel/mpparse.c8
-rw-r--r--arch/x86_64/kernel/smpboot.c39
-rw-r--r--include/asm-x86_64/smp.h2
4 files changed, 47 insertions, 5 deletions
diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt
index ffe1c062088b..a83139692cdf 100644
--- a/Documentation/x86_64/boot-options.txt
+++ b/Documentation/x86_64/boot-options.txt
@@ -122,6 +122,9 @@ SMP
122 122
123 cpumask=MASK only use cpus with bits set in mask 123 cpumask=MASK only use cpus with bits set in mask
124 124
125 additional_cpus=NUM Allow NUM more CPUs for hotplug
126 (defaults are specified by the BIOS or half the available CPUs)
127
125NUMA 128NUMA
126 129
127 numa=off Only set up a single NUMA node spanning all memory. 130 numa=off Only set up a single NUMA node spanning all memory.
diff --git a/arch/x86_64/kernel/mpparse.c b/arch/x86_64/kernel/mpparse.c
index 4a581d1cefbd..1d61f10a92c6 100644
--- a/arch/x86_64/kernel/mpparse.c
+++ b/arch/x86_64/kernel/mpparse.c
@@ -65,7 +65,9 @@ unsigned long mp_lapic_addr = 0;
65/* Processor that is doing the boot up */ 65/* Processor that is doing the boot up */
66unsigned int boot_cpu_id = -1U; 66unsigned int boot_cpu_id = -1U;
67/* Internal processor count */ 67/* Internal processor count */
68static unsigned int num_processors = 0; 68unsigned int num_processors __initdata = 0;
69
70unsigned disabled_cpus __initdata;
69 71
70/* Bitmask of physically existing CPUs */ 72/* Bitmask of physically existing CPUs */
71physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE; 73physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE;
@@ -109,8 +111,10 @@ static void __init MP_processor_info (struct mpc_config_processor *m)
109 int ver, cpu; 111 int ver, cpu;
110 static int found_bsp=0; 112 static int found_bsp=0;
111 113
112 if (!(m->mpc_cpuflag & CPU_ENABLED)) 114 if (!(m->mpc_cpuflag & CPU_ENABLED)) {
115 disabled_cpus++;
113 return; 116 return;
117 }
114 118
115 printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n", 119 printk(KERN_INFO "Processor #%d %d:%d APIC version %d\n",
116 m->mpc_apicid, 120 m->mpc_apicid,
diff --git a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c
index 3393fc08823b..f74319a80659 100644
--- a/arch/x86_64/kernel/smpboot.c
+++ b/arch/x86_64/kernel/smpboot.c
@@ -880,6 +880,9 @@ static __init void disable_smp(void)
880} 880}
881 881
882#ifdef CONFIG_HOTPLUG_CPU 882#ifdef CONFIG_HOTPLUG_CPU
883
884int additional_cpus __initdata = -1;
885
883/* 886/*
884 * cpu_possible_map should be static, it cannot change as cpu's 887 * cpu_possible_map should be static, it cannot change as cpu's
885 * are onlined, or offlined. The reason is per-cpu data-structures 888 * are onlined, or offlined. The reason is per-cpu data-structures
@@ -888,14 +891,38 @@ static __init void disable_smp(void)
888 * cpu_present_map on the other hand can change dynamically. 891 * cpu_present_map on the other hand can change dynamically.
889 * In case when cpu_hotplug is not compiled, then we resort to current 892 * In case when cpu_hotplug is not compiled, then we resort to current
890 * behaviour, which is cpu_possible == cpu_present. 893 * behaviour, which is cpu_possible == cpu_present.
891 * If cpu-hotplug is supported, then we need to preallocate for all
892 * those NR_CPUS, hence cpu_possible_map represents entire NR_CPUS range.
893 * - Ashok Raj 894 * - Ashok Raj
895 *
896 * Three ways to find out the number of additional hotplug CPUs:
897 * - If the BIOS specified disabled CPUs in ACPI/mptables use that.
898 * - otherwise use half of the available CPUs or 2, whatever is more.
899 * - The user can overwrite it with additional_cpus=NUM
900 * We do this because additional CPUs waste a lot of memory.
901 * -AK
894 */ 902 */
895__init void prefill_possible_map(void) 903__init void prefill_possible_map(void)
896{ 904{
897 int i; 905 int i;
898 for (i = 0; i < NR_CPUS; i++) 906 int possible;
907
908 if (additional_cpus == -1) {
909 if (disabled_cpus > 0) {
910 additional_cpus = disabled_cpus;
911 } else {
912 additional_cpus = num_processors / 2;
913 if (additional_cpus == 0)
914 additional_cpus = 2;
915 }
916 }
917 possible = num_processors + additional_cpus;
918 if (possible > NR_CPUS)
919 possible = NR_CPUS;
920
921 printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
922 possible,
923 max_t(int, possible - num_processors, 0));
924
925 for (i = 0; i < possible; i++)
899 cpu_set(i, cpu_possible_map); 926 cpu_set(i, cpu_possible_map);
900} 927}
901#endif 928#endif
@@ -1151,6 +1178,12 @@ void __cpu_die(unsigned int cpu)
1151 printk(KERN_ERR "CPU %u didn't die...\n", cpu); 1178 printk(KERN_ERR "CPU %u didn't die...\n", cpu);
1152} 1179}
1153 1180
1181static __init int setup_additional_cpus(char *s)
1182{
1183 return get_option(&s, &additional_cpus);
1184}
1185__setup("additional_cpus=", setup_additional_cpus);
1186
1154#else /* ... !CONFIG_HOTPLUG_CPU */ 1187#else /* ... !CONFIG_HOTPLUG_CPU */
1155 1188
1156int __cpu_disable(void) 1189int __cpu_disable(void)
diff --git a/include/asm-x86_64/smp.h b/include/asm-x86_64/smp.h
index 592161e979e5..cf8f969f9020 100644
--- a/include/asm-x86_64/smp.h
+++ b/include/asm-x86_64/smp.h
@@ -81,6 +81,8 @@ extern int safe_smp_processor_id(void);
81extern int __cpu_disable(void); 81extern int __cpu_disable(void);
82extern void __cpu_die(unsigned int cpu); 82extern void __cpu_die(unsigned int cpu);
83extern void prefill_possible_map(void); 83extern void prefill_possible_map(void);
84extern unsigned num_processors;
85extern unsigned disabled_cpus;
84 86
85#endif /* !ASSEMBLY */ 87#endif /* !ASSEMBLY */
86 88