blob: c949823ed3dd4f12eda2d91ebe3c01d37fcdaa1a [file] [log] [blame]
Jens Wiklanderc2888862014-08-04 15:39:58 +02001/*
Raymond Mao5fe9abb2023-10-04 09:36:21 -07002 * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
Jens Wiklanderc2888862014-08-04 15:39:58 +02003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Jens Wiklanderc2888862014-08-04 15:39:58 +02005 */
6
Jens Wiklanderc2888862014-08-04 15:39:58 +02007#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
9#include <arch_helpers.h>
10#include <common/bl_common.h>
11#include <common/debug.h>
12#include <lib/el3_runtime/context_mgmt.h>
13#include <plat/common/platform.h>
14
Jens Wiklanderc2888862014-08-04 15:39:58 +020015#include "opteed_private.h"
16
17/*******************************************************************************
18 * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any
19 * actions needed. Nothing at the moment.
20 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090021static void opteed_cpu_on_handler(u_register_t target_cpu)
Jens Wiklanderc2888862014-08-04 15:39:58 +020022{
23}
24
25/*******************************************************************************
26 * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
27 * needed
28 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090029static int32_t opteed_cpu_off_handler(u_register_t unused)
Jens Wiklanderc2888862014-08-04 15:39:58 +020030{
31 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010032 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020033 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
34
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -070035 if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
36 return 0;
37 }
38
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010039 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +020040 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
41
42 /* Program the entry point and enter OPTEE */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010043 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_off_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +020044 rc = opteed_synchronous_sp_entry(optee_ctx);
45
46 /*
47 * Read the response from OPTEE. A non-zero return means that
48 * something went wrong while communicating with OPTEE.
49 */
50 if (rc != 0)
51 panic();
52
53 /*
54 * Reset OPTEE's context for a fresh start when this cpu is turned on
55 * subsequently.
56 */
57 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF);
58
59 return 0;
60}
61
62/*******************************************************************************
63 * This cpu is being suspended. S-EL1 state must have been saved in the
64 * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
65 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090066static void opteed_cpu_suspend_handler(u_register_t max_off_pwrlvl)
Jens Wiklanderc2888862014-08-04 15:39:58 +020067{
68 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010069 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020070 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
71
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -070072 if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
73 return;
74 }
75
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010076 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +020077 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
78
Jorge Ramirez-Ortizd3fb5242018-08-30 16:12:12 +020079 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), CTX_GPREG_X0,
80 max_off_pwrlvl);
81
Soby Mathewf5121572014-09-30 11:19:51 +010082 /* Program the entry point and enter OPTEE */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010083 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_suspend_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +020084 rc = opteed_synchronous_sp_entry(optee_ctx);
85
86 /*
87 * Read the response from OPTEE. A non-zero return means that
88 * something went wrong while communicating with OPTEE.
89 */
90 if (rc != 0)
91 panic();
92
93 /* Update its context to reflect the state OPTEE is in */
94 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND);
95}
96
97/*******************************************************************************
98 * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits
99 * before passing control back to the Secure Monitor. Entry in S-El1 is done
100 * after initialising minimal architectural state that guarantees safe
101 * execution.
102 ******************************************************************************/
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700103void opteed_cpu_on_finish_handler(u_register_t unused)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200104{
105 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100106 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200107 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
108 entry_point_info_t optee_on_entrypoint;
109
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100110 assert(optee_vector_table);
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700111 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF ||
112 get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200113
114 opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100115 (uint64_t)&optee_vector_table->cpu_on_entry,
Raymond Mao5fe9abb2023-10-04 09:36:21 -0700116 0, 0, 0, 0, optee_ctx);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200117
118 /* Initialise this cpu's secure context */
Soby Mathewda43b662015-07-08 21:45:46 +0100119 cm_init_my_context(&optee_on_entrypoint);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200120
121 /* Enter OPTEE */
122 rc = opteed_synchronous_sp_entry(optee_ctx);
123
124 /*
125 * Read the response from OPTEE. A non-zero return means that
126 * something went wrong while communicating with OPTEE.
127 */
128 if (rc != 0)
129 panic();
130
131 /* Update its context to reflect the state OPTEE is in */
132 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
133}
134
135/*******************************************************************************
136 * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it
137 * completed the preceding suspend call. Use that context to program an entry
138 * into OPTEE to allow it to do any remaining book keeping
139 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900140static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200141{
142 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100143 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200144 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
145
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700146 if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
147 return;
148 }
149
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100150 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200151 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
152
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100153 /* Program the entry point, max_off_pwrlvl and enter the SP */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200154 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
155 CTX_GPREG_X0,
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100156 max_off_pwrlvl);
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100157 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_resume_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200158 rc = opteed_synchronous_sp_entry(optee_ctx);
159
160 /*
161 * Read the response from OPTEE. A non-zero return means that
162 * something went wrong while communicating with OPTEE.
163 */
164 if (rc != 0)
165 panic();
166
167 /* Update its context to reflect the state OPTEE is in */
168 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
169}
170
171/*******************************************************************************
172 * Return the type of OPTEE the OPTEED is dealing with. Report the current
173 * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
174 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900175static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200176{
177 return OPTEE_MIGRATE_INFO;
178}
179
180/*******************************************************************************
181 * System is about to be switched off. Allow the OPTEED/OPTEE to perform
182 * any actions needed.
183 ******************************************************************************/
184static void opteed_system_off(void)
185{
Soby Mathewda43b662015-07-08 21:45:46 +0100186 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200187 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
188
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700189 /*
190 * OP-TEE must have been initialized in order to reach this location so
191 * it is safe to init the CPU context if not already done for this core.
192 */
193 if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
194 opteed_cpu_on_finish_handler(0);
195 }
196
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100197 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200198 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
199
200 /* Program the entry point */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100201 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_off_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200202
203 /* Enter OPTEE. We do not care about the return value because we
204 * must continue the shutdown anyway */
205 opteed_synchronous_sp_entry(optee_ctx);
206}
207
208/*******************************************************************************
209 * System is about to be reset. Allow the OPTEED/OPTEE to perform
210 * any actions needed.
211 ******************************************************************************/
212static void opteed_system_reset(void)
213{
Soby Mathewda43b662015-07-08 21:45:46 +0100214 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200215 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
216
Jeffrey Kardatzke7e6b09a2022-10-03 15:50:21 -0700217 /*
218 * OP-TEE must have been initialized in order to reach this location so
219 * it is safe to init the CPU context if not already done for this core.
220 */
221 if (get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_UNKNOWN) {
222 opteed_cpu_on_finish_handler(0);
223 }
224
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100225 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200226 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
227
228 /* Program the entry point */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100229 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_reset_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200230
231 /* Enter OPTEE. We do not care about the return value because we
232 * must continue the reset anyway */
233 opteed_synchronous_sp_entry(optee_ctx);
234}
235
236
237/*******************************************************************************
238 * Structure populated by the OPTEE Dispatcher to be given a chance to
239 * perform any OPTEE bookkeeping before PSCI executes a power mgmt.
240 * operation.
241 ******************************************************************************/
242const spd_pm_ops_t opteed_pm = {
243 .svc_on = opteed_cpu_on_handler,
244 .svc_off = opteed_cpu_off_handler,
245 .svc_suspend = opteed_cpu_suspend_handler,
246 .svc_on_finish = opteed_cpu_on_finish_handler,
247 .svc_suspend_finish = opteed_cpu_suspend_finish_handler,
248 .svc_migrate = NULL,
249 .svc_migrate_info = opteed_cpu_migrate_info,
250 .svc_system_off = opteed_system_off,
251 .svc_system_reset = opteed_system_reset,
252};