spmd_main.c 19.3 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
111
 ******************************************************************************/
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);
112
#if SPMD_SPM_AT_SEL2
113
	cm_el2_sysregs_context_restore(SECURE);
114
#endif
115
116
	cm_set_next_eret_context(SECURE);

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

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

	return rc;
}

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

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

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

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

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

176
177
	ctx->state = SPMC_STATE_ON;

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

	return 1;
}

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

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

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

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

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

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

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

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

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

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

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

257
258
259
	SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr);

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

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

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

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

289
290
291
	/* Register power management hooks with PSCI */
	psci_register_spd_pm_hook(&spmd_pm);

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

	return 0;
296
}
297

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

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

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

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

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

331
	return rc;
332
333
334
335
336
}

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

348
	/* Save incoming security state */
349
	cm_el1_sysregs_context_save(secure_state_in);
350
#if SPMD_SPM_AT_SEL2
351
	cm_el2_sysregs_context_save(secure_state_in);
352
#endif
353
354

	/* Restore outgoing security state */
355
	cm_el1_sysregs_context_restore(secure_state_out);
356
#if SPMD_SPM_AT_SEL2
357
	cm_el2_sysregs_context_restore(secure_state_out);
358
#endif
359
	cm_set_next_eret_context(secure_state_out);
360

361
	SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
362
363
364
365
366
367
			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
368
 * Return FFA_ERROR with specified error code
369
 ******************************************************************************/
J-Alves's avatar
J-Alves committed
370
static uint64_t spmd_ffa_error_return(void *handle, int error_code)
371
{
J-Alves's avatar
J-Alves committed
372
373
374
375
	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);
376
377
}

378
379
380
381
382
383
384
385
386
387
388
/*******************************************************************************
 * 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)));
}

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

398
399
400
/******************************************************************************
 * spmd_handle_spmc_message
 *****************************************************************************/
401
402
403
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)
404
405
406
407
408
409
410
{
	VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__,
		msg, parm1, parm2, parm3, parm4);

	return -EINVAL;
}

411
/*******************************************************************************
J-Alves's avatar
J-Alves committed
412
 * This function handles all SMCs in the range reserved for FFA. Each call is
413
414
 * either forwarded to the other security state or handled by the SPM dispatcher
 ******************************************************************************/
Olivier Deprez's avatar
Olivier Deprez committed
415
416
417
418
419
420
421
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,
422
423
			  uint64_t flags)
{
424
	unsigned int linear_id = plat_my_core_pos();
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

433
434
435
436
437
438
	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));
439
440

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

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

J-Alves's avatar
J-Alves committed
455
	case FFA_VERSION:
J-Alves's avatar
J-Alves committed
456
		input_version = (uint32_t)(0xFFFFFFFF & x1);
457
		/*
J-Alves's avatar
J-Alves committed
458
459
460
461
462
		 * 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".
463
		 */
J-Alves's avatar
J-Alves committed
464
465
466
467
468
469
470
471
472
473
		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
474
475
			 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
			 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
476
477
		break; /* not reached */

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

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

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

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

509
510
		break; /* not reached */

J-Alves's avatar
J-Alves committed
511
	case FFA_ID_GET:
512
		/*
J-Alves's avatar
J-Alves committed
513
		 * Returns the ID of the calling FFA component.
Olivier Deprez's avatar
Olivier Deprez committed
514
		 */
515
		if (!secure_origin) {
J-Alves's avatar
J-Alves committed
516
517
518
519
520
			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);
521
522
		}

J-Alves's avatar
J-Alves committed
523
524
525
526
527
		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
528

529
530
		break; /* not reached */

531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
	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 */

553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
	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
582
583
584
585
	case FFA_RX_RELEASE:
	case FFA_RXTX_MAP_SMC32:
	case FFA_RXTX_MAP_SMC64:
	case FFA_RXTX_UNMAP:
586
587
588
589
590
591
592
	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
593
	case FFA_MSG_RUN:
594
		/* This interface must be invoked only by the Normal world */
595

596
		if (secure_origin) {
J-Alves's avatar
J-Alves committed
597
			return spmd_ffa_error_return(handle,
598
						     FFA_ERROR_NOT_SUPPORTED);
599
600
601
		}

		/* Fall through to forward the call to the other world */
J-Alves's avatar
J-Alves committed
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
	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:
618
619
620
621
622
623
624
		/*
		 * 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.
		 */

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

J-Alves's avatar
J-Alves committed
629
	case FFA_MSG_WAIT:
630
631
632
		/*
		 * 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
633
		 * SPM Core initialised successfully.
634
		 */
635
		if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
636
637
638
			spmd_spm_core_sync_exit(0);
		}

639
		/* Fall through to forward the call to the other world */
640

J-Alves's avatar
J-Alves committed
641
	case FFA_MSG_YIELD:
642
		/* This interface must be invoked only by the Secure world */
643
		if (!secure_origin) {
J-Alves's avatar
J-Alves committed
644
645
			return spmd_ffa_error_return(handle,
						      FFA_ERROR_NOT_SUPPORTED);
646
647
		}

648
		return spmd_smc_forward(smc_fid, secure_origin,
649
					x1, x2, x3, x4, handle);
650
651
652
653
		break; /* not reached */

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