spmd_main.c 19.6 KB
Newer Older
1
/*
2
 * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
3
4
5
6
7
8
9
10
11
 *
 * 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
/*******************************************************************************
 * SPM Core context on CPU based on mpidr.
 ******************************************************************************/
spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr)
{
49
50
51
52
53
54
55
56
	int core_idx = plat_core_pos_by_mpidr(mpidr);

	if (core_idx < 0) {
		ERROR("Invalid mpidr: %llx, returned ID: %d\n", mpidr, core_idx);
		panic();
	}

	return &spm_core_context[core_idx];
57
58
}

Olivier Deprez's avatar
Olivier Deprez committed
59
60
61
62
63
/*******************************************************************************
 * SPM Core context on current CPU get helper.
 ******************************************************************************/
spmd_spm_core_context_t *spmd_get_context(void)
{
64
	return spmd_get_context_by_mpidr(read_mpidr());
Olivier Deprez's avatar
Olivier Deprez committed
65
66
}

67
68
69
70
71
72
73
74
/*******************************************************************************
 * SPM Core entry point information get helper.
 ******************************************************************************/
entry_point_info_t *spmd_spmc_ep_info_get(void)
{
	return spmc_ep_info;
}

75
76
77
78
79
80
81
82
/*******************************************************************************
 * SPM Core ID getter.
 ******************************************************************************/
uint16_t spmd_spmc_id_get(void)
{
	return spmc_attrs.spmc_id;
}

83
84
85
/*******************************************************************************
 * Static function declaration.
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
86
static int32_t spmd_init(void);
87
static int spmd_spmc_init(void *pm_addr);
J-Alves's avatar
J-Alves committed
88
static uint64_t spmd_ffa_error_return(void *handle,
Olivier Deprez's avatar
Olivier Deprez committed
89
90
91
92
93
94
95
96
				       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);
97
98

/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
99
100
 * This function takes an SPMC context pointer and performs a synchronous
 * SPMC entry.
101
102
103
104
105
106
107
108
109
110
 ******************************************************************************/
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 */
111
#if SPMD_SPM_AT_SEL2
112
	cm_el2_sysregs_context_restore(SECURE);
113
114
#else
	cm_el1_sysregs_context_restore(SECURE);
115
#endif
116
117
	cm_set_next_eret_context(SECURE);

118
	/* Enter SPMC */
119
120
121
	rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx);

	/* Save secure state */
122
#if SPMD_SPM_AT_SEL2
123
	cm_el2_sysregs_context_save(SECURE);
124
125
#else
	cm_el1_sysregs_context_save(SECURE);
126
#endif
127
128
129
130
131

	return rc;
}

/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
132
 * This function returns to the place where spmd_spm_core_sync_entry() was
133
134
135
136
 * called originally.
 ******************************************************************************/
__dead2 void spmd_spm_core_sync_exit(uint64_t rc)
{
Olivier Deprez's avatar
Olivier Deprez committed
137
	spmd_spm_core_context_t *ctx = spmd_get_context();
138

Olivier Deprez's avatar
Olivier Deprez committed
139
	/* Get current CPU context from SPMC context */
140
141
142
143
144
145
146
147
148
149
150
151
152
	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
153
 * Jump to the SPM Core for the first time.
154
155
156
 ******************************************************************************/
static int32_t spmd_init(void)
{
Olivier Deprez's avatar
Olivier Deprez committed
157
158
	spmd_spm_core_context_t *ctx = spmd_get_context();
	uint64_t rc;
159
160
	unsigned int linear_id = plat_my_core_pos();
	unsigned int core_id;
161

Olivier Deprez's avatar
Olivier Deprez committed
162
	VERBOSE("SPM Core init start.\n");
163
164
165
	ctx->state = SPMC_STATE_ON_PENDING;

	/* Set the SPMC context state on other CPUs to OFF */
166
	for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) {
167
168
169
170
		if (core_id != linear_id) {
			spm_core_context[core_id].state = SPMC_STATE_OFF;
		}
	}
171
172

	rc = spmd_spm_core_sync_entry(ctx);
Olivier Deprez's avatar
Olivier Deprez committed
173
	if (rc != 0ULL) {
174
		ERROR("SPMC initialisation failed 0x%llx\n", rc);
Olivier Deprez's avatar
Olivier Deprez committed
175
		return 0;
176
177
	}

178
179
	ctx->state = SPMC_STATE_ON;

Olivier Deprez's avatar
Olivier Deprez committed
180
	VERBOSE("SPM Core init end.\n");
181
182
183
184
185

	return 1;
}

