blob: 81758fce711f969d8820b8ba6ce49ffe228df432 [file] [log] [blame]
From 30405f59881c73946b6b0ffdbf25804f9fbf1585 Mon Sep 17 00:00:00 2001
From: Peter Hoyes <Peter.Hoyes@arm.com>
Date: Wed, 14 Jul 2021 12:44:27 +0100
Subject: [PATCH 4/9] armv8: ARMV8_SWITCH_TO_EL1 improvements
Convert CONFIG_ARMV8_SWITCH_TO_EL1 to a Kconfig variable.
Add support for switching to EL1 to bootefi.
Add the environment variable armv8_switch_to_el1 to allow configuring
whether to switch to EL1 at runtime. This overrides the compile-time
option.
Issue-Id: SCM-3728
Upstream-Status: Inappropriate [other]
Implementation pending further discussion
Signed-off-by: Peter Hoyes <Peter.Hoyes@arm.com>
Change-Id: If98478148d6d8d1f732acac5439276700614815f
---
arch/arm/cpu/armv8/exception_level.c | 21 ++++++++++++++--
arch/arm/lib/bootm.c | 36 ++++++++++++++++------------
configs/vexpress_aemv8r_defconfig | 1 +
3 files changed, 41 insertions(+), 17 deletions(-)
diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c
index b11936548f..4aad1550f4 100644
--- a/arch/arm/cpu/armv8/exception_level.c
+++ b/arch/arm/cpu/armv8/exception_level.c
@@ -40,19 +40,36 @@ static void entry_non_secure(struct jmp_buf_data *non_secure_jmp)
* trusted firmware being one embodiment). The operating system shall be
* started at exception level EL2. So here we check the exception level
* and switch it if necessary.
+ *
+ * If armv8_switch_to_el1 (config or env var) is enabled, also switch to EL1
+ * before booting the operating system.
*/
void switch_to_non_secure_mode(void)
{
struct jmp_buf_data non_secure_jmp;
/* On AArch64 we need to make sure we call our payload in < EL3 */
- if (current_el() == 3) {
+
+ int switch_to_el1 = env_get_yesno("armv8_switch_to_el1");
+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
+ if (switch_to_el1 == -1) {
+ switch_to_el1 = 1;
+ }
+#endif
+
+ if (current_el() > 2) {
if (setjmp(&non_secure_jmp))
return;
dcache_disable(); /* flush cache before switch to EL2 */
-
/* Move into EL2 and keep running there */
armv8_switch_to_el2((uintptr_t)&non_secure_jmp, 0, 0, 0,
(uintptr_t)entry_non_secure, ES_TO_AARCH64);
+ } else if (switch_to_el1 == 1 && current_el() > 1) {
+ if (setjmp(&non_secure_jmp))
+ return;
+ dcache_disable(); /* flush cache before switch to EL1 */
+ /* Move into EL1 and keep running there */
+ armv8_switch_to_el1((uintptr_t)&non_secure_jmp, 0, 0, 0,
+ (uintptr_t)entry_non_secure, ES_TO_AARCH64);
}
}
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 9f086f3b90..b044aeca88 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -270,7 +270,6 @@ __weak void update_os_arch_secondary_cores(uint8_t os_arch)
{
}
-#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
static void switch_to_el1(void)
{
if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
@@ -285,7 +284,6 @@ static void switch_to_el1(void)
ES_TO_AARCH64);
}
#endif
-#endif
/* Subcommand: GO */
static void boot_jump_linux(bootm_headers_t *images, int flag)
@@ -312,21 +310,29 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
update_os_arch_secondary_cores(images->os.arch);
+ int armv8_switch_to_el1 = env_get_yesno("armv8_switch_to_el1");
#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
- armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0,
- (u64)switch_to_el1, ES_TO_AARCH64);
-#else
- if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
- (images->os.arch == IH_ARCH_ARM))
- armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number,
- (u64)images->ft_addr, 0,
- (u64)images->ep,
- ES_TO_AARCH32);
- else
- armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0,
- images->ep,
- ES_TO_AARCH64);
+ if (armv8_switch_to_el1 == -1) {
+ armv8_switch_to_el1 = 1;
+ }
#endif
+ if (armv8_switch_to_el1 == 1) {
+ armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0,
+ (u64)switch_to_el1, ES_TO_AARCH64);
+ } else {
+ if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
+ (images->os.arch == IH_ARCH_ARM))
+ armv8_switch_to_el2(0,
+ (u64)gd->bd->bi_arch_number,
+ (u64)images->ft_addr, 0,
+ (u64)images->ep,
+ ES_TO_AARCH32);
+ else
+ armv8_switch_to_el2((u64)images->ft_addr,
+ 0, 0, 0,
+ images->ep,
+ ES_TO_AARCH64);
+ }
}
#else
unsigned long machid = gd->bd->bi_arch_number;
diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig
index 683d983c36..6044f82b00 100644
--- a/configs/vexpress_aemv8r_defconfig
+++ b/configs/vexpress_aemv8r_defconfig
@@ -17,3 +17,4 @@ CONFIG_SYS_PBSIZE=541
# CONFIG_MMC is not set
CONFIG_VIRTIO_MMIO=y
CONFIG_ARMV8_EXCEPTION_VECTORS=n
+CONFIG_ARMV8_SWITCH_TO_EL1=y
--
2.25.1