Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e81d3b64 authored by Stepan Moskovchenko's avatar Stepan Moskovchenko
Browse files

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: default avatarStepan Moskovchenko <stepanm@codeaurora.org>
parent d21f97b7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -429,6 +429,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
			Format: <io>,<irq>,<mode>
			See header of drivers/net/hamradio/baycom_ser_hdx.c.

	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).
+35 −1
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@ struct call_single_queue {
	raw_spinlock_t		lock;
};

/* 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 DEFINE_PER_CPU_SHARED_ALIGNED(struct call_single_queue, call_single_queue);

static int
@@ -523,6 +527,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);
@@ -533,6 +550,21 @@ void __init setup_nr_cpu_ids(void)
	nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
}

/* 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)
{
@@ -544,10 +576,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 */
	printk(KERN_INFO "Brought up %ld CPUs\n", (long)num_online_cpus());
	smp_cpus_done(setup_max_cpus);