/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
186
 * Loads SPMC manifest and inits SPMC.
187
 ******************************************************************************/
188
static int spmd_spmc_init(void *pm_addr)
189
{
Olivier Deprez's avatar
Olivier Deprez committed
190
	spmd_spm_core_context_t *spm_ctx = spmd_get_context();
191
	uint32_t ep_attr;
Olivier Deprez's avatar
Olivier Deprez committed
192
	int rc;
193

Olivier Deprez's avatar
Olivier Deprez committed
194
	/* Load the SPM Core manifest */
195
	rc = plat_spm_core_manifest_load(&spmc_attrs, pm_addr);
196
	if (rc != 0) {
Olivier Deprez's avatar
Olivier Deprez committed
197
198
		WARN("No or invalid SPM Core manifest image provided by BL2\n");
		return rc;
199
200
201
	}

	/*
Olivier Deprez's avatar
Olivier Deprez committed
202
203
	 * Ensure that the SPM Core version is compatible with the SPM
	 * Dispatcher version.
204
	 */
J-Alves's avatar
J-Alves committed
205
206
207
	if ((spmc_attrs.major_version != FFA_VERSION_MAJOR) ||
	    (spmc_attrs.minor_version > FFA_VERSION_MINOR)) {
		WARN("Unsupported FFA version (%u.%u)\n",
208
		     spmc_attrs.major_version, spmc_attrs.minor_version);
Olivier Deprez's avatar
Olivier Deprez committed
209
		return -EINVAL;
210
211
	}

J-Alves's avatar
J-Alves committed
212
	VERBOSE("FFA version (%u.%u)\n", spmc_attrs.major_version,
213
214
	     spmc_attrs.minor_version);

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

218
	/* Validate the SPMC ID, Ensure high bit is set */
Olivier Deprez's avatar
Olivier Deprez committed
219
220
221
222
	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;
223
224
	}

Olivier Deprez's avatar
Olivier Deprez committed
225
	/* Validate the SPM Core execution state */
226
227
	if ((spmc_attrs.exec_state != MODE_RW_64) &&
	    (spmc_attrs.exec_state != MODE_RW_32)) {
228
		WARN("Unsupported %s%x.\n", "SPM Core execution state 0x",
229
		     spmc_attrs.exec_state);
Olivier Deprez's avatar
Olivier Deprez committed
230
		return -EINVAL;
231
232
	}

233
234
	VERBOSE("%s%x.\n", "SPM Core execution state 0x",
		spmc_attrs.exec_state);
235

236
237
238
239
#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
240
		return -EINVAL;
241
242
243
244
245
246
	}

	/*
	 * Check if S-EL2 is supported on this system if S-EL2
	 * is required for SPM
	 */
Olivier Deprez's avatar
Olivier Deprez committed
247
248
249
	if (!is_armv8_4_sel2_present()) {
		WARN("SPM Core run time S-EL2 is not supported.\n");
		return -EINVAL;
250
	}
251
#endif /* SPMD_SPM_AT_SEL2 */
252
253
254

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

259
260
261
	SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr);

	/*
Olivier Deprez's avatar
Olivier Deprez committed
262
263
	 * Populate SPSR for SPM Core based upon validated parameters from the
	 * manifest.
264
265
266
267
268
269
270
271
	 */
	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 {
272
273
274
275
276
277
278

#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,
279
280
281
282
					     MODE_SP_ELX,
					     DISABLE_ALL_EXCEPTIONS);
	}

