Skip to content

Commit 4e1926d

Browse files
jharris-intelnashif
authored andcommitted
arch: aarch64: do EL2 init in EL3 if necessary
If EL2 is implemented but we're skipping EL2, we should still do EL2 init. Otherwise we end up with a bunch of things still at their (unknown) reset values. This in particular causes problems when different cores have different virtual timer offsets. Signed-off-by: James Harris <[email protected]>
1 parent de707b6 commit 4e1926d

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

arch/arm/core/aarch64/reset.c

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <kernel_internal.h>
88
#include "vector_table.h"
99

10+
void z_arm64_el2_init(void);
11+
1012
void __weak z_arm64_el_highest_plat_init(void)
1113
{
1214
/* do nothing */
@@ -36,6 +38,28 @@ void z_arm64_el_highest_init(void)
3638
isb();
3739
}
3840

41+
enum el3_next_el {
42+
EL3_TO_EL2,
43+
EL3_TO_EL1_NO_EL2,
44+
EL3_TO_EL1_SKIP_EL2
45+
};
46+
47+
static inline enum el3_next_el el3_get_next_el(void)
48+
{
49+
if (!is_el_implemented(2)) {
50+
return EL3_TO_EL1_NO_EL2;
51+
} else if (is_in_secure_state() && !is_el2_sec_supported()) {
52+
/*
53+
* Is considered an illegal return "[..] a return to EL2 when EL3 is
54+
* implemented and the value of the SCR_EL3.NS bit is 0 if
55+
* ARMv8.4-SecEL2 is not implemented" (D1.11.2 from ARM DDI 0487E.a)
56+
*/
57+
return EL3_TO_EL1_SKIP_EL2;
58+
} else {
59+
return EL3_TO_EL2;
60+
}
61+
}
62+
3963
void z_arm64_el3_init(void)
4064
{
4165
uint64_t reg;
@@ -64,6 +88,14 @@ void z_arm64_el3_init(void)
6488
z_arm64_el3_plat_init();
6589

6690
isb();
91+
92+
if (el3_get_next_el() == EL3_TO_EL1_SKIP_EL2) {
93+
/*
94+
* handle EL2 init in EL3, as it still needs to be done,
95+
* but we are going to be skipping EL2.
96+
*/
97+
z_arm64_el2_init();
98+
}
6799
}
68100

69101
void z_arm64_el2_init(void)
@@ -89,6 +121,10 @@ void z_arm64_el2_init(void)
89121
zero_cntvoff_el2(); /* Set 64-bit virtual timer offset to 0 */
90122
zero_cnthctl_el2();
91123
zero_cnthp_ctl_el2();
124+
/*
125+
* Enable this if/when we use the hypervisor timer.
126+
* write_cnthp_cval_el2(~(uint64_t)0);
127+
*/
92128

93129
z_arm64_el2_plat_init();
94130

@@ -114,6 +150,13 @@ void z_arm64_el1_init(void)
114150
SCTLR_SA_BIT); /* Enable SP alignment check */
115151
write_sctlr_el1(reg);
116152

153+
write_cntv_cval_el0(~(uint64_t)0);
154+
/*
155+
* Enable these if/when we use the corresponding timers.
156+
* write_cntp_cval_el0(~(uint64_t)0);
157+
* write_cntps_cval_el1(~(uint64_t)0);
158+
*/
159+
117160
z_arm64_el1_plat_init();
118161

119162
isb();
@@ -128,13 +171,7 @@ void z_arm64_el3_get_next_el(uint64_t switch_addr)
128171
/* Mask the DAIF */
129172
spsr = SPSR_DAIF_MASK;
130173

131-
/*
132-
* Is considered an illegal return "[..] a return to EL2 when EL3 is
133-
* implemented and the value of the SCR_EL3.NS bit is 0 if
134-
* ARMv8.4-SecEL2 is not implemented" (D1.11.2 from ARM DDI 0487E.a)
135-
*/
136-
if (is_el_implemented(2) &&
137-
((is_in_secure_state() && is_el2_sec_supported()) || !is_in_secure_state())) {
174+
if (el3_get_next_el() == EL3_TO_EL2) {
138175
/* Dropping into EL2 */
139176
spsr |= SPSR_MODE_EL2T;
140177
} else {

0 commit comments

Comments
 (0)