spmd_main.c 18.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
/*
 * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>
#include <errno.h>
#include <string.h>

#include <arch_helpers.h>
Olivier Deprez's avatar
Olivier Deprez committed
12
#include <arch/aarch64/arch_features.h>
13
14
15
16
17
18
19
20
21
22
#include <bl31/bl31.h>
#include <common/debug.h>
#include <common/runtime_svc.h>
#include <lib/el3_runtime/context_mgmt.h>
#include <lib/smccc.h>
#include <lib/spinlock.h>
#include <lib/utils.h>
#include <plat/common/common_def.h>
#include <plat/common/platform.h>
#include <platform_def.h>
J-Alves's avatar
J-Alves committed
23
#include <services/ffa_svc.h>
24
25
26
27
28
29
30
#include <services/spmd_svc.h>
#include <smccc_helpers.h>
#include "spmd_private.h"

/*******************************************************************************
 * SPM Core context information.
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
31
static spmd_spm_core_context_t spm_core_context[PLATFORM_CORE_COUNT];
32
33
34
35

/*******************************************************************************
 * SPM Core attribute information read from its manifest.
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
36
static spmc_manifest_attribute_t spmc_attrs;
37
38
39
40
41
42
43

/*******************************************************************************
 * SPM Core entry point information. Discovered on the primary core and reused
 * on secondary cores.
 ******************************************************************************/
static entry_point_info_t *spmc_ep_info;

44
45
46
47
48
49
50
51
/*******************************************************************************
 * SPM Core context on CPU based on mpidr.
 ******************************************************************************/
spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr)
{
	return &spm_core_context[plat_core_pos_by_mpidr(mpidr)];
}

Olivier Deprez's avatar
Olivier Deprez committed
52
53
54
55
56
/*******************************************************************************
 * SPM Core context on current CPU get helper.
 ******************************************************************************/
spmd_spm_core_context_t *spmd_get_context(void)
{
57
	return spmd_get_context_by_mpidr(read_mpidr());
Olivier Deprez's avatar
Olivier Deprez committed
58
59
}

60
61
62
63
64
65
66
67
/*******************************************************************************
 * SPM Core entry point information get helper.
 ******************************************************************************/
entry_point_info_t *spmd_spmc_ep_info_get(void)
{
	return spmc_ep_info;
}

68
69
70
71
72
73
74
75
/*******************************************************************************
 * SPM Core ID getter.
 ******************************************************************************/
uint16_t spmd_spmc_id_get(void)
{
	return spmc_attrs.spmc_id;
}

76
77
78
/*******************************************************************************
 * Static function declaration.
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
79
static int32_t spmd_init(void);
80
static int spmd_spmc_init(void *pm_addr);
J-Alves's avatar
J-Alves committed
81
static uint64_t spmd_ffa_error_return(void *handle,
Olivier Deprez's avatar
Olivier Deprez committed
82
83
84
85
86
87
88
89
				       int error_code);
static uint64_t spmd_smc_forward(uint32_t smc_fid,
				 bool secure_origin,
				 uint64_t x1,
				 uint64_t x2,
				 uint64_t x3,
				 uint64_t x4,
				 void *handle);
90
91

/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
92
93
 * This function takes an SPMC context pointer and performs a synchronous
 * SPMC entry.
94
95
96
97
98
99
100
101
102
103
104
 ******************************************************************************/
uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *spmc_ctx)
{
	uint64_t rc;

	assert(spmc_ctx != NULL);

	cm_set_context(&(spmc_ctx->cpu_ctx), SECURE);

	/* Restore the context assigned above */
	cm_el1_sysregs_context_restore(SECURE);
105
#if SPMD_SPM_AT_SEL2
106
	cm_el2_sysregs_context_restore(SECURE);
107
#endif
108
109
	cm_set_next_eret_context(SECURE);

110
	/* Enter SPMC */
111
112
113
114
	rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx);

	/* Save secure state */
	cm_el1_sysregs_context_save(SECURE);
