[PATCH 19/19] arm64: smp: Harden parallel CPU bringup against broken PSCI firmware

Will Deacon will at kernel.org
Tue Sep 8 06:36:39 PDT 2026


On Mon, Sep 07, 2026 at 05:40:22PM +0100, Will Deacon wrote:
> Since firmware has occasionally been known to get things wrong, harden
> our parallel CPU bringup code against a PSCI implementation that passes
> the CPU_ON argument to an incorrect CPU.
> 
> The primary CPU writes the MPIDR of the incoming CPU to the end of its
> task stack and this is then checked against the MPIDR_EL1 register
> during early kernel entry. A mismatch is reported via the existing
> failure reporting mechanism and the CPU is not brought online.
> 
> Suggested-by: David Woodhouse <dwmw at amazon.co.uk>
> Signed-off-by: Will Deacon <will at kernel.org>
> ---
>  arch/arm64/include/asm/smp.h    |  4 +++-
>  arch/arm64/kernel/asm-offsets.c |  1 +
>  arch/arm64/kernel/head.S        | 39 ++++++++++++++++++++++++++++-----
>  arch/arm64/kernel/smp.c         | 11 ++++++++--
>  4 files changed, 46 insertions(+), 9 deletions(-)

[...]

> diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
> index bec4bc1b12db..56deeb9673d6 100644
> --- a/arch/arm64/kernel/head.S
> +++ b/arch/arm64/kernel/head.S
> @@ -192,11 +192,21 @@ SYM_CODE_END(preserve_boot_args)
>  	 * its location in the task stack. We reserve the entire pt_regs space
>  	 * for consistency with user tasks and kthreads.
>  	 */
> -	.macro	init_cpu_task tsk, tmp1, tmp2
> +	.macro	init_cpu_task tsk, tmp1, tmp2, check_mpidr=
>  	msr	sp_el0, \tsk
>  
>  	ldr	\tmp1, [\tsk, #TSK_STACK]
> -	add	sp, \tmp1, #THREAD_SIZE
> +	mov	sp, \tmp1
> +	.ifnb	\check_mpidr
> +	mov_q	\tmp1, MPIDR_HWID_BITMASK
> +	mrs	\tmp2, mpidr_el1
> +	and	\tmp2, \tmp2, \tmp1
> +	ldr	\tmp1, [sp]
> +	sub	\tmp1, \tmp1, \tmp2
> +	cbnz	\tmp1, __cpu_secondary_broken_psci_arg
> +	.endif
> +
> +	add	sp, sp, #THREAD_SIZE
>  	sub	sp, sp, #PT_REGS_SIZE
>  
>  	stp	xzr, xzr, [sp, #S_STACKFRAME]
> @@ -401,11 +411,12 @@ SYM_FUNC_START_LOCAL(__secondary_switched)
>  	cbnz	x2, 1f
>  	adr_l	x0, secondary_data
>  	ldr	x2, [x0, #CPU_BOOT_TASK]
> -	cbz	x2, __secondary_too_slow
> -
> -1:
>  	init_cpu_task x2, x1, x3
> -
> +	cbnz	x2, 2f
> +	b	__secondary_too_slow

Bah, Sashiko points out that this is too late, as x2 has already been
dereferenced on the non-PSCI 0.2+ path. I'll rework this for v2.

Will



More information about the linux-arm-kernel mailing list