aboutsummaryrefslogtreecommitdiffstats
path: root/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0008-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch
blob: 8cbd1f8c9cf02f3158987c6805215923b663e8cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
From 754c5109286e31741952309cb4e8438192511a3b 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 08/11] 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/Kconfig           |  8 +++++++
 arch/arm/cpu/armv8/exception_level.c | 21 ++++++++++++++--
 arch/arm/lib/bootm.c                 | 36 ++++++++++++++++------------
 scripts/config_whitelist.txt         |  1 -
 4 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/arch/arm/cpu/armv8/Kconfig b/arch/arm/cpu/armv8/Kconfig
index bd595095ab..d7de36acfe 100644
--- a/arch/arm/cpu/armv8/Kconfig
+++ b/arch/arm/cpu/armv8/Kconfig
@@ -177,4 +177,12 @@ config ARMV8_SECURE_BASE
 
 endif
 
+config ARMV8_SWITCH_TO_EL1
+	bool "Switch to EL1 before booting the operating system"
+	default n
+	help
+	  Switch to EL1 before booting the operating system, if for example the
+	  operating system does not support booting at EL2, or you wish to prevent
+	  any hypervisors from running. Supported for bootm, booti and bootefi.
+
 endif
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 a59a5e6c0e..e2cf2e6ec4 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -272,7 +272,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) &&
@@ -287,7 +286,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)
@@ -314,21 +312,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/scripts/config_whitelist.txt b/scripts/config_whitelist.txt
index b9c1c61e13..e6b5627447 100644
--- a/scripts/config_whitelist.txt
+++ b/scripts/config_whitelist.txt
@@ -21,7 +21,6 @@ CONFIG_ARC_MMU_VER
 CONFIG_ARMV7_SECURE_BASE
 CONFIG_ARMV7_SECURE_MAX_SIZE
 CONFIG_ARMV7_SECURE_RESERVE_SIZE
-CONFIG_ARMV8_SWITCH_TO_EL1
 CONFIG_ARM_GIC_BASE_ADDRESS
 CONFIG_ARP_TIMEOUT
 CONFIG_AT91C_PQFP_UHPBUG
-- 
2.25.1