115
#if SPMD_SPM_AT_SEL2
116
	cm_el2_sysregs_context_save(SECURE);
117
#endif
118
119
120
121
122

	return rc;
}

/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
123
 * This function returns to the place where spmd_spm_core_sync_entry() was
124
125
126
127
 * called originally.
 ******************************************************************************/
__dead2 void spmd_spm_core_sync_exit(uint64_t rc)
{
Olivier Deprez's avatar
Olivier Deprez committed
128
	spmd_spm_core_context_t *ctx = spmd_get_context();
129

Olivier Deprez's avatar
Olivier Deprez committed
130
	/* Get current CPU context from SPMC context */
131
132
133
134
135
136
137
138
139
140
141
142
143
	assert(cm_get_context(SECURE) == &(ctx->cpu_ctx));

	/*
	 * The SPMD must have initiated the original request through a
	 * synchronous entry into SPMC. Jump back to the original C runtime
	 * context with the value of rc in x0;
	 */
	spmd_spm_core_exit(ctx->c_rt_ctx, rc);

	panic();
}

/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
144
 * Jump to the SPM Core for the first time.
145
146
147
 ******************************************************************************/
static int32_t spmd_init(void)
{
Olivier Deprez's avatar
Olivier Deprez committed
148
149
	spmd_spm_core_context_t *ctx = spmd_get_context();
	uint64_t rc;
150
151
	unsigned int linear_id = plat_my_core_pos();
	unsigned int core_id;
152

Olivier Deprez's avatar
Olivier Deprez committed
153
	VERBOSE("SPM Core init start.\n");
154
155
156
	ctx->state = SPMC_STATE_ON_PENDING;

	/* Set the SPMC context state on other CPUs to OFF */
157
	for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) {
158
159
		if (core_id != linear_id) {
			spm_core_context[core_id].state = SPMC_STATE_OFF;
160
			spm_core_context[core_id].secondary_ep.entry_point = 0UL;
161
162
		}
	}
163
164

	rc = spmd_spm_core_sync_entry(ctx);
Olivier Deprez's avatar
Olivier Deprez committed
165
	if (rc != 0ULL) {
166
		ERROR("SPMC initialisation failed 0x%llx\n", rc);
Olivier Deprez's avatar
Olivier Deprez committed
167
		return 0;
168
169
	}

170
171
	ctx->state = SPMC_STATE_ON;

Olivier Deprez's avatar
Olivier Deprez committed
172
	VERBOSE("SPM Core init end.\n");
173
174
175
176
177

	return 1;
}

/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
178
 * Loads SPMC manifest and inits SPMC.
179
 ******************************************************************************/
