diff options
-rw-r--r-- | arch/x86/kernel/alternative.c | 16 | ||||
-rw-r--r-- | include/linux/smp.h | 2 | ||||
-rw-r--r-- | init/main.c | 16 |
3 files changed, 24 insertions, 10 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index cdc43242da92..318a4f9b7ece 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -273,6 +273,7 @@ struct smp_alt_module { | |||
273 | }; | 273 | }; |
274 | static LIST_HEAD(smp_alt_modules); | 274 | static LIST_HEAD(smp_alt_modules); |
275 | static DEFINE_SPINLOCK(smp_alt); | 275 | static DEFINE_SPINLOCK(smp_alt); |
276 | static int smp_mode = 1; /* protected by smp_alt */ | ||
276 | 277 | ||
277 | void alternatives_smp_module_add(struct module *mod, char *name, | 278 | void alternatives_smp_module_add(struct module *mod, char *name, |
278 | void *locks, void *locks_end, | 279 | void *locks, void *locks_end, |
@@ -354,7 +355,14 @@ void alternatives_smp_switch(int smp) | |||
354 | BUG_ON(!smp && (num_online_cpus() > 1)); | 355 | BUG_ON(!smp && (num_online_cpus() > 1)); |
355 | 356 | ||
356 | spin_lock_irqsave(&smp_alt, flags); | 357 | spin_lock_irqsave(&smp_alt, flags); |
357 | if (smp) { | 358 | |
359 | /* | ||
360 | * Avoid unnecessary switches because it forces JIT based VMs to | ||
361 | * throw away all cached translations, which can be quite costly. | ||
362 | */ | ||
363 | if (smp == smp_mode) { | ||
364 | /* nothing */ | ||
365 | } else if (smp) { | ||
358 | printk(KERN_INFO "SMP alternatives: switching to SMP code\n"); | 366 | printk(KERN_INFO "SMP alternatives: switching to SMP code\n"); |
359 | clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); | 367 | clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP); |
360 | clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP); | 368 | clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP); |
@@ -369,6 +377,7 @@ void alternatives_smp_switch(int smp) | |||
369 | alternatives_smp_unlock(mod->locks, mod->locks_end, | 377 | alternatives_smp_unlock(mod->locks, mod->locks_end, |
370 | mod->text, mod->text_end); | 378 | mod->text, mod->text_end); |
371 | } | 379 | } |
380 | smp_mode = smp; | ||
372 | spin_unlock_irqrestore(&smp_alt, flags); | 381 | spin_unlock_irqrestore(&smp_alt, flags); |
373 | } | 382 | } |
374 | 383 | ||
@@ -441,7 +450,10 @@ void __init alternative_instructions(void) | |||
441 | alternatives_smp_module_add(NULL, "core kernel", | 450 | alternatives_smp_module_add(NULL, "core kernel", |
442 | __smp_locks, __smp_locks_end, | 451 | __smp_locks, __smp_locks_end, |
443 | _text, _etext); | 452 | _text, _etext); |
444 | alternatives_smp_switch(0); | 453 | |
454 | /* Only switch to UP mode if we don't immediately boot others */ | ||
455 | if (num_possible_cpus() == 1 || setup_max_cpus <= 1) | ||
456 | alternatives_smp_switch(0); | ||
445 | } | 457 | } |
446 | #endif | 458 | #endif |
447 | apply_paravirt(__parainstructions, __parainstructions_end); | 459 | apply_paravirt(__parainstructions, __parainstructions_end); |
diff --git a/include/linux/smp.h b/include/linux/smp.h index c25e66bcecf3..55232ccf9cfd 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h | |||
@@ -78,6 +78,8 @@ int on_each_cpu(void (*func) (void *info), void *info, int retry, int wait); | |||
78 | */ | 78 | */ |
79 | void smp_prepare_boot_cpu(void); | 79 | void smp_prepare_boot_cpu(void); |
80 | 80 | ||
81 | extern unsigned int setup_max_cpus; | ||
82 | |||
81 | #else /* !SMP */ | 83 | #else /* !SMP */ |
82 | 84 | ||
83 | /* | 85 | /* |
diff --git a/init/main.c b/init/main.c index 3f8aba291ed3..5843fe996703 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -128,7 +128,7 @@ static char *ramdisk_execute_command; | |||
128 | 128 | ||
129 | #ifdef CONFIG_SMP | 129 | #ifdef CONFIG_SMP |
130 | /* Setup configured maximum number of CPUs to activate */ | 130 | /* Setup configured maximum number of CPUs to activate */ |
131 | static unsigned int __initdata max_cpus = NR_CPUS; | 131 | unsigned int __initdata setup_max_cpus = NR_CPUS; |
132 | 132 | ||
133 | /* | 133 | /* |
134 | * Setup routine for controlling SMP activation | 134 | * Setup routine for controlling SMP activation |
@@ -146,7 +146,7 @@ static inline void disable_ioapic_setup(void) {}; | |||
146 | 146 | ||
147 | static int __init nosmp(char *str) | 147 | static int __init nosmp(char *str) |
148 | { | 148 | { |
149 | max_cpus = 0; | 149 | setup_max_cpus = 0; |
150 | disable_ioapic_setup(); | 150 | disable_ioapic_setup(); |
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
@@ -155,8 +155,8 @@ early_param("nosmp", nosmp); | |||
155 | 155 | ||
156 | static int __init maxcpus(char *str) | 156 | static int __init maxcpus(char *str) |
157 | { | 157 | { |
158 | get_option(&str, &max_cpus); | 158 | get_option(&str, &setup_max_cpus); |
159 | if (max_cpus == 0) | 159 | if (setup_max_cpus == 0) |
160 | disable_ioapic_setup(); | 160 | disable_ioapic_setup(); |
161 | 161 | ||
162 | return 0; | 162 | return 0; |
@@ -164,7 +164,7 @@ static int __init maxcpus(char *str) | |||
164 | 164 | ||
165 | early_param("maxcpus", maxcpus); | 165 | early_param("maxcpus", maxcpus); |
166 | #else | 166 | #else |
167 | #define max_cpus NR_CPUS | 167 | #define setup_max_cpus NR_CPUS |
168 | #endif | 168 | #endif |
169 | 169 | ||
170 | /* | 170 | /* |
@@ -393,7 +393,7 @@ static void __init smp_init(void) | |||
393 | 393 | ||
394 | /* FIXME: This should be done in userspace --RR */ | 394 | /* FIXME: This should be done in userspace --RR */ |
395 | for_each_present_cpu(cpu) { | 395 | for_each_present_cpu(cpu) { |
396 | if (num_online_cpus() >= max_cpus) | 396 | if (num_online_cpus() >= setup_max_cpus) |
397 | break; | 397 | break; |
398 | if (!cpu_online(cpu)) | 398 | if (!cpu_online(cpu)) |
399 | cpu_up(cpu); | 399 | cpu_up(cpu); |
@@ -401,7 +401,7 @@ static void __init smp_init(void) | |||
401 | 401 | ||
402 | /* Any cleanup work */ | 402 | /* Any cleanup work */ |
403 | printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus()); | 403 | printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus()); |
404 | smp_cpus_done(max_cpus); | 404 | smp_cpus_done(setup_max_cpus); |
405 | } | 405 | } |
406 | 406 | ||
407 | #endif | 407 | #endif |
@@ -824,7 +824,7 @@ static int __init kernel_init(void * unused) | |||
824 | __set_special_pids(1, 1); | 824 | __set_special_pids(1, 1); |
825 | cad_pid = task_pid(current); | 825 | cad_pid = task_pid(current); |
826 | 826 | ||
827 | smp_prepare_cpus(max_cpus); | 827 | smp_prepare_cpus(setup_max_cpus); |
828 | 828 | ||
829 | do_pre_smp_initcalls(); | 829 | do_pre_smp_initcalls(); |
830 | 830 | ||