blob: 84f6b4bb84ca29f9bff2e6ec92f3cd1313952c64 [file] [log] [blame]
Brad Bishopbec4ebc2022-08-03 09:55:16 -04001From dbc1a218e9837e39cd50dd3c19f603f29a08ddba Mon Sep 17 00:00:00 2001
2From: Peter Hoyes <Peter.Hoyes@arm.com>
3Date: Wed, 14 Jul 2021 12:44:27 +0100
4Subject: [PATCH 4/9] armv8: ARMV8_SWITCH_TO_EL1 improvements
5
6Convert CONFIG_ARMV8_SWITCH_TO_EL1 to a Kconfig variable.
7
8Add support for switching to EL1 to bootefi.
9
10Add the environment variable armv8_switch_to_el1 to allow configuring
11whether to switch to EL1 at runtime. This overrides the compile-time
12option.
13
14Issue-Id: SCM-3728
15Upstream-Status: Inappropriate [other]
16 Implementation pending further discussion
17Signed-off-by: Peter Hoyes <Peter.Hoyes@arm.com>
18Change-Id: If98478148d6d8d1f732acac5439276700614815f
19---
20 arch/arm/cpu/armv8/Kconfig | 8 +++++++
21 arch/arm/cpu/armv8/exception_level.c | 21 ++++++++++++++--
22 arch/arm/lib/bootm.c | 36 ++++++++++++++++------------
23 configs/vexpress_aemv8r_defconfig | 1 +
24 4 files changed, 49 insertions(+), 17 deletions(-)
25
26diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
27index 031faa909c..110adf63b3 100644
28--- a/arch/arm/cpu/armv8/Kconfig
29+++ b/arch/arm/cpu/armv8/Kconfig
30@@ -191,4 +191,12 @@ config ARMV8_EA_EL3_FIRST
31 Exception handling at all exception levels for External Abort and
32 SError interrupt exception are taken in EL3.
33
34+config ARMV8_SWITCH_TO_EL1
35+ bool "Switch to EL1 before booting the operating system"
36+ default n
37+ help
38+ Switch to EL1 before booting the operating system, if for example the
39+ operating system does not support booting at EL2, or you wish to prevent
40+ any hypervisors from running. Supported for bootm, booti and bootefi.
41+
42 endif
43diff --git a/arch/arm/cpu/armv8/exception_level.c b/arch/arm/cpu/armv8/exception_level.c
44index b11936548f..4aad1550f4 100644
45--- a/arch/arm/cpu/armv8/exception_level.c
46+++ b/arch/arm/cpu/armv8/exception_level.c
47@@ -40,19 +40,36 @@ static void entry_non_secure(struct jmp_buf_data *non_secure_jmp)
48 * trusted firmware being one embodiment). The operating system shall be
49 * started at exception level EL2. So here we check the exception level
50 * and switch it if necessary.
51+ *
52+ * If armv8_switch_to_el1 (config or env var) is enabled, also switch to EL1
53+ * before booting the operating system.
54 */
55 void switch_to_non_secure_mode(void)
56 {
57 struct jmp_buf_data non_secure_jmp;
58
59 /* On AArch64 we need to make sure we call our payload in < EL3 */
60- if (current_el() == 3) {
61+
62+ int switch_to_el1 = env_get_yesno("armv8_switch_to_el1");
63+#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
64+ if (switch_to_el1 == -1) {
65+ switch_to_el1 = 1;
66+ }
67+#endif
68+
69+ if (current_el() > 2) {
70 if (setjmp(&non_secure_jmp))
71 return;
72 dcache_disable(); /* flush cache before switch to EL2 */
73-
74 /* Move into EL2 and keep running there */
75 armv8_switch_to_el2((uintptr_t)&non_secure_jmp, 0, 0, 0,
76 (uintptr_t)entry_non_secure, ES_TO_AARCH64);
77+ } else if (switch_to_el1 == 1 && current_el() > 1) {
78+ if (setjmp(&non_secure_jmp))
79+ return;
80+ dcache_disable(); /* flush cache before switch to EL1 */
81+ /* Move into EL1 and keep running there */
82+ armv8_switch_to_el1((uintptr_t)&non_secure_jmp, 0, 0, 0,
83+ (uintptr_t)entry_non_secure, ES_TO_AARCH64);
84 }
85 }
86diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
87index a59a5e6c0e..e2cf2e6ec4 100644
88--- a/arch/arm/lib/bootm.c
89+++ b/arch/arm/lib/bootm.c
90@@ -272,7 +272,6 @@ __weak void update_os_arch_secondary_cores(uint8_t os_arch)
91 {
92 }
93
94-#ifdef CONFIG_ARMV8_SWITCH_TO_EL1
95 static void switch_to_el1(void)
96 {
97 if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
98@@ -287,7 +286,6 @@ static void switch_to_el1(void)
99 ES_TO_AARCH64);
100 }
101 #endif
102-#endif
103
104 /* Subcommand: GO */
105 static void boot_jump_linux(bootm_headers_t *images, int flag)
106@@ -314,21 +312,29 @@ static void boot_jump_linux(bootm_headers_t *images, int flag)
107
108 update_os_arch_secondary_cores(images->os.arch);
109
110+ int armv8_switch_to_el1 = env_get_yesno("armv8_switch_to_el1");
111 #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
112- armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0,
113- (u64)switch_to_el1, ES_TO_AARCH64);
114-#else
115- if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
116- (images->os.arch == IH_ARCH_ARM))
117- armv8_switch_to_el2(0, (u64)gd->bd->bi_arch_number,
118- (u64)images->ft_addr, 0,
119- (u64)images->ep,
120- ES_TO_AARCH32);
121- else
122- armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0,
123- images->ep,
124- ES_TO_AARCH64);
125+ if (armv8_switch_to_el1 == -1) {
126+ armv8_switch_to_el1 = 1;
127+ }
128 #endif
129+ if (armv8_switch_to_el1 == 1) {
130+ armv8_switch_to_el2((u64)images->ft_addr, 0, 0, 0,
131+ (u64)switch_to_el1, ES_TO_AARCH64);
132+ } else {
133+ if ((IH_ARCH_DEFAULT == IH_ARCH_ARM64) &&
134+ (images->os.arch == IH_ARCH_ARM))
135+ armv8_switch_to_el2(0,
136+ (u64)gd->bd->bi_arch_number,
137+ (u64)images->ft_addr, 0,
138+ (u64)images->ep,
139+ ES_TO_AARCH32);
140+ else
141+ armv8_switch_to_el2((u64)images->ft_addr,
142+ 0, 0, 0,
143+ images->ep,
144+ ES_TO_AARCH64);
145+ }
146 }
147 #else
148 unsigned long machid = gd->bd->bi_arch_number;
149diff --git a/configs/vexpress_aemv8r_defconfig b/configs/vexpress_aemv8r_defconfig
150index 1d5b7411f0..35e5e8a5e1 100644
151--- a/configs/vexpress_aemv8r_defconfig
152+++ b/configs/vexpress_aemv8r_defconfig
153@@ -14,3 +14,4 @@ CONFIG_SYS_PROMPT="VExpress64# "
154 # CONFIG_MMC is not set
155 CONFIG_VIRTIO_MMIO=y
156 CONFIG_ARMV8_EXCEPTION_VECTORS=n
157+CONFIG_ARMV8_SWITCH_TO_EL1=y
158--
1592.25.1
160