summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorStepan Moskovchenko <stepanm@codeaurora.org>2014-05-19 19:07:33 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:07:48 -0700
commit1ca3decb1bb5ecc4b84e49f35424ec89cfc52b48 (patch)
treea9bfcfe4e5762fdaedb9efab65a02f532d4541a0 /kernel
parent77228fba61416c8ca65dd41818f916eaa39d1773 (diff)
smp: Allow booting a specific subset of CPUs
In a heterogenous multiprocessor system, specifying the 'maxcpus' parameter on the kernel command line does not provide sufficient control over which CPUs are brought online at kernel boot time, since CPUs may have nonuniform performance characteristics. Thus, we introduce a 'boot_cpus' command line argument, allowing the user to explicitly specify the list of CPUs that shall be brought online during kernel boot. Change-Id: I5f119e23202660941fa7be8c4e6dd91a82365451 Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org> [abhimany: resolve trivial merge conflicts] Signed-off-by: Abhimanyu Kapur <abhimany@codeaurora.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/smp.c35
1 files changed, 34 insertions, 1 deletions
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);