Olivier Deprez's avatar
Olivier Deprez committed
283
	/* Initialise SPM Core context with this entry point information */
284
285
286
287
	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;
288

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

291
292
293
	/* Register power management hooks with PSCI */
	psci_register_spd_pm_hook(&spmd_pm);

Olivier Deprez's avatar
Olivier Deprez committed
294
	/* Register init function for deferred init. */
295
296
297
	bl31_register_bl32_init(&spmd_init);

	return 0;
298
}
299

300
/*******************************************************************************
Olivier Deprez's avatar
Olivier Deprez committed
301
 * Initialize context of SPM Core.
302
303
304
 ******************************************************************************/
int spmd_setup(void)
{
305
	void *spmc_manifest;
306
	int rc;
307

308
	spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
Olivier Deprez's avatar
Olivier Deprez committed
309
310
311
	if (spmc_ep_info == NULL) {
		WARN("No SPM Core image provided by BL2 boot loader.\n");
		return -EINVAL;
312
313
314
	}

	/* Under no circumstances will this parameter be 0 */
Olivier Deprez's avatar
Olivier Deprez committed
315
	assert(spmc_ep_info->pc != 0ULL);
316
317
318

	/*
	 * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will
Olivier Deprez's avatar
Olivier Deprez committed
319
	 * be used as a manifest for the SPM Core at the next lower EL/mode.
320
	 */
321
322
323
324
	spmc_manifest = (void *)spmc_ep_info->args.arg0;
	if (spmc_manifest == NULL) {
		ERROR("Invalid or absent SPM Core manifest.\n");
		return -EINVAL;
325
326
327
	}

	/* Load manifest, init SPMC */
328
	rc = spmd_spmc_init(spmc_manifest);
329
	if (rc != 0) {
Olivier Deprez's avatar
Olivier Deprez committed
330
		WARN("Booting device without SPM initialization.\n");
331
332
	}

333
	return rc;
334
335
336
337
338
}

/*******************************************************************************
 * Forward SMC to the other security state
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
339
340
341
342
343
344
345
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)
346
{
347
348
	unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE;
	unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE;
349

350
	/* Save incoming security state */
351
#if SPMD_SPM_AT_SEL2
352
353
354
	if (secure_state_in == NON_SECURE) {
		cm_el1_sysregs_context_save(secure_state_in);
	}
355
	cm_el2_sysregs_context_save(secure_state_in);
356
357
#else
	cm_el1_sysregs_context_save(secure_state_in);
358
#endif
359
360

	/* Restore outgoing security state */
361
#if SPMD_SPM_AT_SEL2
362
363
364
	if (secure_state_out == NON_SECURE) {
		cm_el1_sysregs_context_restore(secure_state_out);
	}
365
	cm_el2_sysregs_context_restore(secure_state_out);
366
367
#else
	cm_el1_sysregs_context_restore(secure_state_out);
368
#endif
369
	cm_set_next_eret_context(secure_state_out);
370

371
	SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
372
373
374
375
376
377
			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
378
 * Return FFA_ERROR with specified error code
379
 ******************************************************************************/
J-Alves's avatar
J-Alves committed
380
static uint64_t spmd_ffa_error_return(void *handle, int error_code)
381
{
382
383
	SMC_RET8(handle, (uint32_t) FFA_ERROR,
		 FFA_TARGET_INFO_MBZ, (uint32_t)error_code,
J-Alves's avatar
J-Alves committed
384
385
		 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
		 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
386
387
}

388
389
390
391
392
393
394
395
396
397
398
/*******************************************************************************
 * 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)));
}

399
400
401
402
403
404
405
406
407
/******************************************************************************
 * 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));
}

408
409
410
/******************************************************************************
 * spmd_handle_spmc_message
 *****************************************************************************/
411
412
413
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)
414
415
416
417
418
419
420
{
	VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__,
		msg, parm1, parm2, parm3, parm4);

	return -EINVAL;
}

