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

Commit b69e0dc1 authored by James Morse's avatar James Morse Committed by Catalin Marinas
Browse files

arm64: smp: Add function to determine if cpus are stuck in the kernel



kernel/smp.c has a fancy counter that keeps track of the number of CPUs
it marked as not-present and left in cpu_park_loop(). If there are any
CPUs spinning in here, features like kexec or hibernate may release them
by overwriting this memory.

This problem also occurs on machines using spin-tables to release
secondary cores.
After commit 44dbcc93 ("arm64: Fix behavior of maxcpus=N")
we bring all known cpus into the secondary holding pen, meaning this
memory can't be re-used by kexec or hibernate.

Add a function cpus_are_stuck_in_kernel() to determine if either of these
cases have occurred.

Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Acked-by: default avatarMark Rutland <mark.rutland@arm.com>
Reviewed-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
[catalin.marinas@arm.com: cherry-picked from mainline for kexec dependency]
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent d770b5a0
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -124,6 +124,18 @@ static inline void cpu_panic_kernel(void)
	cpu_park_loop();
}

/*
 * If a secondary CPU enters the kernel but fails to come online,
 * (e.g. due to mismatched features), and cannot exit the kernel,
 * we increment cpus_stuck_in_kernel and leave the CPU in a
 * quiesecent loop within the kernel text. The memory containing
 * this loop must not be re-used for anything else as the 'stuck'
 * core is executing it.
 *
 * This function is used to inhibit features like kexec and hibernate.
 */
bool cpus_are_stuck_in_kernel(void);

#endif /* ifndef __ASSEMBLY__ */

#endif /* ifndef __ASM_SMP_H */
+18 −0
Original line number Diff line number Diff line
@@ -909,3 +909,21 @@ int setup_profiling_timer(unsigned int multiplier)
{
	return -EINVAL;
}

static bool have_cpu_die(void)
{
#ifdef CONFIG_HOTPLUG_CPU
	int any_cpu = raw_smp_processor_id();

	if (cpu_ops[any_cpu]->cpu_die)
		return true;
#endif
	return false;
}

bool cpus_are_stuck_in_kernel(void)
{
	bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die());

	return !!cpus_stuck_in_kernel || smp_spin_tables;
}