180
static int spmd_spmc_init(void *pm_addr)
181
{
Olivier Deprez's avatar
Olivier Deprez committed
182
	spmd_spm_core_context_t *spm_ctx = spmd_get_context();
183
	uint32_t ep_attr;
Olivier Deprez's avatar
Olivier Deprez committed
184
	int rc;
185

Olivier Deprez's avatar
Olivier Deprez committed
186
	/* Load the SPM Core manifest */
187
	rc = plat_spm_core_manifest_load(&spmc_attrs, pm_addr);
188
	if (rc != 0) {
Olivier Deprez's avatar
Olivier Deprez committed
189
190
		WARN("No or invalid SPM Core manifest image provided by BL2\n");
		return rc;
191
192
193
	}

	/*
Olivier Deprez's avatar
Olivier Deprez committed
194
195
	 * Ensure that the SPM Core version is compatible with the SPM
	 * Dispatcher version.
196
	 */
J-Alves's avatar
J-Alves committed
197
198
199
	if ((spmc_attrs.major_version != FFA_VERSION_MAJOR) ||
	    (spmc_attrs.minor_version > FFA_VERSION_MINOR)) {
		WARN("Unsupported FFA version (%u.%u)\n",
200
		     spmc_attrs.major_version, spmc_attrs.minor_version);
Olivier Deprez's avatar
Olivier Deprez committed
201
		return -EINVAL;
202
203
	}

J-Alves's avatar
J-Alves committed
204
	VERBOSE("FFA version (%u.%u)\n", spmc_attrs.major_version,
205
206
	     spmc_attrs.minor_version);

Olivier Deprez's avatar
Olivier Deprez committed
207
	VERBOSE("SPM Core run time EL%x.\n",
208
	     SPMD_SPM_AT_SEL2 ? MODE_EL2 : MODE_EL1);
209

210
	/* Validate the SPMC ID, Ensure high bit is set */
Olivier Deprez's avatar
Olivier Deprez committed
211
212
213
214
	if (((spmc_attrs.spmc_id >> SPMC_SECURE_ID_SHIFT) &
			SPMC_SECURE_ID_MASK) == 0U) {
		WARN("Invalid ID (0x%x) for SPMC.\n", spmc_attrs.spmc_id);
		return -EINVAL;
215
216
	}

Olivier Deprez's avatar
Olivier Deprez committed
217
	/* Validate the SPM Core execution state */
218
219
	if ((spmc_attrs.exec_state != MODE_RW_64) &&
	    (spmc_attrs.exec_state != MODE_RW_32)) {
220
		WARN("Unsupported %s%x.\n", "SPM Core execution state 0x",
221
		     spmc_attrs.exec_state);
Olivier Deprez's avatar
Olivier Deprez committed
222
		return -EINVAL;
223
224
	}

225
226
	VERBOSE("%s%x.\n", "SPM Core execution state 0x",
		spmc_attrs.exec_state);
227

228
229
230
231
#if SPMD_SPM_AT_SEL2
	/* Ensure manifest has not requested AArch32 state in S-EL2 */
	if (spmc_attrs.exec_state == MODE_RW_32) {
		WARN("AArch32 state at S-EL2 is not supported.\n");
Olivier Deprez's avatar
Olivier Deprez committed
232
		return -EINVAL;
233
234
235
236
237
238
	}

	/*
	 * Check if S-EL2 is supported on this system if S-EL2
	 * is required for SPM
	 */
Olivier Deprez's avatar
Olivier Deprez committed
239
240
241
	if (!is_armv8_4_sel2_present()) {
		WARN("SPM Core run time S-EL2 is not supported.\n");
		return -EINVAL;
242
	}
243
#endif /* SPMD_SPM_AT_SEL2 */
244
245
246

	/* Initialise an entrypoint to set up the CPU context */
	ep_attr = SECURE | EP_ST_ENABLE;
Olivier Deprez's avatar
Olivier Deprez committed
247
	if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0ULL) {
248
		ep_attr |= EP_EE_BIG;
249
250
	}

251
252
253
	SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr);

	/*
Olivier Deprez's avatar
Olivier Deprez committed
254
255
	 * Populate SPSR for SPM Core based upon validated parameters from the
	 * manifest.
256
257
258
259
260
261
262
263
	 */
	if (spmc_attrs.exec_state == MODE_RW_32) {
		spmc_ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
						 SPSR_E_LITTLE,
						 DAIF_FIQ_BIT |
						 DAIF_IRQ_BIT |
						 DAIF_ABT_BIT);
	} else {
264
265
266
267
268
269
270

#if SPMD_SPM_AT_SEL2
		static const uint32_t runtime_el = MODE_EL2;
#else
		static const uint32_t runtime_el = MODE_EL1;
#endif
		spmc_ep_info->spsr = SPSR_64(runtime_el,
271
272
273
274
					     MODE_SP_ELX,
					     DISABLE_ALL_EXCEPTIONS);
	}

Olivier Deprez's avatar
Olivier Deprez committed
275
	/* Initialise SPM Core context with this entry point information */
276
277
278
279
	cm_setup_context(&spm_ctx->cpu_ctx, spmc_ep_info);

	/* Reuse PSCI affinity states to mark this SPMC context as off */
	spm_ctx->state = AFF_STATE_OFF;
