blob: b1336517e7e1b9b14870bb69e4a0784e569cdcf1 [file] [log] [blame]
Jens Wiklanderc2888862014-08-04 15:39:58 +02001/*
Edison Ai5d685d32017-07-18 16:52:26 +08002 * Copyright (c) 2013-2017, 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
7#include <arch_helpers.h>
8#include <assert.h>
9#include <bl_common.h>
10#include <context_mgmt.h>
11#include <debug.h>
12#include <platform.h>
13#include "opteed_private.h"
14
15/*******************************************************************************
16 * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any
17 * actions needed. Nothing at the moment.
18 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090019static void opteed_cpu_on_handler(u_register_t target_cpu)
Jens Wiklanderc2888862014-08-04 15:39:58 +020020{
21}
22
23/*******************************************************************************
24 * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
25 * needed
26 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090027static int32_t opteed_cpu_off_handler(u_register_t unused)
Jens Wiklanderc2888862014-08-04 15:39:58 +020028{
29 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010030 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020031 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
32
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010033 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +020034 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
35
36 /* Program the entry point and enter OPTEE */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010037 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_off_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +020038 rc = opteed_synchronous_sp_entry(optee_ctx);
39
40 /*
41 * Read the response from OPTEE. A non-zero return means that
42 * something went wrong while communicating with OPTEE.
43 */
44 if (rc != 0)
45 panic();
46
47 /*
48 * Reset OPTEE's context for a fresh start when this cpu is turned on
49 * subsequently.
50 */
51 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF);
52
53 return 0;
54}
55
56/*******************************************************************************
57 * This cpu is being suspended. S-EL1 state must have been saved in the
58 * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
59 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090060static void opteed_cpu_suspend_handler(u_register_t max_off_pwrlvl)
Jens Wiklanderc2888862014-08-04 15:39:58 +020061{
62 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010063 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020064 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
65
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010066 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +020067 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
68
Jorge Ramirez-Ortizd3fb5242018-08-30 16:12:12 +020069 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), CTX_GPREG_X0,
70 max_off_pwrlvl);
71
Soby Mathewf5121572014-09-30 11:19:51 +010072 /* Program the entry point and enter OPTEE */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010073 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_suspend_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +020074 rc = opteed_synchronous_sp_entry(optee_ctx);
75
76 /*
77 * Read the response from OPTEE. A non-zero return means that
78 * something went wrong while communicating with OPTEE.
79 */
80 if (rc != 0)
81 panic();
82
83 /* Update its context to reflect the state OPTEE is in */
84 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND);
85}
86
87/*******************************************************************************
88 * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits
89 * before passing control back to the Secure Monitor. Entry in S-El1 is done
90 * after initialising minimal architectural state that guarantees safe
91 * execution.
92 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090093static void opteed_cpu_on_finish_handler(u_register_t unused)
Jens Wiklanderc2888862014-08-04 15:39:58 +020094{
95 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010096 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020097 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
98 entry_point_info_t optee_on_entrypoint;
99
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100100 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200101 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF);
102
103 opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100104 (uint64_t)&optee_vector_table->cpu_on_entry,
Jens Wiklanderce6cd162017-08-24 13:16:22 +0200105 0, 0, 0, optee_ctx);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200106
107 /* Initialise this cpu's secure context */
Soby Mathewda43b662015-07-08 21:45:46 +0100108 cm_init_my_context(&optee_on_entrypoint);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200109
110 /* Enter OPTEE */
111 rc = opteed_synchronous_sp_entry(optee_ctx);
112
113 /*
114 * Read the response from OPTEE. A non-zero return means that
115 * something went wrong while communicating with OPTEE.
116 */
117 if (rc != 0)
118 panic();
119
120 /* Update its context to reflect the state OPTEE is in */
121 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
122}
123
124/*******************************************************************************
125 * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it
126 * completed the preceding suspend call. Use that context to program an entry
127 * into OPTEE to allow it to do any remaining book keeping
128 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900129static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200130{
131 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100132 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200133 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
134
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100135 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200136 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
137
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100138 /* Program the entry point, max_off_pwrlvl and enter the SP */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200139 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
140 CTX_GPREG_X0,
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100141 max_off_pwrlvl);
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100142 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_resume_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200143 rc = opteed_synchronous_sp_entry(optee_ctx);
144
145 /*
146 * Read the response from OPTEE. A non-zero return means that
147 * something went wrong while communicating with OPTEE.
148 */
149 if (rc != 0)
150 panic();
151
152 /* Update its context to reflect the state OPTEE is in */
153 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
154}
155
156/*******************************************************************************
157 * Return the type of OPTEE the OPTEED is dealing with. Report the current
158 * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
159 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900160static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200161{
162 return OPTEE_MIGRATE_INFO;
163}
164
165/*******************************************************************************
166 * System is about to be switched off. Allow the OPTEED/OPTEE to perform
167 * any actions needed.
168 ******************************************************************************/
169static void opteed_system_off(void)
170{
Soby Mathewda43b662015-07-08 21:45:46 +0100171 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200172 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
173
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100174 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200175 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
176
177 /* Program the entry point */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100178 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_off_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200179
180 /* Enter OPTEE. We do not care about the return value because we
181 * must continue the shutdown anyway */
182 opteed_synchronous_sp_entry(optee_ctx);
183}
184
185/*******************************************************************************
186 * System is about to be reset. Allow the OPTEED/OPTEE to perform
187 * any actions needed.
188 ******************************************************************************/
189static void opteed_system_reset(void)
190{
Soby Mathewda43b662015-07-08 21:45:46 +0100191 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200192 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
193
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100194 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200195 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
196
197 /* Program the entry point */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100198 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_reset_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200199
200 /* Enter OPTEE. We do not care about the return value because we
201 * must continue the reset anyway */
202 opteed_synchronous_sp_entry(optee_ctx);
203}
204
205
206/*******************************************************************************
207 * Structure populated by the OPTEE Dispatcher to be given a chance to
208 * perform any OPTEE bookkeeping before PSCI executes a power mgmt.
209 * operation.
210 ******************************************************************************/
211const spd_pm_ops_t opteed_pm = {
212 .svc_on = opteed_cpu_on_handler,
213 .svc_off = opteed_cpu_off_handler,
214 .svc_suspend = opteed_cpu_suspend_handler,
215 .svc_on_finish = opteed_cpu_on_finish_handler,
216 .svc_suspend_finish = opteed_cpu_suspend_finish_handler,
217 .svc_migrate = NULL,
218 .svc_migrate_info = opteed_cpu_migrate_info,
219 .svc_system_off = opteed_system_off,
220 .svc_system_reset = opteed_system_reset,
221};