summaryrefslogtreecommitdiff
path: root/meta-arm/meta-arm-bsp/recipes-bsp/u-boot/u-boot/fvp-baser-aemv8r64/0004-armv8-ARMV8_SWITCH_TO_EL1-improvements.patch
blob: 81758fce711f969d8820b8ba6ce49ffe228df432 (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
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