421
/*******************************************************************************
J-Alves's avatar
J-Alves committed
422
 * This function handles all SMCs in the range reserved for FFA. Each call is
423
424
 * either forwarded to the other security state or handled by the SPM dispatcher
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
425
426
427
428
429
430
431
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,
432
433
			  uint64_t flags)
{
434
	unsigned int linear_id = plat_my_core_pos();
Olivier Deprez's avatar
Olivier Deprez committed
435
	spmd_spm_core_context_t *ctx = spmd_get_context();
436
437
	bool secure_origin;
	int32_t ret;
J-Alves's avatar
J-Alves committed
438
	uint32_t input_version;
439
440

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

443
444
445
446
447
448
	VERBOSE("SPM(%u): 0x%x 0x%llx 0x%llx 0x%llx 0x%llx "
		"0x%llx 0x%llx 0x%llx\n",
		linear_id, 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));
449
450

	switch (smc_fid) {
J-Alves's avatar
J-Alves committed
451
	case FFA_ERROR:
452
453
		/*
		 * Check if this is the first invocation of this interface on
Olivier Deprez's avatar
Olivier Deprez committed
454
		 * this CPU. If so, then indicate that the SPM Core initialised
455
456
		 * unsuccessfully.
		 */
457
		if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
458
			spmd_spm_core_sync_exit(x2);
459
		}
460

461
		return spmd_smc_forward(smc_fid, secure_origin,
462
					x1, x2, x3, x4, handle);
463
464
		break; /* not reached */

J-Alves's avatar
J-Alves committed
465
	case FFA_VERSION:
J-Alves's avatar
J-Alves committed
466
		input_version = (uint32_t)(0xFFFFFFFF & x1);
467
		/*
J-Alves's avatar
J-Alves committed
468
469
470
471
472
		 * 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".
473
		 */
J-Alves's avatar
J-Alves committed
474
475
476
477
		if ((input_version & FFA_VERSION_BIT31_MASK) ||
			(ctx->state == SPMC_STATE_RESET)) {
			ret = FFA_ERROR_NOT_SUPPORTED;
		} else if (!secure_origin) {
478
479
			ret = MAKE_FFA_VERSION(spmc_attrs.major_version,
					       spmc_attrs.minor_version);
J-Alves's avatar
J-Alves committed
480
		} else {
481
482
			ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR,
					       FFA_VERSION_MINOR);
J-Alves's avatar
J-Alves committed
483
484
		}

485
486
487
		SMC_RET8(handle, (uint32_t)ret, FFA_TARGET_INFO_MBZ,
			 FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
			 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
488
489
		break; /* not reached */

J-Alves's avatar
J-Alves committed
490
	case FFA_FEATURES:
491
492
		/*
		 * This is an optional interface. Do the minimal checks and
Olivier Deprez's avatar
Olivier Deprez committed
493
		 * forward to SPM Core which will handle it if implemented.
494
495
496
		 */

		/*
J-Alves's avatar
J-Alves committed
497
		 * Check if x1 holds a valid FFA fid. This is an
498
499
		 * optimization.
		 */
J-Alves's avatar
J-Alves committed
500
501
		if (!is_ffa_fid(x1)) {
			return spmd_ffa_error_return(handle,
502
						     FFA_ERROR_NOT_SUPPORTED);
503
		}
504

Olivier Deprez's avatar
Olivier Deprez committed
505
		/* Forward SMC from Normal world to the SPM Core */
506
507
		if (!secure_origin) {
			return spmd_smc_forward(smc_fid, secure_origin,
508
						x1, x2, x3, x4, handle);
509
		}
510

Olivier Deprez's avatar
Olivier Deprez committed
511
512
		/*
		 * Return success if call was from secure world i.e. all
J-Alves's avatar
J-Alves committed
513
		 * FFA functions are supported. This is essentially a
Olivier Deprez's avatar
Olivier Deprez committed
514
515
		 * nop.
		 */
J-Alves's avatar
J-Alves committed
516
		SMC_RET8(handle, FFA_SUCCESS_SMC32, x1, x2, x3, x4,
Olivier Deprez's avatar
Olivier Deprez committed
517
518
519
520
			 SMC_GET_GP(handle, CTX_GPREG_X5),
			 SMC_GET_GP(handle, CTX_GPREG_X6),
			 SMC_GET_GP(handle, CTX_GPREG_X7));

521
522
		break; /* not reached */

J-Alves's avatar
J-Alves committed
523
	case FFA_ID_GET:
524
		/*
J-Alves's avatar
J-Alves committed
525
		 * Returns the ID of the calling FFA component.
Olivier Deprez's avatar
Olivier Deprez committed
526
		 */
527
		if (!secure_origin) {
J-Alves's avatar
J-Alves committed
528
529
530
531
532
			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);
533
534
		}

