diff options
author | Andi Kleen <ak@suse.de> | 2005-11-05 11:25:54 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-14 22:55:15 -0500 |
commit | 420f8f68c9c5148dddf946bebdbc7eacde2172cb (patch) | |
tree | 59cf49ac38e0c7560bb57d988869f67b1ff20342 /arch/x86_64 | |
parent | 485832a5d928facd82f1525270d9f048da2063a1 (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>
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/mpparse.c | 8 | ||||
-rw-r--r-- | arch/x86_64/kernel/smpboot.c | 39 |
2 files changed, 42 insertions, 5 deletions
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 */ |
66 | unsigned int boot_cpu_id = -1U; | 66 | unsigned int boot_cpu_id = -1U; |
67 | /* Internal processor count */ | 67 | /* Internal processor count */ |
68 | static unsigned int num_processors = 0; | 68 | unsigned int num_processors __initdata = 0; |
69 | |||
70 | unsigned disabled_cpus __initdata; | ||
69 | 71 | ||
70 | /* Bitmask of physically existing CPUs */ | 72 | /* Bitmask of physically existing CPUs */ |
71 | physid_mask_t phys_cpu_present_map = PHYSID_MASK_NONE; | 73 | physid_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 | |||
884 | int 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 | ||
1181 | static __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 | ||
1156 | int __cpu_disable(void) | 1189 | int __cpu_disable(void) |