280

Olivier Deprez's avatar
Olivier Deprez committed
281
	INFO("SPM Core setup done.\n");
282

283
284
285
	/* Register power management hooks with PSCI */
	psci_register_spd_pm_hook(&spmd_pm);

Olivier Deprez's avatar
Olivier Deprez committed
286
	/* Register init function for deferred init. */
287
288
289
	bl31_register_bl32_init(&spmd_init);

	return 0;
290
}
291

292
/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
293
 * Initialize context of SPM Core.
294
295
296
 ******************************************************************************/
int spmd_setup(void)
{
297
	void *spmc_manifest;
298
	int rc;
299

300
	spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
Olivier Deprez's avatar
Olivier Deprez committed
301
302
303
	if (spmc_ep_info == NULL) {
		WARN("No SPM Core image provided by BL2 boot loader.\n");
		return -EINVAL;
304
305
306
	}

	/* Under no circumstances will this parameter be 0 */
Olivier Deprez's avatar
Olivier Deprez committed
307
	assert(spmc_ep_info->pc != 0ULL);
308
309
310

	/*
	 * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will
Olivier Deprez's avatar
Olivier Deprez committed
311
	 * be used as a manifest for the SPM Core at the next lower EL/mode.
312
	 */
313
314
315
316
	spmc_manifest = (void *)spmc_ep_info->args.arg0;
	if (spmc_manifest == NULL) {
		ERROR("Invalid or absent SPM Core manifest.\n");
		return -EINVAL;
317
318
319
	}

	/* Load manifest, init SPMC */
320
	rc = spmd_spmc_init(spmc_manifest);
321
	if (rc != 0) {
Olivier Deprez's avatar
Olivier Deprez committed
322
		WARN("Booting device without SPM initialization.\n");
323
324
	}

325
	return rc;
326
327
328
329
330
}

/*******************************************************************************
 * Forward SMC to the other security state
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
331
332
333
334
335
336
337
static uint64_t spmd_smc_forward(uint32_t smc_fid,
				 bool secure_origin,
				 uint64_t x1,
				 uint64_t x2,
				 uint64_t x3,
				 uint64_t x4,
				 void *handle)
338
{
339
340
	unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE;
	unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE;
341

342
	/* Save incoming security state */
343
	cm_el1_sysregs_context_save(secure_state_in);
344
#if SPMD_SPM_AT_SEL2
345
	cm_el2_sysregs_context_save(secure_state_in);
346
#endif
347
348

	/* Restore outgoing security state */
349
	cm_el1_sysregs_context_restore(secure_state_out);
350
#if SPMD_SPM_AT_SEL2
351
	cm_el2_sysregs_context_restore(secure_state_out);
352
#endif
353
	cm_set_next_eret_context(secure_state_out);
354

355
	SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
356
357
358
359
360
361
			SMC_GET_GP(handle, CTX_GPREG_X5),
			SMC_GET_GP(handle, CTX_GPREG_X6),
			SMC_GET_GP(handle, CTX_GPREG_X7));
}

/*******************************************************************************
J-Alves's avatar
J-Alves committed
362
 * Return FFA_ERROR with specified error code
363
 ******************************************************************************/