J-Alves's avatar
J-Alves committed
535
536
537
538
539
		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
540

541
542
		break; /* not reached */

543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
	case FFA_SECONDARY_EP_REGISTER_SMC64:
		if (secure_origin) {
			ret = spmd_pm_secondary_ep_register(x1);

			if (ret < 0) {
				SMC_RET8(handle, FFA_ERROR_SMC64,
					FFA_TARGET_INFO_MBZ, ret,
					FFA_PARAM_MBZ, FFA_PARAM_MBZ,
					FFA_PARAM_MBZ, FFA_PARAM_MBZ,
					FFA_PARAM_MBZ);
			} else {
				SMC_RET8(handle, FFA_SUCCESS_SMC64,
					FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ,
					FFA_PARAM_MBZ, FFA_PARAM_MBZ,
					FFA_PARAM_MBZ, FFA_PARAM_MBZ,
					FFA_PARAM_MBZ);
			}
		}

		return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
		break; /* Not reached */

565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
	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
594
595
596
597
	case FFA_RX_RELEASE:
	case FFA_RXTX_MAP_SMC32:
	case FFA_RXTX_MAP_SMC64:
	case FFA_RXTX_UNMAP:
598
599
600
601
602
603
604
	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
605
	case FFA_MSG_RUN:
606
		/* This interface must be invoked only by the Normal world */
607

608
		if (secure_origin) {
J-Alves's avatar
J-Alves committed
609
			return spmd_ffa_error_return(handle,
610
						     FFA_ERROR_NOT_SUPPORTED);
611
612
613
		}

		/* Fall through to forward the call to the other world */
J-Alves's avatar
J-Alves committed
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
	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:
630
631
632
633
634
635
636
		/*
		 * 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.
		 */

637
		return spmd_smc_forward(smc_fid, secure_origin,
638
					x1, x2, x3, x4, handle);
639
640
		break; /* not reached */

J-Alves's avatar
J-Alves committed
641
	case FFA_MSG_WAIT:
642
643
644
		/*
		 * 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
645
		 * SPM Core initialised successfully.
646
		 */
647
		if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
648
649
650
			spmd_spm_core_sync_exit(0);
		}

651
		/* Fall through to forward the call to the other world */
652
	case FFA_INTERRUPT:
J-Alves's avatar
J-Alves committed
653
	case FFA_MSG_YIELD:
654
		/* This interface must be invoked only by the Secure world */
655
		if (!secure_origin) {
J-Alves's avatar
J-Alves committed
656
657
			return spmd_ffa_error_return(handle,
						      FFA_ERROR_NOT_SUPPORTED);
658
659
		}

660
		return spmd_smc_forward(smc_fid, secure_origin,
661
					x1, x2, x3, x4, handle);
662
663
664
665
		break; /* not reached */

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