Skip to content

Commit a88cf70

Browse files
James MorseAKASHI Takahiro
authored andcommitted
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 44dbcc93ab67 ("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: James Morse <james.morse@arm.com> Acked-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Conflicts: arch/arm64/include/asm/smp.h due to missing commit 17eebd1a435c ("arm64: Add cpu_panic_kernel helper")
1 parent 4a9d7e3 commit a88cf70

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

arch/arm64/include/asm/smp.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,18 @@ static inline void update_cpu_boot_status(int val)
113113
dsb(ishst);
114114
}
115115

116+
/*
117+
* If a secondary CPU enters the kernel but fails to come online,
118+
* (e.g. due to mismatched features), and cannot exit the kernel,
119+
* we increment cpus_stuck_in_kernel and leave the CPU in a
120+
* quiesecent loop within the kernel text. The memory containing
121+
* this loop must not be re-used for anything else as the 'stuck'
122+
* core is executing it.
123+
*
124+
* This function is used to inhibit features like kexec and hibernate.
125+
*/
126+
bool cpus_are_stuck_in_kernel(void);
127+
116128
#endif /* ifndef __ASSEMBLY__ */
117129

118130
#endif /* ifndef __ASM_SMP_H */

arch/arm64/kernel/smp.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,3 +890,21 @@ int setup_profiling_timer(unsigned int multiplier)
890890
{
891891
return -EINVAL;
892892
}
893+
894+
static bool have_cpu_die(void)
895+
{
896+
#ifdef CONFIG_HOTPLUG_CPU
897+
int any_cpu = raw_smp_processor_id();
898+
899+
if (cpu_ops[any_cpu]->cpu_die)
900+
return true;
901+
#endif
902+
return false;
903+
}
904+
905+
bool cpus_are_stuck_in_kernel(void)
906+
{
907+
bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die());
908+
909+
return !!cpus_stuck_in_kernel || smp_spin_tables;
910+
}

0 commit comments

Comments
 (0)