J-Alves's avatar
J-Alves committed
364
static uint64_t spmd_ffa_error_return(void *handle, int error_code)
365
{
J-Alves's avatar
J-Alves committed
366
367
368
369
	SMC_RET8(handle, FFA_ERROR,
		 FFA_TARGET_INFO_MBZ, error_code,
		 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
370
371
}

372
373
374
375
376
377
378
379
380
381
382
/*******************************************************************************
 * spmd_check_address_in_binary_image
 ******************************************************************************/
bool spmd_check_address_in_binary_image(uint64_t address)
{
	assert(!check_uptr_overflow(spmc_attrs.load_address, spmc_attrs.binary_size));

	return ((address >= spmc_attrs.load_address) &&
		(address < (spmc_attrs.load_address + spmc_attrs.binary_size)));
}

383
384
385
386
387
388
389
390
391
/******************************************************************************
 * spmd_is_spmc_message
 *****************************************************************************/
static bool spmd_is_spmc_message(unsigned int ep)
{
	return ((ffa_endpoint_destination(ep) == SPMD_DIRECT_MSG_ENDPOINT_ID)
		&& (ffa_endpoint_source(ep) == spmc_attrs.spmc_id));
}

392
393
394
/******************************************************************************
 * spmd_handle_spmc_message
 *****************************************************************************/
395
396
397
static int spmd_handle_spmc_message(unsigned long long msg,
		unsigned long long parm1, unsigned long long parm2,
		unsigned long long parm3, unsigned long long parm4)
398
399
400
401
402
403
404
405
406
407
408
409
410
411
{
	VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__,
		msg, parm1, parm2, parm3, parm4);

	switch (msg) {
	case SPMD_DIRECT_MSG_SET_ENTRY_POINT:
		return spmd_pm_secondary_core_set_ep(parm1, parm2, parm3);
	default:
		break;
	}

	return -EINVAL;
}

412
/*******************************************************************************
J-Alves's avatar
J-Alves committed
413
 * This function handles all SMCs in the range reserved for FFA. Each call is
414
415
 * either forwarded to the other security state or handled by the SPM dispatcher
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
416
417
418
419
420
421
422
uint64_t spmd_smc_handler(uint32_t smc_fid,
			  uint64_t x1,
			  uint64_t x2,
			  uint64_t x3,
			  uint64_t x4,
			  void *cookie,
			  void *handle,
423
424
			  uint64_t flags)
{
Olivier Deprez's avatar
Olivier Deprez committed
425
	spmd_spm_core_context_t *ctx = spmd_get_context();
426
427
	bool secure_origin;
	int32_t ret;
J-Alves's avatar
J-Alves committed
428
	uint32_t input_version;
429
430

	/* Determine which security state this SMC originated from */
431
	secure_origin = is_caller_secure(flags);
432

Olivier Deprez's avatar
Olivier Deprez committed
433
	INFO("SPM: 0x%x 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx 0x%llx\n",
434
435
436
437
438
	     smc_fid, x1, x2, x3, x4, SMC_GET_GP(handle, CTX_GPREG_X5),
	     SMC_GET_GP(handle, CTX_GPREG_X6),
	     SMC_GET_GP(handle, CTX_GPREG_X7));

	switch (smc_fid) {
J-Alves's avatar
J-Alves committed
439
	case FFA_ERROR:
440
441
		/*
		 * Check if this is the first invocation of this interface on
Olivier Deprez's avatar
Olivier Deprez committed
442
		 * this CPU. If so, then indicate that the SPM Core initialised
443
444
		 * unsuccessfully.
		 */
445
		if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
446
			spmd_spm_core_sync_exit(x2);
447
		}
448

449
		return spmd_smc_forward(smc_fid, secure_origin,
450
					x1, x2, x3, x4, handle);
451
452
		break; /* not reached */

J-Alves's avatar
J-Alves committed
453
	case FFA_VERSION:
J-Alves's avatar
J-Alves committed
454
		input_version = (uint32_t)(0xFFFFFFFF & x1);
455
		/*
J-Alves's avatar
J-Alves committed
456
457
458
459
460
		 * If caller is secure and SPMC was initialized,
		 * return FFA_VERSION of SPMD.
		 * If caller is non secure and SPMC was initialized,
		 * return SPMC's version.
		 * Sanity check to "input_version".
461
		 */
