blob: 719eeb748df900d2855d10f0f38e8ddabf272f3a [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
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
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010035 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +020036 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
37
38 /* Program the entry point and enter OPTEE */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010039 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_off_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +020040 rc = opteed_synchronous_sp_entry(optee_ctx);
41
42 /*
43 * Read the response from OPTEE. A non-zero return means that
44 * something went wrong while communicating with OPTEE.
45 */
46 if (rc != 0)
47 panic();
48
49 /*
50 * Reset OPTEE's context for a fresh start when this cpu is turned on
51 * subsequently.
52 */
53 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF);
54
55 return 0;
56}
57
58/*******************************************************************************
59 * This cpu is being suspended. S-EL1 state must have been saved in the
60 * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
61 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090062static void opteed_cpu_suspend_handler(u_register_t max_off_pwrlvl)
Jens Wiklanderc2888862014-08-04 15:39:58 +020063{
64 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010065 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020066 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
67
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010068 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +020069 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
70
Jorge Ramirez-Ortizd3fb5242018-08-30 16:12:12 +020071 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), CTX_GPREG_X0,
72 max_off_pwrlvl);
73
Soby Mathewf5121572014-09-30 11:19:51 +010074 /* Program the entry point and enter OPTEE */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +010075 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_suspend_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +020076 rc = opteed_synchronous_sp_entry(optee_ctx);
77
78 /*
79 * Read the response from OPTEE. A non-zero return means that
80 * something went wrong while communicating with OPTEE.
81 */
82 if (rc != 0)
83 panic();
84
85 /* Update its context to reflect the state OPTEE is in */
86 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND);
87}
88
89/*******************************************************************************
90 * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits
91 * before passing control back to the Secure Monitor. Entry in S-El1 is done
92 * after initialising minimal architectural state that guarantees safe
93 * execution.
94 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +090095static void opteed_cpu_on_finish_handler(u_register_t unused)
Jens Wiklanderc2888862014-08-04 15:39:58 +020096{
97 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +010098 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +020099 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
100 entry_point_info_t optee_on_entrypoint;
101
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100102 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200103 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF);
104
105 opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100106 (uint64_t)&optee_vector_table->cpu_on_entry,
Jens Wiklanderce6cd162017-08-24 13:16:22 +0200107 0, 0, 0, optee_ctx);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200108
109 /* Initialise this cpu's secure context */
Soby Mathewda43b662015-07-08 21:45:46 +0100110 cm_init_my_context(&optee_on_entrypoint);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200111
112 /* Enter OPTEE */
113 rc = opteed_synchronous_sp_entry(optee_ctx);
114
115 /*
116 * Read the response from OPTEE. A non-zero return means that
117 * something went wrong while communicating with OPTEE.
118 */
119 if (rc != 0)
120 panic();
121
122 /* Update its context to reflect the state OPTEE is in */
123 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
124}
125
126/*******************************************************************************
127 * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it
128 * completed the preceding suspend call. Use that context to program an entry
129 * into OPTEE to allow it to do any remaining book keeping
130 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900131static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200132{
133 int32_t rc = 0;
Soby Mathewda43b662015-07-08 21:45:46 +0100134 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200135 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
136
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100137 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200138 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
139
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100140 /* Program the entry point, max_off_pwrlvl and enter the SP */
Jens Wiklanderc2888862014-08-04 15:39:58 +0200141 write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
142 CTX_GPREG_X0,
Achin Gupta9a0ff9b2015-09-07 20:43:27 +0100143 max_off_pwrlvl);
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100144 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_resume_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200145 rc = opteed_synchronous_sp_entry(optee_ctx);
146
147 /*
148 * Read the response from OPTEE. A non-zero return means that
149 * something went wrong while communicating with OPTEE.
150 */
151 if (rc != 0)
152 panic();
153
154 /* Update its context to reflect the state OPTEE is in */
155 set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
156}
157
158/*******************************************************************************
159 * Return the type of OPTEE the OPTEED is dealing with. Report the current
160 * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
161 ******************************************************************************/
Masahiro Yamada5ac9d962018-04-19 01:18:48 +0900162static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu)
Jens Wiklanderc2888862014-08-04 15:39:58 +0200163{
164 return OPTEE_MIGRATE_INFO;
165}
166
167/*******************************************************************************
168 * System is about to be switched off. Allow the OPTEED/OPTEE to perform
169 * any actions needed.
170 ******************************************************************************/
171static void opteed_system_off(void)
172{
Soby Mathewda43b662015-07-08 21:45:46 +0100173 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200174 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
175
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100176 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200177 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
178
179 /* Program the entry point */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100180 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_off_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200181
182 /* Enter OPTEE. We do not care about the return value because we
183 * must continue the shutdown anyway */
184 opteed_synchronous_sp_entry(optee_ctx);
185}
186
187/*******************************************************************************
188 * System is about to be reset. Allow the OPTEED/OPTEE to perform
189 * any actions needed.
190 ******************************************************************************/
191static void opteed_system_reset(void)
192{
Soby Mathewda43b662015-07-08 21:45:46 +0100193 uint32_t linear_id = plat_my_core_pos();
Jens Wiklanderc2888862014-08-04 15:39:58 +0200194 optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
195
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100196 assert(optee_vector_table);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200197 assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
198
199 /* Program the entry point */
Daniel Boulbyc5259cc2018-05-15 11:41:55 +0100200 cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_reset_entry);
Jens Wiklanderc2888862014-08-04 15:39:58 +0200201
202 /* Enter OPTEE. We do not care about the return value because we
203 * must continue the reset anyway */
204 opteed_synchronous_sp_entry(optee_ctx);
205}
206
207
208/*******************************************************************************
209 * Structure populated by the OPTEE Dispatcher to be given a chance to
210 * perform any OPTEE bookkeeping before PSCI executes a power mgmt.
211 * operation.
212 ******************************************************************************/
213const spd_pm_ops_t opteed_pm = {
214 .svc_on = opteed_cpu_on_handler,
215 .svc_off = opteed_cpu_off_handler,
216 .svc_suspend = opteed_cpu_suspend_handler,
217 .svc_on_finish = opteed_cpu_on_finish_handler,
218 .svc_suspend_finish = opteed_cpu_suspend_finish_handler,
219 .svc_migrate = NULL,
220 .svc_migrate_info = opteed_cpu_migrate_info,
221 .svc_system_off = opteed_system_off,
222 .svc_system_reset = opteed_system_reset,
223};