aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/alternative.c16
-rw-r--r--include/linux/smp.h2
-rw-r--r--init/main.c16
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};
274static LIST_HEAD(smp_alt_modules); 274static LIST_HEAD(smp_alt_modules);
275static DEFINE_SPINLOCK(smp_alt); 275static DEFINE_SPINLOCK(smp_alt);
276static int smp_mode = 1; /* protected by smp_alt */
276 277
277void alternatives_smp_module_add(struct module *mod, char *name, 278void 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 */
79void smp_prepare_boot_cpu(void); 79void smp_prepare_boot_cpu(void);
80 80
81extern 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 */
131static unsigned int __initdata max_cpus = NR_CPUS; 131unsigned 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
147static int __init nosmp(char *str) 147static 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
156static int __init maxcpus(char *str) 156static 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
165early_param("maxcpus", maxcpus); 165early_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