J-Alves's avatar
J-Alves committed
462
463
464
465
466
467
468
469
470
471
		if ((input_version & FFA_VERSION_BIT31_MASK) ||
			(ctx->state == SPMC_STATE_RESET)) {
			ret = FFA_ERROR_NOT_SUPPORTED;
		} else if (!secure_origin) {
			ret = MAKE_FFA_VERSION(spmc_attrs.major_version, spmc_attrs.minor_version);
		} else {
			ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR);
		}

		SMC_RET8(handle, ret, FFA_TARGET_INFO_MBZ, FFA_TARGET_INFO_MBZ,
J-Alves's avatar
J-Alves committed
472
473
			 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
			 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
474
475
		break; /* not reached */

J-Alves's avatar
J-Alves committed
476
	case FFA_FEATURES:
477
478
		/*
		 * This is an optional interface. Do the minimal checks and
Olivier Deprez's avatar
Olivier Deprez committed
479
		 * forward to SPM Core which will handle it if implemented.
480
481
482
		 */

		/*
J-Alves's avatar
J-Alves committed
483
		 * Check if x1 holds a valid FFA fid. This is an
484
485
		 * optimization.
		 */
J-Alves's avatar
J-Alves committed
486
487
488
		if (!is_ffa_fid(x1)) {
			return spmd_ffa_error_return(handle,
						      FFA_ERROR_NOT_SUPPORTED);
489
		}
490

Olivier Deprez's avatar
Olivier Deprez committed
491
		/* Forward SMC from Normal world to the SPM Core */
492
493
		if (!secure_origin) {
			return spmd_smc_forward(smc_fid, secure_origin,
494
						x1, x2, x3, x4, handle);
495
		}
496

Olivier Deprez's avatar
Olivier Deprez committed
497
498
		/*
		 * Return success if call was from secure world i.e. all
J-Alves's avatar
J-Alves committed
499
		 * FFA functions are supported. This is essentially a
Olivier Deprez's avatar
Olivier Deprez committed
500
501
		 * nop.
		 */
J-Alves's avatar
J-Alves committed
502
		SMC_RET8(handle, FFA_SUCCESS_SMC32, x1, x2, x3, x4,
Olivier Deprez's avatar
Olivier Deprez committed
503
504
505
506
			 SMC_GET_GP(handle, CTX_GPREG_X5),
			 SMC_GET_GP(handle, CTX_GPREG_X6),
			 SMC_GET_GP(handle, CTX_GPREG_X7));

507
508
		break; /* not reached */

J-Alves's avatar
J-Alves committed
509
	case FFA_ID_GET:
510
		/*
J-Alves's avatar
J-Alves committed
511
		 * Returns the ID of the calling FFA component.
Olivier Deprez's avatar
Olivier Deprez committed
512
		 */
513
		if (!secure_origin) {
J-Alves's avatar
J-Alves committed
514
515
516
517
518
			SMC_RET8(handle, FFA_SUCCESS_SMC32,
				 FFA_TARGET_INFO_MBZ, FFA_NS_ENDPOINT_ID,
				 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
				 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
				 FFA_PARAM_MBZ);
519
520
		}

J-Alves's avatar
J-Alves committed
521
522
523
524
525
		SMC_RET8(handle, FFA_SUCCESS_SMC32,
			 FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id,
			 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
			 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
			 FFA_PARAM_MBZ);
Olivier Deprez's avatar
Olivier Deprez committed
526

527
528
		break; /* not reached */

529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
	case FFA_MSG_SEND_DIRECT_REQ_SMC32:
		if (secure_origin && spmd_is_spmc_message(x1)) {
			ret = spmd_handle_spmc_message(x3, x4,
				SMC_GET_GP(handle, CTX_GPREG_X5),
				SMC_GET_GP(handle, CTX_GPREG_X6),
				SMC_GET_GP(handle, CTX_GPREG_X7));

			SMC_RET8(handle, FFA_SUCCESS_SMC32,
				FFA_TARGET_INFO_MBZ, ret,
				FFA_PARAM_MBZ, FFA_PARAM_MBZ,
				FFA_PARAM_MBZ, FFA_PARAM_MBZ,
				FFA_PARAM_MBZ);
		} else {
			/* Forward direct message to the other world */
			return spmd_smc_forward(smc_fid, secure_origin,
				x1, x2, x3, x4, handle);
		}
		break; /* Not reached */

	case FFA_MSG_SEND_DIRECT_RESP_SMC32:
		if (secure_origin && spmd_is_spmc_message(x1)) {
			spmd_spm_core_sync_exit(0);
		} else {
			/* Forward direct message to the other world */
			return spmd_smc_forward(smc_fid, secure_origin,
				x1, x2, x3, x4, handle);
		}
		break; /* Not reached */

J-Alves's avatar
J-Alves committed
558
559
560
561
	case FFA_RX_RELEASE:
	case FFA_RXTX_MAP_SMC32:
	case FFA_RXTX_MAP_SMC64:
	case FFA_RXTX_UNMAP:
562
563
564
565
566
567
568
	case FFA_PARTITION_INFO_GET:
		/*
		 * Should not be allowed to forward FFA_PARTITION_INFO_GET
		 * from Secure world to Normal world
		 *
		 * Fall through to forward the call to the other world
		 */
J-Alves's avatar
J-Alves committed
569
	case FFA_MSG_RUN:
570
		/* This interface must be invoked only by the Normal world */
571

572
		if (secure_origin) {
J-Alves's avatar
J-Alves committed
573
			return spmd_ffa_error_return(handle,
574
						     FFA_ERROR_NOT_SUPPORTED);
575
576
577
		}

		/* Fall through to forward the call to the other world */
J-Alves's avatar
J-Alves committed
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
	case FFA_MSG_SEND:
	case FFA_MSG_SEND_DIRECT_REQ_SMC64:
	case FFA_MSG_SEND_DIRECT_RESP_SMC64:
	case FFA_MEM_DONATE_SMC32:
	case FFA_MEM_DONATE_SMC64:
	case FFA_MEM_LEND_SMC32:
	case FFA_MEM_LEND_SMC64:
	case FFA_MEM_SHARE_SMC32:
	case FFA_MEM_SHARE_SMC64:
	case FFA_MEM_RETRIEVE_REQ_SMC32:
	case FFA_MEM_RETRIEVE_REQ_SMC64:
	case FFA_MEM_RETRIEVE_RESP:
	case FFA_MEM_RELINQUISH:
	case FFA_MEM_RECLAIM:
	case FFA_SUCCESS_SMC32:
	case FFA_SUCCESS_SMC64:
594
595
596
597
598
599
600
		/*
		 * TODO: Assume that no requests originate from EL3 at the
		 * moment. This will change if a SP service is required in
		 * response to secure interrupts targeted to EL3. Until then
		 * simply forward the call to the Normal world.
		 */

601
		return spmd_smc_forward(smc_fid, secure_origin,
602
					x1, x2, x3, x4, handle);
603
604
		break; /* not reached */

J-Alves's avatar
J-Alves committed
605
	case FFA_MSG_WAIT:
606
607
608
		/*
		 * Check if this is the first invocation of this interface on
		 * this CPU from the Secure world. If so, then indicate that the
Olivier Deprez's avatar
Olivier Deprez committed
609
		 * SPM Core initialised successfully.
610
		 */
611
		if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
612
613
614
			spmd_spm_core_sync_exit(0);
		}

615
		/* Fall through to forward the call to the other world */
616

J-Alves's avatar
J-Alves committed
617
	case FFA_MSG_YIELD:
618
		/* This interface must be invoked only by the Secure world */
619
		if (!secure_origin) {
J-Alves's avatar
J-Alves committed
620
621
			return spmd_ffa_error_return(handle,
						      FFA_ERROR_NOT_SUPPORTED);
622
623
		}

624
		return spmd_smc_forward(smc_fid, secure_origin,
625
					x1, x2, x3, x4, handle);
626
627
628
629
		break; /* not reached */

	default:
		WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
J-Alves's avatar
J-Alves committed
630
		return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
631
632
	}
}