summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--kernel/smp.c35
2 files changed, 38 insertions, 1 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 742f69d18fc8..6834ace0c778 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -548,6 +548,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
embedded devices based on command line input.
See Documentation/block/cmdline-partition.txt
+ boot_cpus= [SMP]
+ Rather than attempting to online all possible CPUs at
+ boot time, only online the specified set of CPUs.
+
boot_delay= Milliseconds to delay each printk during boot.
Values larger than 10 seconds (10000) are changed to
no delay (0).
diff --git a/kernel/smp.c b/kernel/smp.c
index d903c02223af..abdc48cd79a3 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -32,6 +32,9 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data);
static DEFINE_PER_CPU_SHARED_ALIGNED(struct llist_head, call_single_queue);
static void flush_smp_call_function_queue(bool warn_cpu_offline);
+/* CPU mask indicating which CPUs to bring online during smp_init() */
+static bool have_boot_cpu_mask;
+static cpumask_var_t boot_cpu_mask;
static int
hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu)
@@ -548,6 +551,19 @@ static int __init maxcpus(char *str)
early_param("maxcpus", maxcpus);
+static int __init boot_cpus(char *str)
+{
+ alloc_bootmem_cpumask_var(&boot_cpu_mask);
+ if (cpulist_parse(str, boot_cpu_mask) < 0) {
+ pr_warn("SMP: Incorrect boot_cpus cpumask\n");
+ return -EINVAL;
+ }
+ have_boot_cpu_mask = true;
+ return 0;
+}
+
+early_param("boot_cpus", boot_cpus);
+
/* Setup number of possible processor ids */
int nr_cpu_ids __read_mostly = NR_CPUS;
EXPORT_SYMBOL(nr_cpu_ids);
@@ -563,6 +579,21 @@ void __weak smp_announce(void)
printk(KERN_INFO "Brought up %d CPUs\n", num_online_cpus());
}
+/* Should the given CPU be booted during smp_init() ? */
+static inline bool boot_cpu(int cpu)
+{
+ if (!have_boot_cpu_mask)
+ return true;
+
+ return cpumask_test_cpu(cpu, boot_cpu_mask);
+}
+
+static inline void free_boot_cpu_mask(void)
+{
+ if (have_boot_cpu_mask) /* Allocated from boot_cpus() */
+ free_bootmem_cpumask_var(boot_cpu_mask);
+}
+
/* Called by boot processor to activate the rest. */
void __init smp_init(void)
{
@@ -574,10 +605,12 @@ void __init smp_init(void)
for_each_present_cpu(cpu) {
if (num_online_cpus() >= setup_max_cpus)
break;
- if (!cpu_online(cpu))
+ if (!cpu_online(cpu) && boot_cpu(cpu))
cpu_up(cpu);
}
+ free_boot_cpu_mask();
+
/* Any cleanup work */
smp_announce();
smp_cpus_done(setup_max_cpus);