1 /*
2 * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdbool.h>
8 #include <string.h>
9
10 #include <arch_helpers.h>
11 #include <context.h>
12 #include <lib/el3_runtime/context_mgmt.h>
13 #include <lib/psci/psci.h>
14 #include <lib/utils.h>
15 #include <plat/arm/common/plat_arm.h>
16 #include <smccc_helpers.h>
17
18 /*
19 * Handle SMC from a lower exception level to switch its execution state
20 * (either from AArch64 to AArch32, or vice versa).
21 *
22 * smc_fid:
23 * SMC function ID - either ARM_SIP_SVC_STATE_SWITCH_64 or
24 * ARM_SIP_SVC_STATE_SWITCH_32.
25 * pc_hi, pc_lo:
26 * PC upon re-entry to the calling exception level; width dependent on the
27 * calling exception level.
28 * cookie_hi, cookie_lo:
29 * Opaque pointer pairs received from the caller to pass it back, upon
30 * re-entry.
31 * handle:
32 * Handle to saved context.
33 */
arm_execution_state_switch(unsigned int smc_fid,uint32_t pc_hi,uint32_t pc_lo,uint32_t cookie_hi,uint32_t cookie_lo,void * handle)34 int arm_execution_state_switch(unsigned int smc_fid,
35 uint32_t pc_hi,
36 uint32_t pc_lo,
37 uint32_t cookie_hi,
38 uint32_t cookie_lo,
39 void *handle)
40 {
41 bool caller_64, thumb = false, from_el2;
42 unsigned int el, endianness;
43 u_register_t spsr, pc, scr, sctlr;
44 entry_point_info_t ep;
45 cpu_context_t *ctx = (cpu_context_t *) handle;
46 el3_state_t *el3_ctx = get_el3state_ctx(ctx);
47
48 /* Validate supplied entry point */
49 pc = (u_register_t) (((uint64_t) pc_hi << 32) | pc_lo);
50 if (arm_validate_ns_entrypoint(pc) != 0)
51 goto invalid_param;
52
53 /* That the SMC originated from NS is already validated by the caller */
54
55 /*
56 * Disallow state switch if any of the secondaries have been brought up.
57 */
58 if (psci_secondaries_brought_up() != 0)
59 goto exec_denied;
60
61 spsr = read_ctx_reg(el3_ctx, CTX_SPSR_EL3);
62 caller_64 = (GET_RW(spsr) == MODE_RW_64);
63
64 if (caller_64) {
65 /*
66 * If the call originated from AArch64, expect 32-bit pointers when
67 * switching to AArch32.
68 */
69 if ((pc_hi != 0U) || (cookie_hi != 0U))
70 goto invalid_param;
71
72 pc = pc_lo;
73
74 /* Instruction state when entering AArch32 */
75 thumb = (pc & 1U) != 0U;
76 } else {
77 /* Construct AArch64 PC */
78 pc = (((u_register_t) pc_hi) << 32) | pc_lo;
79 }
80
81 /* Make sure PC is 4-byte aligned, except for Thumb */
82 if (((pc & 0x3U) != 0U) && !thumb)
83 goto invalid_param;
84
85 /*
86 * EL3 controls register width of the immediate lower EL only. Expect
87 * this request from EL2/Hyp unless:
88 *
89 * - EL2 is not implemented;
90 * - EL2 is implemented, but was disabled. This can be inferred from
91 * SCR_EL3.HCE.
92 */
93 from_el2 = caller_64 ? (GET_EL(spsr) == MODE_EL2) :
94 (GET_M32(spsr) == MODE32_hyp);
95 scr = read_ctx_reg(el3_ctx, CTX_SCR_EL3);
96 if (!from_el2) {
97 /* The call is from NS privilege level other than HYP */
98
99 /*
100 * Disallow switching state if there's a Hypervisor in place;
101 * this request must be taken up with the Hypervisor instead.
102 */
103 if ((scr & SCR_HCE_BIT) != 0U)
104 goto exec_denied;
105 }
106
107 /*
108 * Return to the caller using the same endianness. Extract
109 * endianness bit from the respective system control register
110 * directly.
111 */
112 sctlr = from_el2 ? read_sctlr_el2() : read_sctlr_el1();
113 endianness = ((sctlr & SCTLR_EE_BIT) != 0U) ? 1U : 0U;
114
115 /* Construct SPSR for the exception state we're about to switch to */
116 if (caller_64) {
117 unsigned long long impl;
118
119 /*
120 * Switching from AArch64 to AArch32. Ensure this CPU implements
121 * the target EL in AArch32.
122 */
123 impl = from_el2 ? el_implemented(2) : el_implemented(1);
124 if (impl != EL_IMPL_A64_A32)
125 goto exec_denied;
126
127 /* Return to the equivalent AArch32 privilege level */
128 el = from_el2 ? MODE32_hyp : MODE32_svc;
129 spsr = SPSR_MODE32((u_register_t) el,
130 thumb ? SPSR_T_THUMB : SPSR_T_ARM,
131 endianness, DISABLE_ALL_EXCEPTIONS);
132 } else {
133 /*
134 * Switching from AArch32 to AArch64. Since it's not possible to
135 * implement an EL as AArch32-only (from which this call was
136 * raised), it's safe to assume AArch64 is also implemented.
137 */
138 el = from_el2 ? MODE_EL2 : MODE_EL1;
139 spsr = SPSR_64((u_register_t) el, MODE_SP_ELX,
140 DISABLE_ALL_EXCEPTIONS);
141 }
142
143 /*
144 * Use the context management library to re-initialize the existing
145 * context with the execution state flipped. Since the library takes
146 * entry_point_info_t pointer as the argument, construct a dummy one
147 * with PC, state width, endianness, security etc. appropriately set.
148 * Other entries in the entry point structure are irrelevant for
149 * purpose.
150 */
151 zeromem(&ep, sizeof(ep));
152 ep.pc = pc;
153 ep.spsr = (uint32_t) spsr;
154 SET_PARAM_HEAD(&ep, PARAM_EP, VERSION_1,
155 ((unsigned int) ((endianness != 0U) ? EP_EE_BIG :
156 EP_EE_LITTLE)
157 | NON_SECURE | EP_ST_DISABLE));
158
159 /*
160 * Re-initialize the system register context, and exit EL3 as if for the
161 * first time. State switch is effectively a soft reset of the
162 * calling EL.
163 */
164 cm_init_my_context(&ep);
165 cm_prepare_el3_exit(NON_SECURE);
166
167 /*
168 * State switch success. The caller of SMC wouldn't see the SMC
169 * returning. Instead, execution starts at the supplied entry point,
170 * with context pointers populated in registers 0 and 1.
171 */
172 SMC_RET2(handle, cookie_hi, cookie_lo);
173
174 invalid_param:
175 SMC_RET1(handle, STATE_SW_E_PARAM);
176
177 exec_denied:
178 /* State switch denied */
179 SMC_RET1(handle, STATE_SW_E_DENIED);
180 }
181