77#include <kernel_internal.h>
88#include "vector_table.h"
99
10+ void z_arm64_el2_init (void );
11+
1012void __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+
3963void 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
69101void 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