Add support for exiting Gunyah hypervisor and switching to EL2 during early boot. This is required for platforms that boot U-Boot in a hypervisor guest environment where U-Boot needs to run at EL2 to enable other hypervisors like KVM.
The switch is performed via TrustZone SMC call before EL register configuration in start.S. The implementation: - Checks current exception level and only executes at EL1 - Uses TrustZone SMC to exit Gunyah and transition to EL2 - Integrates with existing boot0.h workaround infrastructure A new Kconfig option CONFIG_QCOM_EL2_GUNYAH_EXIT_SUPPORT enables this functionality. Signed-off-by: Aswin Murugan <[email protected]> --- Change in v3: - Corrected the logic to accurately detect the current Exception Level (EL) and fuction properly when U-Boot enters either EL2 or EL1. Link to v2: https://lore.kernel.org/u-boot/[email protected]/ Change in v2: - EL2 switch is made at early stage instead of doing at the very last stage in the previous version - This change is based on the patch [1] [1] https://lore.kernel.org/all/[email protected]/ Link to v1: https://lore.kernel.org/u-boot/[email protected]/ --- arch/arm/mach-snapdragon/Kconfig | 7 ++++ arch/arm/mach-snapdragon/include/mach/boot0.h | 3 ++ .../include/mach/gunyah_exit_boot0.h | 35 +++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 arch/arm/mach-snapdragon/include/mach/gunyah_exit_boot0.h diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index f863daf6bb9..931d25c1023 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -56,6 +56,13 @@ config BOOT0_MSM8916_PSCI_WORKAROUND help Select this if you are building U-Boot proper for an msm8916 board that uses the buggy PSCI implementation. + +config QCOM_EL2_GUNYAH_EXIT_SUPPORT + bool "Enable early EL2 switch by exiting Gunyah" + help + Exit Gunyah hypervisor and switch to EL2 during early boot. This must + happen before EL register configuration in start.S so that U-Boot can + run properly at EL2. endchoice endif diff --git a/arch/arm/mach-snapdragon/include/mach/boot0.h b/arch/arm/mach-snapdragon/include/mach/boot0.h index b3c76d6d97d..032a9fbdb12 100644 --- a/arch/arm/mach-snapdragon/include/mach/boot0.h +++ b/arch/arm/mach-snapdragon/include/mach/boot0.h @@ -1,9 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0+ */ + #if defined(CONFIG_SPL_BUILD) b reset #else #if defined(CONFIG_BOOT0_MSM8916_PSCI_WORKAROUND) #include "msm8916_boot0.h" +#elif defined(CONFIG_QCOM_EL2_GUNYAH_EXIT_SUPPORT) +#include "gunyah_exit_boot0.h" #else b reset #endif diff --git a/arch/arm/mach-snapdragon/include/mach/gunyah_exit_boot0.h b/arch/arm/mach-snapdragon/include/mach/gunyah_exit_boot0.h new file mode 100644 index 00000000000..5c5bd3b6691 --- /dev/null +++ b/arch/arm/mach-snapdragon/include/mach/gunyah_exit_boot0.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Early Gunyah Hypervisor Exit + * + * Exit Gunyah hypervisor and switch to EL2 during early boot. This must + * happen before EL register configuration in start.S so that U-Boot can + * run properly at EL2. + */ + +#include <asm/macro.h> +#include <linux/arm-smccc.h> + +/* TrustZone SMC IDs for hypervisor configuration */ +#define TZ_EL2_SWITCH_SMC_ID 0x02000121 +#define TZ_EL2_SWITCH_PARAM_ID 0x00000023 +#define TZ_EL2_SWITCH_PARAM2_EXIT_GUNYAH 0x1 + + /* Only perform hypervisor switch if we're at EL1 */ + switch_el x9, 3f, 2f, 1f + + /* Save FDT address before we modify x0 */ +1: mov x9, x0 + + /* Switch to EL2 (exit Gunyah) */ + ldr w0, =TZ_EL2_SWITCH_SMC_ID + ldr w1, =TZ_EL2_SWITCH_PARAM_ID + mov w2, wzr + mov w3, wzr + ldr w4, =TZ_EL2_SWITCH_PARAM2_EXIT_GUNYAH + smc #0 + + /* Restore FDT address */ + mov x0, x9 +2: +3: b reset -- 2.34.1

