• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
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  ******************************************************************************/
opteed_cpu_on_handler(uint64_t target_cpu)19 static void opteed_cpu_on_handler(uint64_t target_cpu)
20 {
21 }
22 
23 /*******************************************************************************
24  * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions
25  * needed
26  ******************************************************************************/
opteed_cpu_off_handler(uint64_t unused)27 static int32_t opteed_cpu_off_handler(uint64_t unused)
28 {
29 	int32_t rc = 0;
30 	uint32_t linear_id = plat_my_core_pos();
31 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
32 
33 	assert(optee_vectors);
34 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
35 
36 	/* Program the entry point and enter OPTEE */
37 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_off_entry);
38 	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  ******************************************************************************/
opteed_cpu_suspend_handler(uint64_t max_off_pwrlvl)60 static void opteed_cpu_suspend_handler(uint64_t max_off_pwrlvl)
61 {
62 	int32_t rc = 0;
63 	uint32_t linear_id = plat_my_core_pos();
64 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
65 
66 	assert(optee_vectors);
67 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
68 
69 	/* Program the entry point and enter OPTEE */
70 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_suspend_entry);
71 	rc = opteed_synchronous_sp_entry(optee_ctx);
72 
73 	/*
74 	 * Read the response from OPTEE. A non-zero return means that
75 	 * something went wrong while communicating with OPTEE.
76 	 */
77 	if (rc != 0)
78 		panic();
79 
80 	/* Update its context to reflect the state OPTEE is in */
81 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND);
82 }
83 
84 /*******************************************************************************
85  * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits
86  * before passing control back to the Secure Monitor. Entry in S-El1 is done
87  * after initialising minimal architectural state that guarantees safe
88  * execution.
89  ******************************************************************************/
opteed_cpu_on_finish_handler(uint64_t unused)90 static void opteed_cpu_on_finish_handler(uint64_t unused)
91 {
92 	int32_t rc = 0;
93 	uint32_t linear_id = plat_my_core_pos();
94 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
95 	entry_point_info_t optee_on_entrypoint;
96 
97 	assert(optee_vectors);
98 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF);
99 
100 	opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw,
101 				(uint64_t)&optee_vectors->cpu_on_entry,
102 				0, 0, 0, optee_ctx);
103 
104 	/* Initialise this cpu's secure context */
105 	cm_init_my_context(&optee_on_entrypoint);
106 
107 	/* Enter OPTEE */
108 	rc = opteed_synchronous_sp_entry(optee_ctx);
109 
110 	/*
111 	 * Read the response from OPTEE. A non-zero return means that
112 	 * something went wrong while communicating with OPTEE.
113 	 */
114 	if (rc != 0)
115 		panic();
116 
117 	/* Update its context to reflect the state OPTEE is in */
118 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
119 }
120 
121 /*******************************************************************************
122  * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it
123  * completed the preceding suspend call. Use that context to program an entry
124  * into OPTEE to allow it to do any remaining book keeping
125  ******************************************************************************/
opteed_cpu_suspend_finish_handler(uint64_t max_off_pwrlvl)126 static void opteed_cpu_suspend_finish_handler(uint64_t max_off_pwrlvl)
127 {
128 	int32_t rc = 0;
129 	uint32_t linear_id = plat_my_core_pos();
130 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
131 
132 	assert(optee_vectors);
133 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND);
134 
135 	/* Program the entry point, max_off_pwrlvl and enter the SP */
136 	write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx),
137 		      CTX_GPREG_X0,
138 		      max_off_pwrlvl);
139 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->cpu_resume_entry);
140 	rc = opteed_synchronous_sp_entry(optee_ctx);
141 
142 	/*
143 	 * Read the response from OPTEE. A non-zero return means that
144 	 * something went wrong while communicating with OPTEE.
145 	 */
146 	if (rc != 0)
147 		panic();
148 
149 	/* Update its context to reflect the state OPTEE is in */
150 	set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON);
151 }
152 
153 /*******************************************************************************
154  * Return the type of OPTEE the OPTEED is dealing with. Report the current
155  * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE.
156  ******************************************************************************/
opteed_cpu_migrate_info(uint64_t * resident_cpu)157 static int32_t opteed_cpu_migrate_info(uint64_t *resident_cpu)
158 {
159 	return OPTEE_MIGRATE_INFO;
160 }
161 
162 /*******************************************************************************
163  * System is about to be switched off. Allow the OPTEED/OPTEE to perform
164  * any actions needed.
165  ******************************************************************************/
opteed_system_off(void)166 static void opteed_system_off(void)
167 {
168 	uint32_t linear_id = plat_my_core_pos();
169 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
170 
171 	assert(optee_vectors);
172 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
173 
174 	/* Program the entry point */
175 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_off_entry);
176 
177 	/* Enter OPTEE. We do not care about the return value because we
178 	 * must continue the shutdown anyway */
179 	opteed_synchronous_sp_entry(optee_ctx);
180 }
181 
182 /*******************************************************************************
183  * System is about to be reset. Allow the OPTEED/OPTEE to perform
184  * any actions needed.
185  ******************************************************************************/
opteed_system_reset(void)186 static void opteed_system_reset(void)
187 {
188 	uint32_t linear_id = plat_my_core_pos();
189 	optee_context_t *optee_ctx = &opteed_sp_context[linear_id];
190 
191 	assert(optee_vectors);
192 	assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON);
193 
194 	/* Program the entry point */
195 	cm_set_elr_el3(SECURE, (uint64_t) &optee_vectors->system_reset_entry);
196 
197 	/* Enter OPTEE. We do not care about the return value because we
198 	 * must continue the reset anyway */
199 	opteed_synchronous_sp_entry(optee_ctx);
200 }
201 
202 
203 /*******************************************************************************
204  * Structure populated by the OPTEE Dispatcher to be given a chance to
205  * perform any OPTEE bookkeeping before PSCI executes a power mgmt.
206  * operation.
207  ******************************************************************************/
208 const spd_pm_ops_t opteed_pm = {
209 	.svc_on = opteed_cpu_on_handler,
210 	.svc_off = opteed_cpu_off_handler,
211 	.svc_suspend = opteed_cpu_suspend_handler,
212 	.svc_on_finish = opteed_cpu_on_finish_handler,
213 	.svc_suspend_finish = opteed_cpu_suspend_finish_handler,
214 	.svc_migrate = NULL,
215 	.svc_migrate_info = opteed_cpu_migrate_info,
216 	.svc_system_off = opteed_system_off,
217 	.svc_system_reset = opteed_system_reset,
218 };
219