On QCS8275 (Monaco) the boot firmware enters U-Boot on a Cortex-A78C core. The Cortex-A78C cores have pointer authentication and the Cortex-A55 cores do not, and Linux only brings up CPUs that match its boot CPU in that respect, so booting it from a Cortex-A78C leaves the four Cortex-A55 cores offline.
Add BOOT0_QCOM_BOOT_CPU. On any CPU other than QCOM_BOOT_CPU_MPIDR it powers that CPU on at _start with PSCI CPU_ON, passing x0 on as the context ID, and turns the entering CPU off. If CPU_ON fails, U-Boot carries on where it was entered. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Tyler Baker <[email protected]> --- arch/arm/mach-snapdragon/Kconfig | 21 ++++++++++++++ arch/arm/mach-snapdragon/include/mach/boot0.h | 2 ++ .../mach-snapdragon/include/mach/boot_cpu_boot0.h | 33 ++++++++++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index ddded0029e..6770f5070a 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -80,6 +80,27 @@ config BOOT0_SDM845_WORKAROUND help Select this if you are building U-Boot SPL for sdm845. +config BOOT0_QCOM_BOOT_CPU + bool "boot0.h hook to run U-Boot on a selected CPU" + help + At entry, if U-Boot runs on any CPU other than the one given by + QCOM_BOOT_CPU_MPIDR, power that CPU on at the U-Boot entry point + with PSCI CPU_ON and turn the entering CPU off, so U-Boot and the OS + it boots run on the selected CPU. PSCI is called through SMC. + + On QCS8275 (Monaco) the boot firmware enters on a Cortex-A78C core, + which has pointer authentication, while the Cortex-A55 cores do not. + Linux only brings up CPUs that match its boot CPU's pointer + authentication support, so it has to boot on a Cortex-A55. + endchoice +config QCOM_BOOT_CPU_MPIDR + hex "MPIDR affinity of the CPU to run U-Boot on" + depends on BOOT0_QCOM_BOOT_CPU + default 0x0 + help + Affinity fields (Aff3..Aff0) of the MPIDR of the CPU that U-Boot moves + to at entry. + endif diff --git a/arch/arm/mach-snapdragon/include/mach/boot0.h b/arch/arm/mach-snapdragon/include/mach/boot0.h index b71aab37f4..2f6b724fe8 100644 --- a/arch/arm/mach-snapdragon/include/mach/boot0.h +++ b/arch/arm/mach-snapdragon/include/mach/boot0.h @@ -8,6 +8,8 @@ #else #if defined(CONFIG_BOOT0_MSM8916_PSCI_WORKAROUND) #include "msm8916_boot0.h" +#elif defined(CONFIG_BOOT0_QCOM_BOOT_CPU) +#include "boot_cpu_boot0.h" #else b reset #endif diff --git a/arch/arm/mach-snapdragon/include/mach/boot_cpu_boot0.h b/arch/arm/mach-snapdragon/include/mach/boot_cpu_boot0.h new file mode 100644 index 0000000000..0b9cc0bd58 --- /dev/null +++ b/arch/arm/mach-snapdragon/include/mach/boot_cpu_boot0.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Move the boot to the CPU selected by CONFIG_QCOM_BOOT_CPU_MPIDR: power it + * on at _start with PSCI CPU_ON (over SMC), passing x0 on as the context ID, + * then power the entering CPU off. On SoCs with mixed CPU types the boot + * firmware may enter U-Boot on a CPU the OS cannot boot from. + */ +#include <asm/psci.h> + + mrs x9, mpidr_el1 + ldr x10, =0xff00ffffff /* Aff3..Aff0 */ + and x9, x9, x10 + ldr x1, =CONFIG_QCOM_BOOT_CPU_MPIDR + cmp x9, x1 + b.eq reset + + mov x9, x0 + adr x2, _start + mov x3, x9 + ldr x0, =ARM_PSCI_0_2_FN64_CPU_ON + smc #0 + cbnz x0, 2f + + /* U-Boot now runs on the selected CPU; this one must not go on. */ + ldr x0, =ARM_PSCI_0_2_FN_CPU_OFF + smc #0 +1: wfi + b 1b + + /* CPU_ON failed: stay on this CPU. */ +2: mov x0, x9 + b reset + .ltorg -- 2.47.3
