Skip to content

Commit

Permalink
powerpc/pseries: Do not start secondaries in Open Firmware
Browse files Browse the repository at this point in the history
Starting secondary CPUs early on from Open Firmware and placing them
in a holding spin loop slows down the boot process significantly under
some hypervisors such as KVM.

This is also unnecessary when RTAS supports querying the CPU state

So let's not do it.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Benjamin Herrenschmidt committed Sep 25, 2013
1 parent 0c9fa29 commit dbe78b4
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 10 deletions.
21 changes: 21 additions & 0 deletions arch/powerpc/kernel/prom_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ static int __initdata mem_reserve_cnt;

static cell_t __initdata regbuf[1024];

static bool rtas_has_query_cpu_stopped;


/*
* Error results ... some OF calls will return "-1" on error, some
Expand Down Expand Up @@ -1574,6 +1576,11 @@ static void __init prom_instantiate_rtas(void)
prom_setprop(rtas_node, "/rtas", "linux,rtas-entry",
&val, sizeof(val));

/* Check if it supports "query-cpu-stopped-state" */
if (prom_getprop(rtas_node, "query-cpu-stopped-state",
&val, sizeof(val)) != PROM_ERROR)
rtas_has_query_cpu_stopped = true;

#if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__)
/* PowerVN takeover hack */
prom_rtas_data = base;
Expand Down Expand Up @@ -1815,6 +1822,18 @@ static void __init prom_hold_cpus(void)
= (void *) LOW_ADDR(__secondary_hold_acknowledge);
unsigned long secondary_hold = LOW_ADDR(__secondary_hold);

/*
* On pseries, if RTAS supports "query-cpu-stopped-state",
* we skip this stage, the CPUs will be started by the
* kernel using RTAS.
*/
if ((of_platform == PLATFORM_PSERIES ||
of_platform == PLATFORM_PSERIES_LPAR) &&
rtas_has_query_cpu_stopped) {
prom_printf("prom_hold_cpus: skipped\n");
return;
}

prom_debug("prom_hold_cpus: start...\n");
prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
Expand Down Expand Up @@ -3011,6 +3030,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* On non-powermacs, put all CPUs in spin-loops.
*
* PowerMacs use a different mechanism to spin CPUs
*
* (This must be done after instanciating RTAS)
*/
if (of_platform != PLATFORM_POWERMAC &&
of_platform != PLATFORM_OPAL)
Expand Down
26 changes: 16 additions & 10 deletions arch/powerpc/platforms/pseries/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,18 +233,24 @@ static void __init smp_init_pseries(void)

alloc_bootmem_cpumask_var(&of_spin_mask);

/* Mark threads which are still spinning in hold loops. */
if (cpu_has_feature(CPU_FTR_SMT)) {
for_each_present_cpu(i) {
if (cpu_thread_in_core(i) == 0)
cpumask_set_cpu(i, of_spin_mask);
}
} else {
cpumask_copy(of_spin_mask, cpu_present_mask);
/*
* Mark threads which are still spinning in hold loops
*
* We know prom_init will not have started them if RTAS supports
* query-cpu-stopped-state.
*/
if (rtas_token("query-cpu-stopped-state") == RTAS_UNKNOWN_SERVICE) {
if (cpu_has_feature(CPU_FTR_SMT)) {
for_each_present_cpu(i) {
if (cpu_thread_in_core(i) == 0)
cpumask_set_cpu(i, of_spin_mask);
}
} else
cpumask_copy(of_spin_mask, cpu_present_mask);

cpumask_clear_cpu(boot_cpuid, of_spin_mask);
}

cpumask_clear_cpu(boot_cpuid, of_spin_mask);

/* Non-lpar has additional take/give timebase */
if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) {
smp_ops->give_timebase = rtas_give_timebase;
Expand Down

0 comments on commit dbe78b4

Please sign in to comment.