blob: e0fe494be4ad016065926ec02a9ebf44305f23f8 [file] [log] [blame]
Antonio Nino Diazc41f2062017-10-24 10:07:35 +01001/*
Antonio Nino Diaz35b37f02018-01-08 17:33:34 +00002 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <assert.h>
9#include <bl31.h>
10#include <context_mgmt.h>
11#include <debug.h>
12#include <errno.h>
Antonio Nino Diaz35b37f02018-01-08 17:33:34 +000013#include <mm_svc.h>
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010014#include <platform.h>
15#include <runtime_svc.h>
16#include <secure_partition.h>
Antonio Nino Diaz3c817f42018-03-21 10:49:27 +000017#include <smccc.h>
18#include <smccc_helpers.h>
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010019#include <spinlock.h>
20#include <spm_svc.h>
21#include <utils.h>
22#include <xlat_tables_v2.h>
23
24#include "spm_private.h"
25
26/* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */
27static spinlock_t mem_attr_smc_lock;
28
29/*******************************************************************************
30 * Secure Partition context information.
31 ******************************************************************************/
32static secure_partition_context_t sp_ctx;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010033
34/*******************************************************************************
35 * Replace the S-EL1 re-entry information with S-EL0 re-entry
36 * information
37 ******************************************************************************/
Antonio Nino Diaze8811472018-04-17 15:10:18 +010038static void spm_setup_next_eret_into_sel0(const cpu_context_t *secure_context)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010039{
40 assert(secure_context == cm_get_context(SECURE));
41
42 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1());
43}
44
45/*******************************************************************************
46 * This function takes an SP context pointer and:
47 * 1. Applies the S-EL1 system register context from sp_ctx->cpu_ctx.
48 * 2. Saves the current C runtime state (callee-saved registers) on the stack
49 * frame and saves a reference to this state.
50 * 3. Calls el3_exit() so that the EL3 system and general purpose registers
Sandrine Bailleux843d3f02017-12-07 09:48:56 +000051 * from the sp_ctx->cpu_ctx are used to enter the secure partition image.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010052 ******************************************************************************/
53static uint64_t spm_synchronous_sp_entry(secure_partition_context_t *sp_ctx_ptr)
54{
55 uint64_t rc;
56
57 assert(sp_ctx_ptr != NULL);
58 assert(sp_ctx_ptr->c_rt_ctx == 0);
59 assert(cm_get_context(SECURE) == &sp_ctx_ptr->cpu_ctx);
60
61 /* Apply the Secure EL1 system register context and switch to it */
62 cm_el1_sysregs_context_restore(SECURE);
63 cm_set_next_eret_context(SECURE);
64
65 VERBOSE("%s: We're about to enter the Secure partition...\n", __func__);
66
67 rc = spm_secure_partition_enter(&sp_ctx_ptr->c_rt_ctx);
68#if ENABLE_ASSERTIONS
69 sp_ctx_ptr->c_rt_ctx = 0;
70#endif
71
72 return rc;
73}
74
75
76/*******************************************************************************
77 * This function takes a Secure partition context pointer and:
Sandrine Bailleux843d3f02017-12-07 09:48:56 +000078 * 1. Saves the S-EL1 system register context to sp_ctx->cpu_ctx.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010079 * 2. Restores the current C runtime state (callee saved registers) from the
80 * stack frame using the reference to this state saved in
81 * spm_secure_partition_enter().
82 * 3. It does not need to save any general purpose or EL3 system register state
83 * as the generic smc entry routine should have saved those.
84 ******************************************************************************/
85static void __dead2 spm_synchronous_sp_exit(
Antonio Nino Diaze8811472018-04-17 15:10:18 +010086 const secure_partition_context_t *sp_ctx_ptr, uint64_t ret)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010087{
88 assert(sp_ctx_ptr != NULL);
89 /* Save the Secure EL1 system register context */
90 assert(cm_get_context(SECURE) == &sp_ctx_ptr->cpu_ctx);
91 cm_el1_sysregs_context_save(SECURE);
92
Antonio Nino Diaze8811472018-04-17 15:10:18 +010093 assert(sp_ctx_ptr->c_rt_ctx != 0U);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +010094 spm_secure_partition_exit(sp_ctx_ptr->c_rt_ctx, ret);
95
96 /* Should never reach here */
97 assert(0);
98}
99
100/*******************************************************************************
101 * This function passes control to the Secure Partition image (BL32) for the
102 * first time on the primary cpu after a cold boot. It assumes that a valid
103 * secure context has already been created by spm_setup() which can be directly
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000104 * used. This function performs a synchronous entry into the Secure partition.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100105 * The SP passes control back to this routine through a SMC.
106 ******************************************************************************/
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100107static int32_t spm_init(void)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100108{
109 entry_point_info_t *secure_partition_ep_info;
110 uint64_t rc;
111
112 VERBOSE("%s entry\n", __func__);
113
114 /*
115 * Get information about the Secure Partition (BL32) image. Its
116 * absence is a critical failure.
117 */
118 secure_partition_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100119 assert(secure_partition_ep_info != NULL);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100120
121 /*
122 * Initialise the common context and then overlay the S-EL0 specific
123 * context on top of it.
124 */
125 cm_init_my_context(secure_partition_ep_info);
126 secure_partition_setup();
127
128 /*
Antonio Nino Diaz496f54d2018-01-08 09:59:33 +0000129 * Make all CPUs use the same secure context.
130 */
131 for (unsigned int i = 0; i < PLATFORM_CORE_COUNT; i++) {
132 cm_set_context_by_index(i, &sp_ctx.cpu_ctx, SECURE);
133 }
134
135 /*
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000136 * Arrange for an entry into the secure partition.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100137 */
Antonio Nino Diazc58cb872017-12-18 10:51:58 +0000138 sp_ctx.sp_init_in_progress = 1;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100139 rc = spm_synchronous_sp_entry(&sp_ctx);
140 assert(rc == 0);
Antonio Nino Diazc58cb872017-12-18 10:51:58 +0000141 sp_ctx.sp_init_in_progress = 0;
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000142 VERBOSE("SP_MEMORY_ATTRIBUTES_SET_AARCH64 availability has been revoked\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100143
144 return rc;
145}
146
147/*******************************************************************************
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000148 * Given a secure partition entrypoint info pointer, entry point PC & pointer to
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100149 * a context data structure, this function will initialize the SPM context and
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000150 * entry point info for the secure partition.
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100151 ******************************************************************************/
152void spm_init_sp_ep_state(struct entry_point_info *sp_ep_info,
153 uint64_t pc,
154 secure_partition_context_t *sp_ctx_ptr)
155{
156 uint32_t ep_attr;
157
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100158 assert(sp_ep_info != NULL);
159 assert(pc != 0U);
160 assert(sp_ctx_ptr != NULL);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100161
162 cm_set_context(&sp_ctx_ptr->cpu_ctx, SECURE);
163
164 /* initialise an entrypoint to set up the CPU context */
165 ep_attr = SECURE | EP_ST_ENABLE;
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100166 if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100167 ep_attr |= EP_EE_BIG;
168 SET_PARAM_HEAD(sp_ep_info, PARAM_EP, VERSION_1, ep_attr);
169
170 sp_ep_info->pc = pc;
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000171 /* The secure partition runs in S-EL0. */
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100172 sp_ep_info->spsr = SPSR_64(MODE_EL0,
173 MODE_SP_EL0,
174 DISABLE_ALL_EXCEPTIONS);
175
176 zeromem(&sp_ep_info->args, sizeof(sp_ep_info->args));
177}
178
179/*******************************************************************************
180 * Secure Partition Manager setup. The SPM finds out the SP entrypoint if not
181 * already known and initialises the context for entry into the SP for its
182 * initialisation.
183 ******************************************************************************/
184int32_t spm_setup(void)
185{
186 entry_point_info_t *secure_partition_ep_info;
187
188 VERBOSE("%s entry\n", __func__);
189
190 /*
191 * Get information about the Secure Partition (BL32) image. Its
192 * absence is a critical failure.
193 */
194 secure_partition_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100195 if (secure_partition_ep_info == NULL) {
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100196 WARN("No SPM provided by BL2 boot loader, Booting device"
197 " without SPM initialization. SMCs destined for SPM"
198 " will return SMC_UNK\n");
199 return 1;
200 }
201
202 /*
203 * If there's no valid entry point for SP, we return a non-zero value
204 * signalling failure initializing the service. We bail out without
205 * registering any handlers
206 */
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100207 if (secure_partition_ep_info->pc == 0U) {
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100208 return 1;
209 }
210
211 spm_init_sp_ep_state(secure_partition_ep_info,
212 secure_partition_ep_info->pc,
213 &sp_ctx);
214
215 /*
216 * All SPM initialization done. Now register our init function with
217 * BL31 for deferred invocation
218 */
219 bl31_register_bl32_init(&spm_init);
220
221 VERBOSE("%s exit\n", __func__);
222
223 return 0;
224}
225
226/*
227 * Attributes are encoded using a different format in the SMC interface than in
228 * the Trusted Firmware, where the mmap_attr_t enum type is used. This function
229 * converts an attributes value from the SMC format to the mmap_attr_t format by
230 * setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and MT_EXECUTE/MT_EXECUTE_NEVER.
231 * The other fields are left as 0 because they are ignored by the function
232 * change_mem_attributes().
233 */
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100234static unsigned int smc_attr_to_mmap_attr(unsigned int attributes)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100235{
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100236 unsigned int tf_attr = 0U;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100237
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000238 unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
239 >> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100240
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000241 if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RW) {
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100242 tf_attr |= MT_RW | MT_USER;
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000243 } else if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RO) {
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100244 tf_attr |= MT_RO | MT_USER;
245 } else {
246 /* Other values are reserved. */
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000247 assert(access == SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100248 /* The only requirement is that there's no access from EL0 */
249 tf_attr |= MT_RO | MT_PRIVILEGED;
250 }
251
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000252 if ((attributes & SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) {
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100253 tf_attr |= MT_EXECUTE;
254 } else {
255 tf_attr |= MT_EXECUTE_NEVER;
256 }
257
258 return tf_attr;
259}
260
261/*
262 * This function converts attributes from the Trusted Firmware format into the
263 * SMC interface format.
264 */
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100265static unsigned int smc_mmap_to_smc_attr(unsigned int attr)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100266{
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100267 unsigned int smc_attr = 0U;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100268
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100269 unsigned int data_access;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100270
271 if ((attr & MT_USER) == 0) {
272 /* No access from EL0. */
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000273 data_access = SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100274 } else {
275 if ((attr & MT_RW) != 0) {
276 assert(MT_TYPE(attr) != MT_DEVICE);
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000277 data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RW;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100278 } else {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000279 data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RO;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100280 }
281 }
282
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000283 smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK)
284 << SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100285
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100286 if ((attr & MT_EXECUTE_NEVER) != 0U) {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000287 smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100288 }
289
290 return smc_attr;
291}
292
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100293static int32_t spm_memory_attributes_get_smc_handler(uintptr_t base_va)
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100294{
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100295 uint32_t attributes;
296
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100297 spin_lock(&mem_attr_smc_lock);
298
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100299 int rc = get_mem_attributes(secure_partition_xlat_ctx_handle,
300 base_va, &attributes);
301
302 spin_unlock(&mem_attr_smc_lock);
303
304 /* Convert error codes of get_mem_attributes() into SPM ones. */
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100305 assert((rc == 0) || (rc == -EINVAL));
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100306
307 if (rc == 0) {
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100308 return (int32_t) smc_mmap_to_smc_attr(attributes);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100309 } else {
310 return SPM_INVALID_PARAMETER;
311 }
312}
313
314static int spm_memory_attributes_set_smc_handler(u_register_t page_address,
315 u_register_t pages_count,
316 u_register_t smc_attributes)
317{
318 uintptr_t base_va = (uintptr_t) page_address;
319 size_t size = (size_t) (pages_count * PAGE_SIZE);
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100320 uint32_t attributes = (uint32_t) smc_attributes;
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100321
322 INFO(" Start address : 0x%lx\n", base_va);
323 INFO(" Number of pages: %i (%zi bytes)\n", (int) pages_count, size);
324 INFO(" Attributes : 0x%x\n", attributes);
325
326 spin_lock(&mem_attr_smc_lock);
327
328 int ret = change_mem_attributes(secure_partition_xlat_ctx_handle,
329 base_va, size, smc_attr_to_mmap_attr(attributes));
330
331 spin_unlock(&mem_attr_smc_lock);
332
333 /* Convert error codes of change_mem_attributes() into SPM ones. */
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100334 assert((ret == 0) || (ret == -EINVAL));
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100335
336 return (ret == 0) ? SPM_SUCCESS : SPM_INVALID_PARAMETER;
337}
338
339
340uint64_t spm_smc_handler(uint32_t smc_fid,
341 uint64_t x1,
342 uint64_t x2,
343 uint64_t x3,
344 uint64_t x4,
345 void *cookie,
346 void *handle,
347 uint64_t flags)
348{
349 cpu_context_t *ns_cpu_context;
350 unsigned int ns;
351
352 /* Determine which security state this SMC originated from */
353 ns = is_caller_non_secure(flags);
354
355 if (ns == SMC_FROM_SECURE) {
356
357 /* Handle SMCs from Secure world. */
358
359 switch (smc_fid) {
360
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000361 case SPM_VERSION_AARCH32:
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100362 SMC_RET1(handle, SPM_VERSION_COMPILED);
363
364 case SP_EVENT_COMPLETE_AARCH64:
365 assert(handle == cm_get_context(SECURE));
366 cm_el1_sysregs_context_save(SECURE);
367 spm_setup_next_eret_into_sel0(handle);
368
Antonio Nino Diazc58cb872017-12-18 10:51:58 +0000369 if (sp_ctx.sp_init_in_progress) {
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100370 /*
371 * SPM reports completion. The SPM must have
372 * initiated the original request through a
373 * synchronous entry into the secure
374 * partition. Jump back to the original C
375 * runtime context.
376 */
377 spm_synchronous_sp_exit(&sp_ctx, x1);
378 assert(0);
379 }
380
Antonio Nino Diaz496f54d2018-01-08 09:59:33 +0000381 /* Release the Secure Partition context */
382 spin_unlock(&sp_ctx.lock);
383
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100384 /*
385 * This is the result from the Secure partition of an
386 * earlier request. Copy the result into the non-secure
387 * context, save the secure state and return to the
388 * non-secure state.
389 */
390
391 /* Get a reference to the non-secure context */
392 ns_cpu_context = cm_get_context(NON_SECURE);
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100393 assert(ns_cpu_context != NULL);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100394
395 /* Restore non-secure state */
396 cm_el1_sysregs_context_restore(NON_SECURE);
397 cm_set_next_eret_context(NON_SECURE);
398
399 /* Return to normal world */
400 SMC_RET1(ns_cpu_context, x1);
401
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000402 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
403 INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100404
Antonio Nino Diazc58cb872017-12-18 10:51:58 +0000405 if (!sp_ctx.sp_init_in_progress) {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000406 WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100407 SMC_RET1(handle, SPM_NOT_SUPPORTED);
408 }
409 SMC_RET1(handle, spm_memory_attributes_get_smc_handler(x1));
410
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000411 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
412 INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100413
Antonio Nino Diazc58cb872017-12-18 10:51:58 +0000414 if (!sp_ctx.sp_init_in_progress) {
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000415 WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n");
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100416 SMC_RET1(handle, SPM_NOT_SUPPORTED);
417 }
418 SMC_RET1(handle, spm_memory_attributes_set_smc_handler(x1, x2, x3));
419 default:
420 break;
421 }
422 } else {
423
424 /* Handle SMCs from Non-secure world. */
425
426 switch (smc_fid) {
427
Antonio Nino Diaz35b37f02018-01-08 17:33:34 +0000428 case MM_VERSION_AARCH32:
429 SMC_RET1(handle, MM_VERSION_COMPILED);
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100430
Sandrine Bailleuxb31ee6b2017-12-01 09:44:21 +0000431 case MM_COMMUNICATE_AARCH32:
432 case MM_COMMUNICATE_AARCH64:
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000433 {
434 uint64_t mm_cookie = x1;
435 uint64_t comm_buffer_address = x2;
436 uint64_t comm_size_address = x3;
437
438 /* Cookie. Reserved for future use. It must be zero. */
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100439 if (mm_cookie != 0U) {
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000440 ERROR("MM_COMMUNICATE: cookie is not zero\n");
441 SMC_RET1(handle, SPM_INVALID_PARAMETER);
442 }
443
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100444 if (comm_buffer_address == 0U) {
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000445 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n");
446 SMC_RET1(handle, SPM_INVALID_PARAMETER);
447 }
448
Antonio Nino Diaze8811472018-04-17 15:10:18 +0100449 if (comm_size_address != 0U) {
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000450 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n");
451 }
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100452
453 /* Save the Normal world context */
454 cm_el1_sysregs_context_save(NON_SECURE);
455
Antonio Nino Diaz496f54d2018-01-08 09:59:33 +0000456 /* Lock the Secure Partition context. */
457 spin_lock(&sp_ctx.lock);
458
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100459 /*
460 * Restore the secure world context and prepare for
461 * entry in S-EL0
462 */
463 assert(&sp_ctx.cpu_ctx == cm_get_context(SECURE));
464 cm_el1_sysregs_context_restore(SECURE);
465 cm_set_next_eret_context(SECURE);
466
Sandrine Bailleux843d3f02017-12-07 09:48:56 +0000467 SMC_RET4(&sp_ctx.cpu_ctx, smc_fid, comm_buffer_address,
468 comm_size_address, plat_my_core_pos());
469 }
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100470
Antonio Nino Diaz837173f2017-12-01 14:12:43 +0000471 case SP_MEMORY_ATTRIBUTES_GET_AARCH64:
472 case SP_MEMORY_ATTRIBUTES_SET_AARCH64:
Antonio Nino Diazc41f2062017-10-24 10:07:35 +0100473 /* SMC interfaces reserved for secure callers. */
474 SMC_RET1(handle, SPM_NOT_SUPPORTED);
475
476 default:
477 break;
478 }
479 }
480
481 SMC_RET1(handle, SMC_UNK);
482}