xref: /rk3399_ARM-atf/services/std_svc/spm/el3_spmc/spmc_shared_mem.c (revision f0244e5dd1b8cbab75ef00c1b9b56eed5b3cad4b)
1 /*
2  * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <errno.h>
7 
8 #include <common/debug.h>
9 #include <common/runtime_svc.h>
10 #include <lib/object_pool.h>
11 #include <lib/spinlock.h>
12 #include <lib/xlat_tables/xlat_tables_v2.h>
13 #include <services/ffa_svc.h>
14 #include "spmc.h"
15 #include "spmc_shared_mem.h"
16 
17 #include <platform_def.h>
18 
19 /**
20  * struct spmc_shmem_obj - Shared memory object.
21  * @desc_size:      Size of @desc.
22  * @desc_filled:    Size of @desc already received.
23  * @in_use:         Number of clients that have called ffa_mem_retrieve_req
24  *                  without a matching ffa_mem_relinquish call.
25  * @desc:           FF-A memory region descriptor passed in ffa_mem_share.
26  */
27 struct spmc_shmem_obj {
28 	size_t desc_size;
29 	size_t desc_filled;
30 	size_t in_use;
31 	struct ffa_mtd_v1_0 desc;
32 };
33 
34 /*
35  * Declare our data structure to store the metadata of memory share requests.
36  * The main datastore is allocated on a per platform basis to ensure enough
37  * storage can be made available.
38  * The address of the data store will be populated by the SPMC during its
39  * initialization.
40  */
41 
42 struct spmc_shmem_obj_state spmc_shmem_obj_state = {
43 	/* Set start value for handle so top 32 bits are needed quickly. */
44 	.next_handle = 0xffffffc0U,
45 };
46 
47 /**
48  * spmc_shmem_obj_size - Convert from descriptor size to object size.
49  * @desc_size:  Size of struct ffa_memory_region_descriptor object.
50  *
51  * Return: Size of struct spmc_shmem_obj object.
52  */
53 static size_t spmc_shmem_obj_size(size_t desc_size)
54 {
55 	return desc_size + offsetof(struct spmc_shmem_obj, desc);
56 }
57 
58 /**
59  * spmc_shmem_obj_alloc - Allocate struct spmc_shmem_obj.
60  * @state:      Global state.
61  * @desc_size:  Size of struct ffa_memory_region_descriptor object that
62  *              allocated object will hold.
63  *
64  * Return: Pointer to newly allocated object, or %NULL if there not enough space
65  *         left. The returned pointer is only valid while @state is locked, to
66  *         used it again after unlocking @state, spmc_shmem_obj_lookup must be
67  *         called.
68  */
69 static struct spmc_shmem_obj *
70 spmc_shmem_obj_alloc(struct spmc_shmem_obj_state *state, size_t desc_size)
71 {
72 	struct spmc_shmem_obj *obj;
73 	size_t free = state->data_size - state->allocated;
74 
75 	if (state->data == NULL) {
76 		ERROR("Missing shmem datastore!\n");
77 		return NULL;
78 	}
79 
80 	if (spmc_shmem_obj_size(desc_size) > free) {
81 		WARN("%s(0x%zx) failed, free 0x%zx\n",
82 		     __func__, desc_size, free);
83 		return NULL;
84 	}
85 	obj = (struct spmc_shmem_obj *)(state->data + state->allocated);
86 	obj->desc = (struct ffa_mtd_v1_0) {0};
87 	obj->desc_size = desc_size;
88 	obj->desc_filled = 0;
89 	obj->in_use = 0;
90 	state->allocated += spmc_shmem_obj_size(desc_size);
91 	return obj;
92 }
93 
94 /**
95  * spmc_shmem_obj_free - Free struct spmc_shmem_obj.
96  * @state:      Global state.
97  * @obj:        Object to free.
98  *
99  * Release memory used by @obj. Other objects may move, so on return all
100  * pointers to struct spmc_shmem_obj object should be considered invalid, not
101  * just @obj.
102  *
103  * The current implementation always compacts the remaining objects to simplify
104  * the allocator and to avoid fragmentation.
105  */
106 
107 static void spmc_shmem_obj_free(struct spmc_shmem_obj_state *state,
108 				  struct spmc_shmem_obj *obj)
109 {
110 	size_t free_size = spmc_shmem_obj_size(obj->desc_size);
111 	uint8_t *shift_dest = (uint8_t *)obj;
112 	uint8_t *shift_src = shift_dest + free_size;
113 	size_t shift_size = state->allocated - (shift_src - state->data);
114 
115 	if (shift_size != 0U) {
116 		memmove(shift_dest, shift_src, shift_size);
117 	}
118 	state->allocated -= free_size;
119 }
120 
121 /**
122  * spmc_shmem_obj_lookup - Lookup struct spmc_shmem_obj by handle.
123  * @state:      Global state.
124  * @handle:     Unique handle of object to return.
125  *
126  * Return: struct spmc_shmem_obj_state object with handle matching @handle.
127  *         %NULL, if not object in @state->data has a matching handle.
128  */
129 static struct spmc_shmem_obj *
130 spmc_shmem_obj_lookup(struct spmc_shmem_obj_state *state, uint64_t handle)
131 {
132 	uint8_t *curr = state->data;
133 
134 	while (curr - state->data < state->allocated) {
135 		struct spmc_shmem_obj *obj = (struct spmc_shmem_obj *)curr;
136 
137 		if (obj->desc.handle == handle) {
138 			return obj;
139 		}
140 		curr += spmc_shmem_obj_size(obj->desc_size);
141 	}
142 	return NULL;
143 }
144 
145 static struct ffa_comp_mrd *
146 spmc_shmem_obj_get_comp_mrd(struct spmc_shmem_obj *obj)
147 {
148 	return (struct ffa_comp_mrd *)
149 		((uint8_t *)(&obj->desc) + obj->desc.emad[0].comp_mrd_offset);
150 }
151 
152 /**
153  * spmc_shmem_obj_ffa_constituent_size - Calculate variable size part of obj.
154  * @obj:    Object containing ffa_memory_region_descriptor.
155  *
156  * Return: Size of ffa_constituent_memory_region_descriptors in @obj.
157  */
158 static size_t
159 spmc_shmem_obj_ffa_constituent_size(struct spmc_shmem_obj *obj)
160 {
161 	return spmc_shmem_obj_get_comp_mrd(obj)->address_range_count *
162 		sizeof(struct ffa_cons_mrd);
163 }
164 
165 /**
166  * spmc_shmem_check_obj - Check that counts in descriptor match overall size.
167  * @obj:    Object containing ffa_memory_region_descriptor.
168  *
169  * Return: 0 if object is valid, -EINVAL if constituent_memory_region_descriptor
170  * offset or count is invalid.
171  */
172 static int spmc_shmem_check_obj(struct spmc_shmem_obj *obj)
173 {
174 	if (obj->desc.emad_count == 0U) {
175 		WARN("%s: unsupported attribute desc count %u.\n",
176 		     __func__, obj->desc.emad_count);
177 		return -EINVAL;
178 	}
179 
180 	/*
181 	 * Ensure the emad array lies within the bounds of the descriptor by
182 	 * checking the address of the element past the end of the array.
183 	 */
184 	if ((uintptr_t) &obj->desc.emad[obj->desc.emad_count] >
185 	    (uintptr_t)((uint8_t *) &obj->desc + obj->desc_size)) {
186 		WARN("Invalid emad access.\n");
187 		return -EINVAL;
188 	}
189 
190 	for (size_t emad_num = 0; emad_num < obj->desc.emad_count; emad_num++) {
191 		size_t size;
192 		size_t count;
193 		size_t expected_size;
194 		size_t total_page_count;
195 		struct ffa_comp_mrd *comp;
196 
197 		uint32_t offset = obj->desc.emad[emad_num].comp_mrd_offset;
198 		size_t header_emad_size = sizeof(obj->desc) +
199 			obj->desc.emad_count * sizeof(obj->desc.emad[emad_num]);
200 
201 		if (offset < header_emad_size) {
202 			WARN("%s: invalid object, offset %u < header + emad %zu\n",
203 			     __func__, offset, header_emad_size);
204 			return -EINVAL;
205 		}
206 
207 		size = obj->desc_size;
208 
209 		if (offset > size) {
210 			WARN("%s: invalid object, offset %u > total size %zu\n",
211 			     __func__, offset, obj->desc_size);
212 			return -EINVAL;
213 		}
214 		size -= offset;
215 
216 		if (size < sizeof(struct ffa_comp_mrd)) {
217 			WARN("%s: invalid object, offset %u, total size %zu, no header space.\n",
218 			     __func__, offset, obj->desc_size);
219 			return -EINVAL;
220 		}
221 		size -= sizeof(struct ffa_comp_mrd);
222 
223 		count = size / sizeof(struct ffa_cons_mrd);
224 
225 		comp = spmc_shmem_obj_get_comp_mrd(obj);
226 
227 		if (comp->address_range_count != count) {
228 			WARN("%s: invalid object, desc count %u != %zu\n",
229 			     __func__, comp->address_range_count, count);
230 			return -EINVAL;
231 		}
232 
233 		expected_size = offset + sizeof(*comp) +
234 				spmc_shmem_obj_ffa_constituent_size(obj);
235 		if (expected_size != obj->desc_size) {
236 			WARN("%s: invalid object, computed size %zu != size %zu\n",
237 			       __func__, expected_size, obj->desc_size);
238 			return -EINVAL;
239 		}
240 
241 		if (obj->desc_filled < obj->desc_size) {
242 			/*
243 			 * The whole descriptor has not yet been received.
244 			 * Skip final checks.
245 			 */
246 			return 0;
247 		}
248 
249 		total_page_count = 0;
250 
251 		for (size_t i = 0; i < count; i++) {
252 			total_page_count +=
253 				comp->address_range_array[i].page_count;
254 		}
255 		if (comp->total_page_count != total_page_count) {
256 			WARN("%s: invalid object, desc total_page_count %u != %zu\n",
257 			     __func__, comp->total_page_count,
258 			total_page_count);
259 			return -EINVAL;
260 		}
261 	}
262 
263 	return 0;
264 }
265 
266 static long spmc_ffa_fill_desc(struct mailbox *mbox,
267 			       struct spmc_shmem_obj *obj,
268 			       uint32_t fragment_length,
269 			       ffa_mtd_flag32_t mtd_flag,
270 			       void *smc_handle)
271 {
272 	int ret;
273 	uint32_t handle_low;
274 	uint32_t handle_high;
275 
276 	if (mbox->rxtx_page_count == 0U) {
277 		WARN("%s: buffer pair not registered.\n", __func__);
278 		ret = -EINVAL;
279 		goto err_arg;
280 	}
281 
282 	if (fragment_length > mbox->rxtx_page_count * PAGE_SIZE_4KB) {
283 		WARN("%s: bad fragment size %u > %u buffer size\n", __func__,
284 		     fragment_length, mbox->rxtx_page_count * PAGE_SIZE_4KB);
285 		ret = -EINVAL;
286 		goto err_arg;
287 	}
288 
289 	memcpy((uint8_t *)&obj->desc + obj->desc_filled,
290 	       (uint8_t *) mbox->tx_buffer,
291 	       fragment_length);
292 
293 	if (fragment_length > obj->desc_size - obj->desc_filled) {
294 		WARN("%s: bad fragment size %u > %zu remaining\n", __func__,
295 		     fragment_length, obj->desc_size - obj->desc_filled);
296 		ret = -EINVAL;
297 		goto err_arg;
298 	}
299 
300 	/* Ensure that the sender ID resides in the normal world. */
301 	if (ffa_is_secure_world_id(obj->desc.sender_id)) {
302 		WARN("%s: Invalid sender ID 0x%x.\n",
303 		     __func__, obj->desc.sender_id);
304 		ret = FFA_ERROR_DENIED;
305 		goto err_arg;
306 	}
307 
308 	/*
309 	 * We don't currently support any optional flags so ensure none are
310 	 * requested.
311 	 */
312 	if (obj->desc.flags != 0U && mtd_flag != 0U &&
313 	    (obj->desc.flags != mtd_flag)) {
314 		WARN("%s: invalid memory transaction flags %u != %u\n",
315 		     __func__, obj->desc.flags, mtd_flag);
316 		ret = -EINVAL;
317 		goto err_arg;
318 	}
319 
320 	if (obj->desc_filled == 0U) {
321 		/* First fragment, descriptor header has been copied */
322 		obj->desc.handle = spmc_shmem_obj_state.next_handle++;
323 		obj->desc.flags |= mtd_flag;
324 	}
325 
326 	obj->desc_filled += fragment_length;
327 
328 	ret = spmc_shmem_check_obj(obj);
329 	if (ret != 0) {
330 		goto err_bad_desc;
331 	}
332 
333 	handle_low = (uint32_t)obj->desc.handle;
334 	handle_high = obj->desc.handle >> 32;
335 
336 	if (obj->desc_filled != obj->desc_size) {
337 		SMC_RET8(smc_handle, FFA_MEM_FRAG_RX, handle_low,
338 			 handle_high, obj->desc_filled,
339 			 (uint32_t)obj->desc.sender_id << 16, 0, 0, 0);
340 	}
341 
342 	/* The full descriptor has been received, perform any final checks. */
343 
344 	/*
345 	 * If a partition ID resides in the secure world validate that the
346 	 * partition ID is for a known partition. Ignore any partition ID
347 	 * belonging to the normal world as it is assumed the Hypervisor will
348 	 * have validated these.
349 	 */
350 	for (size_t i = 0; i < obj->desc.emad_count; i++) {
351 		ffa_endpoint_id16_t ep_id = obj->desc.emad[i].mapd.endpoint_id;
352 
353 		if (ffa_is_secure_world_id(ep_id)) {
354 			if (spmc_get_sp_ctx(ep_id) == NULL) {
355 				WARN("%s: Invalid receiver id 0x%x\n",
356 				     __func__, ep_id);
357 				ret = FFA_ERROR_INVALID_PARAMETER;
358 				goto err_bad_desc;
359 			}
360 		}
361 	}
362 
363 	/* Ensure partition IDs are not duplicated. */
364 	for (size_t i = 0; i < obj->desc.emad_count; i++) {
365 		for (size_t j = i + 1; j < obj->desc.emad_count; j++) {
366 			if (obj->desc.emad[i].mapd.endpoint_id ==
367 				obj->desc.emad[j].mapd.endpoint_id) {
368 				ret = FFA_ERROR_INVALID_PARAMETER;
369 				goto err_bad_desc;
370 			}
371 		}
372 	}
373 
374 	SMC_RET8(smc_handle, FFA_SUCCESS_SMC32, 0, handle_low, handle_high, 0,
375 		 0, 0, 0);
376 
377 err_bad_desc:
378 err_arg:
379 	spmc_shmem_obj_free(&spmc_shmem_obj_state, obj);
380 	return spmc_ffa_error_return(smc_handle, FFA_ERROR_INVALID_PARAMETER);
381 }
382 
383 /**
384  * spmc_ffa_mem_send - FFA_MEM_SHARE/LEND implementation.
385  * @client:             Client state.
386  * @total_length:       Total length of shared memory descriptor.
387  * @fragment_length:    Length of fragment of shared memory descriptor passed in
388  *                      this call.
389  * @address:            Not supported, must be 0.
390  * @page_count:         Not supported, must be 0.
391  * @smc_handle:         Handle passed to smc call. Used to return
392  *                      FFA_MEM_FRAG_RX or SMC_FC_FFA_SUCCESS.
393  *
394  * Implements a subset of the FF-A FFA_MEM_SHARE and FFA_MEM_LEND calls needed
395  * to share or lend memory from non-secure os to secure os (with no stream
396  * endpoints).
397  *
398  * Return: 0 on success, error code on failure.
399  */
400 long spmc_ffa_mem_send(uint32_t smc_fid,
401 			bool secure_origin,
402 			uint64_t total_length,
403 			uint32_t fragment_length,
404 			uint64_t address,
405 			uint32_t page_count,
406 			void *cookie,
407 			void *handle,
408 			uint64_t flags)
409 
410 {
411 	long ret;
412 	struct spmc_shmem_obj *obj;
413 	struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
414 	ffa_mtd_flag32_t mtd_flag;
415 
416 	if (address != 0U || page_count != 0U) {
417 		WARN("%s: custom memory region for message not supported.\n",
418 		     __func__);
419 		return spmc_ffa_error_return(handle,
420 					     FFA_ERROR_INVALID_PARAMETER);
421 	}
422 
423 	if (secure_origin) {
424 		WARN("%s: unsupported share direction.\n", __func__);
425 		return spmc_ffa_error_return(handle,
426 					     FFA_ERROR_INVALID_PARAMETER);
427 	}
428 
429 	if (fragment_length < sizeof(obj->desc)) {
430 		WARN("%s: bad first fragment size %u < %zu\n",
431 		     __func__, fragment_length, sizeof(obj->desc));
432 		return spmc_ffa_error_return(handle,
433 					     FFA_ERROR_INVALID_PARAMETER);
434 	}
435 
436 	if ((smc_fid & FUNCID_NUM_MASK) == FFA_FNUM_MEM_SHARE) {
437 		mtd_flag = FFA_MTD_FLAG_TYPE_SHARE_MEMORY;
438 	} else if ((smc_fid & FUNCID_NUM_MASK) == FFA_FNUM_MEM_LEND) {
439 		mtd_flag = FFA_MTD_FLAG_TYPE_LEND_MEMORY;
440 	} else {
441 		WARN("%s: invalid memory management operation.\n", __func__);
442 		return spmc_ffa_error_return(handle,
443 					     FFA_ERROR_INVALID_PARAMETER);
444 	}
445 
446 	spin_lock(&spmc_shmem_obj_state.lock);
447 
448 	obj = spmc_shmem_obj_alloc(&spmc_shmem_obj_state, total_length);
449 	if (obj == NULL) {
450 		ret = FFA_ERROR_NO_MEMORY;
451 		goto err_unlock;
452 	}
453 
454 	spin_lock(&mbox->lock);
455 	ret = spmc_ffa_fill_desc(mbox, obj, fragment_length, mtd_flag, handle);
456 	spin_unlock(&mbox->lock);
457 
458 	spin_unlock(&spmc_shmem_obj_state.lock);
459 	return ret;
460 
461 err_unlock:
462 	spin_unlock(&spmc_shmem_obj_state.lock);
463 	return spmc_ffa_error_return(handle, ret);
464 }
465 
466 /**
467  * spmc_ffa_mem_frag_tx - FFA_MEM_FRAG_TX implementation.
468  * @client:             Client state.
469  * @handle_low:         Handle_low value returned from FFA_MEM_FRAG_RX.
470  * @handle_high:        Handle_high value returned from FFA_MEM_FRAG_RX.
471  * @fragment_length:    Length of fragments transmitted.
472  * @sender_id:          Vmid of sender in bits [31:16]
473  * @smc_handle:         Handle passed to smc call. Used to return
474  *                      FFA_MEM_FRAG_RX or SMC_FC_FFA_SUCCESS.
475  *
476  * Return: @smc_handle on success, error code on failure.
477  */
478 long spmc_ffa_mem_frag_tx(uint32_t smc_fid,
479 			  bool secure_origin,
480 			  uint64_t handle_low,
481 			  uint64_t handle_high,
482 			  uint32_t fragment_length,
483 			  uint32_t sender_id,
484 			  void *cookie,
485 			  void *handle,
486 			  uint64_t flags)
487 {
488 	long ret;
489 	uint32_t desc_sender_id;
490 	struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
491 
492 	struct spmc_shmem_obj *obj;
493 	uint64_t mem_handle = handle_low | (((uint64_t)handle_high) << 32);
494 
495 	spin_lock(&spmc_shmem_obj_state.lock);
496 
497 	obj = spmc_shmem_obj_lookup(&spmc_shmem_obj_state, mem_handle);
498 	if (obj == NULL) {
499 		WARN("%s: invalid handle, 0x%lx, not a valid handle.\n",
500 		     __func__, mem_handle);
501 		ret = FFA_ERROR_INVALID_PARAMETER;
502 		goto err_unlock;
503 	}
504 
505 	desc_sender_id = (uint32_t)obj->desc.sender_id << 16;
506 	if (sender_id != desc_sender_id) {
507 		WARN("%s: invalid sender_id 0x%x != 0x%x\n", __func__,
508 		     sender_id, desc_sender_id);
509 		ret = FFA_ERROR_INVALID_PARAMETER;
510 		goto err_unlock;
511 	}
512 
513 	if (obj->desc_filled == obj->desc_size) {
514 		WARN("%s: object desc already filled, %zu\n", __func__,
515 		     obj->desc_filled);
516 		ret = FFA_ERROR_INVALID_PARAMETER;
517 		goto err_unlock;
518 	}
519 
520 	spin_lock(&mbox->lock);
521 	ret = spmc_ffa_fill_desc(mbox, obj, fragment_length, 0, handle);
522 	spin_unlock(&mbox->lock);
523 
524 	spin_unlock(&spmc_shmem_obj_state.lock);
525 	return ret;
526 
527 err_unlock:
528 	spin_unlock(&spmc_shmem_obj_state.lock);
529 	return spmc_ffa_error_return(handle, ret);
530 }
531 
532 /**
533  * spmc_ffa_mem_retrieve_req - FFA_MEM_RETRIEVE_REQ implementation.
534  * @smc_fid:            FID of SMC
535  * @total_length:       Total length of retrieve request descriptor if this is
536  *                      the first call. Otherwise (unsupported) must be 0.
537  * @fragment_length:    Length of fragment of retrieve request descriptor passed
538  *                      in this call. Only @fragment_length == @length is
539  *                      supported by this implementation.
540  * @address:            Not supported, must be 0.
541  * @page_count:         Not supported, must be 0.
542  * @smc_handle:         Handle passed to smc call. Used to return
543  *                      FFA_MEM_RETRIEVE_RESP.
544  *
545  * Implements a subset of the FF-A FFA_MEM_RETRIEVE_REQ call.
546  * Used by secure os to retrieve memory already shared by non-secure os.
547  * If the data does not fit in a single FFA_MEM_RETRIEVE_RESP message,
548  * the client must call FFA_MEM_FRAG_RX until the full response has been
549  * received.
550  *
551  * Return: @handle on success, error code on failure.
552  */
553 long
554 spmc_ffa_mem_retrieve_req(uint32_t smc_fid,
555 			  bool secure_origin,
556 			  uint32_t total_length,
557 			  uint32_t fragment_length,
558 			  uint64_t address,
559 			  uint32_t page_count,
560 			  void *cookie,
561 			  void *handle,
562 			  uint64_t flags)
563 {
564 	int ret;
565 	size_t buf_size;
566 	size_t copy_size;
567 	struct ffa_mtd_v1_0 *resp;
568 	const struct ffa_mtd_v1_0 *req;
569 	struct spmc_shmem_obj *obj = NULL;
570 	struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
571 
572 	if (!secure_origin) {
573 		WARN("%s: unsupported retrieve req direction.\n", __func__);
574 		return spmc_ffa_error_return(handle,
575 					     FFA_ERROR_INVALID_PARAMETER);
576 	}
577 
578 	if (address != 0U || page_count != 0U) {
579 		WARN("%s: custom memory region not supported.\n", __func__);
580 		return spmc_ffa_error_return(handle,
581 					     FFA_ERROR_INVALID_PARAMETER);
582 	}
583 
584 	spin_lock(&mbox->lock);
585 
586 	req = mbox->tx_buffer;
587 	resp = mbox->rx_buffer;
588 	buf_size = mbox->rxtx_page_count * FFA_PAGE_SIZE;
589 
590 	if (mbox->rxtx_page_count == 0U) {
591 		WARN("%s: buffer pair not registered.\n", __func__);
592 		ret = FFA_ERROR_INVALID_PARAMETER;
593 		goto err_unlock_mailbox;
594 	}
595 
596 	if (mbox->state != MAILBOX_STATE_EMPTY) {
597 		WARN("%s: RX Buffer is full! %d\n", __func__, mbox->state);
598 		ret = FFA_ERROR_DENIED;
599 		goto err_unlock_mailbox;
600 	}
601 
602 	if (fragment_length != total_length) {
603 		WARN("%s: fragmented retrieve request not supported.\n",
604 		     __func__);
605 		ret = FFA_ERROR_INVALID_PARAMETER;
606 		goto err_unlock_mailbox;
607 	}
608 
609 	if (req->emad_count == 0U) {
610 		WARN("%s: unsupported attribute desc count %u.\n",
611 		     __func__, obj->desc.emad_count);
612 		return -EINVAL;
613 	}
614 
615 	if (total_length < sizeof(*req)) {
616 		WARN("%s: invalid length %u < %zu\n", __func__, total_length,
617 		     sizeof(*req));
618 		ret = FFA_ERROR_INVALID_PARAMETER;
619 		goto err_unlock_mailbox;
620 	}
621 
622 	spin_lock(&spmc_shmem_obj_state.lock);
623 
624 	obj = spmc_shmem_obj_lookup(&spmc_shmem_obj_state, req->handle);
625 	if (obj == NULL) {
626 		ret = FFA_ERROR_INVALID_PARAMETER;
627 		goto err_unlock_all;
628 	}
629 
630 	if (obj->desc_filled != obj->desc_size) {
631 		WARN("%s: incomplete object desc filled %zu < size %zu\n",
632 		     __func__, obj->desc_filled, obj->desc_size);
633 		ret = FFA_ERROR_INVALID_PARAMETER;
634 		goto err_unlock_all;
635 	}
636 
637 	if (req->emad_count != 0U && req->sender_id != obj->desc.sender_id) {
638 		WARN("%s: wrong sender id 0x%x != 0x%x\n",
639 		     __func__, req->sender_id, obj->desc.sender_id);
640 		ret = FFA_ERROR_INVALID_PARAMETER;
641 		goto err_unlock_all;
642 	}
643 
644 	if (req->emad_count != 0U && req->tag != obj->desc.tag) {
645 		WARN("%s: wrong tag 0x%lx != 0x%lx\n",
646 		     __func__, req->tag, obj->desc.tag);
647 		ret = FFA_ERROR_INVALID_PARAMETER;
648 		goto err_unlock_all;
649 	}
650 
651 	if (req->emad_count != 0U && req->emad_count != obj->desc.emad_count) {
652 		WARN("%s: mistmatch of endpoint counts %u != %u\n",
653 		     __func__, req->emad_count, obj->desc.emad_count);
654 		ret = FFA_ERROR_INVALID_PARAMETER;
655 		goto err_unlock_all;
656 	}
657 
658 	if (req->flags != 0U) {
659 		if ((req->flags & FFA_MTD_FLAG_TYPE_MASK) !=
660 		    (obj->desc.flags & FFA_MTD_FLAG_TYPE_MASK)) {
661 			/*
662 			 * If the retrieve request specifies the memory
663 			 * transaction ensure it matches what we expect.
664 			 */
665 			WARN("%s: wrong mem transaction flags %x != %x\n",
666 			__func__, req->flags, obj->desc.flags);
667 			ret = FFA_ERROR_INVALID_PARAMETER;
668 			goto err_unlock_all;
669 		}
670 
671 		if (req->flags != FFA_MTD_FLAG_TYPE_SHARE_MEMORY &&
672 		    req->flags != FFA_MTD_FLAG_TYPE_LEND_MEMORY) {
673 			/*
674 			 * Current implementation does not support donate and
675 			 * it supports no other flags.
676 			 */
677 			WARN("%s: invalid flags 0x%x\n", __func__, req->flags);
678 			ret = FFA_ERROR_INVALID_PARAMETER;
679 			goto err_unlock_all;
680 		}
681 	}
682 
683 	/*
684 	 * Ensure the emad array lies within the bounds of the descriptor by
685 	 * checking the address of the element past the end of the array.
686 	 */
687 	if ((uintptr_t) &req->emad[req->emad_count] >
688 	    (uintptr_t)((uint8_t *) &req + total_length)) {
689 		WARN("Invalid emad access.\n");
690 		return -EINVAL;
691 	}
692 
693 	/*
694 	 * Validate all the endpoints match in the case of multiple
695 	 * borrowers. We don't mandate that the order of the borrowers
696 	 * must match in the descriptors therefore check to see if the
697 	 * endpoints match in any order.
698 	 */
699 	for (size_t i = 0; i < req->emad_count; i++) {
700 		bool found = false;
701 
702 		for (size_t j = 0; j < obj->desc.emad_count; j++) {
703 			if (req->emad[i].mapd.endpoint_id ==
704 			    obj->desc.emad[j].mapd.endpoint_id) {
705 				found = true;
706 				break;
707 			}
708 		}
709 
710 		if (!found) {
711 			WARN("%s: invalid receiver id (0x%x).\n",
712 			     __func__, req->emad[i].mapd.endpoint_id);
713 			ret = FFA_ERROR_INVALID_PARAMETER;
714 			goto err_unlock_all;
715 		}
716 	}
717 
718 	mbox->state = MAILBOX_STATE_FULL;
719 
720 	if (req->emad_count != 0U) {
721 		obj->in_use++;
722 	}
723 
724 	copy_size = MIN(obj->desc_size, buf_size);
725 
726 	memcpy(resp, &obj->desc, copy_size);
727 
728 	spin_unlock(&spmc_shmem_obj_state.lock);
729 	spin_unlock(&mbox->lock);
730 
731 	SMC_RET8(handle, FFA_MEM_RETRIEVE_RESP, obj->desc_size,
732 		 copy_size, 0, 0, 0, 0, 0);
733 
734 err_unlock_all:
735 	spin_unlock(&spmc_shmem_obj_state.lock);
736 err_unlock_mailbox:
737 	spin_unlock(&mbox->lock);
738 	return spmc_ffa_error_return(handle, ret);
739 }
740 
741 /**
742  * spmc_ffa_mem_frag_rx - FFA_MEM_FRAG_RX implementation.
743  * @client:             Client state.
744  * @handle_low:         Handle passed to &FFA_MEM_RETRIEVE_REQ. Bit[31:0].
745  * @handle_high:        Handle passed to &FFA_MEM_RETRIEVE_REQ. Bit[63:32].
746  * @fragment_offset:    Byte offset in descriptor to resume at.
747  * @sender_id:          Bit[31:16]: Endpoint id of sender if client is a
748  *                      hypervisor. 0 otherwise.
749  * @smc_handle:         Handle passed to smc call. Used to return
750  *                      FFA_MEM_FRAG_TX.
751  *
752  * Return: @smc_handle on success, error code on failure.
753  */
754 long spmc_ffa_mem_frag_rx(uint32_t smc_fid,
755 			  bool secure_origin,
756 			  uint32_t handle_low,
757 			  uint32_t handle_high,
758 			  uint32_t fragment_offset,
759 			  uint32_t sender_id,
760 			  void *cookie,
761 			  void *handle,
762 			  uint64_t flags)
763 {
764 	int ret;
765 	void *src;
766 	size_t buf_size;
767 	size_t copy_size;
768 	size_t full_copy_size;
769 	uint32_t desc_sender_id;
770 	struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
771 	uint64_t mem_handle = handle_low | (((uint64_t)handle_high) << 32);
772 	struct spmc_shmem_obj *obj;
773 
774 	if (!secure_origin) {
775 		WARN("%s: can only be called from swld.\n",
776 		     __func__);
777 		return spmc_ffa_error_return(handle,
778 					     FFA_ERROR_INVALID_PARAMETER);
779 	}
780 
781 	spin_lock(&spmc_shmem_obj_state.lock);
782 
783 	obj = spmc_shmem_obj_lookup(&spmc_shmem_obj_state, mem_handle);
784 	if (obj == NULL) {
785 		WARN("%s: invalid handle, 0x%lx, not a valid handle.\n",
786 		     __func__, mem_handle);
787 		ret = FFA_ERROR_INVALID_PARAMETER;
788 		goto err_unlock_shmem;
789 	}
790 
791 	desc_sender_id = (uint32_t)obj->desc.sender_id << 16;
792 	if (sender_id != 0U && sender_id != desc_sender_id) {
793 		WARN("%s: invalid sender_id 0x%x != 0x%x\n", __func__,
794 		     sender_id, desc_sender_id);
795 		ret = FFA_ERROR_INVALID_PARAMETER;
796 		goto err_unlock_shmem;
797 	}
798 
799 	if (fragment_offset >= obj->desc_size) {
800 		WARN("%s: invalid fragment_offset 0x%x >= 0x%zx\n",
801 		     __func__, fragment_offset, obj->desc_size);
802 		ret = FFA_ERROR_INVALID_PARAMETER;
803 		goto err_unlock_shmem;
804 	}
805 
806 	spin_lock(&mbox->lock);
807 
808 	if (mbox->rxtx_page_count == 0U) {
809 		WARN("%s: buffer pair not registered.\n", __func__);
810 		ret = FFA_ERROR_INVALID_PARAMETER;
811 		goto err_unlock_all;
812 	}
813 
814 	if (mbox->state != MAILBOX_STATE_EMPTY) {
815 		WARN("%s: RX Buffer is full!\n", __func__);
816 		ret = FFA_ERROR_DENIED;
817 		goto err_unlock_all;
818 	}
819 
820 	buf_size = mbox->rxtx_page_count * FFA_PAGE_SIZE;
821 
822 	mbox->state = MAILBOX_STATE_FULL;
823 
824 	full_copy_size = obj->desc_size - fragment_offset;
825 	copy_size = MIN(full_copy_size, buf_size);
826 
827 	src = &obj->desc;
828 
829 	memcpy(mbox->rx_buffer, src + fragment_offset, copy_size);
830 
831 	spin_unlock(&mbox->lock);
832 	spin_unlock(&spmc_shmem_obj_state.lock);
833 
834 	SMC_RET8(handle, FFA_MEM_FRAG_TX, handle_low, handle_high,
835 		 copy_size, sender_id, 0, 0, 0);
836 
837 err_unlock_all:
838 	spin_unlock(&mbox->lock);
839 err_unlock_shmem:
840 	spin_unlock(&spmc_shmem_obj_state.lock);
841 	return spmc_ffa_error_return(handle, ret);
842 }
843 
844 /**
845  * spmc_ffa_mem_relinquish - FFA_MEM_RELINQUISH implementation.
846  * @client:             Client state.
847  *
848  * Implements a subset of the FF-A FFA_MEM_RELINQUISH call.
849  * Used by secure os release previously shared memory to non-secure os.
850  *
851  * The handle to release must be in the client's (secure os's) transmit buffer.
852  *
853  * Return: 0 on success, error code on failure.
854  */
855 int spmc_ffa_mem_relinquish(uint32_t smc_fid,
856 			    bool secure_origin,
857 			    uint32_t handle_low,
858 			    uint32_t handle_high,
859 			    uint32_t fragment_offset,
860 			    uint32_t sender_id,
861 			    void *cookie,
862 			    void *handle,
863 			    uint64_t flags)
864 {
865 	int ret;
866 	struct mailbox *mbox = spmc_get_mbox_desc(secure_origin);
867 	struct spmc_shmem_obj *obj;
868 	const struct ffa_mem_relinquish_descriptor *req;
869 
870 	if (!secure_origin) {
871 		WARN("%s: unsupported relinquish direction.\n", __func__);
872 		return spmc_ffa_error_return(handle,
873 					     FFA_ERROR_INVALID_PARAMETER);
874 	}
875 
876 	spin_lock(&mbox->lock);
877 
878 	if (mbox->rxtx_page_count == 0U) {
879 		WARN("%s: buffer pair not registered.\n", __func__);
880 		ret = FFA_ERROR_INVALID_PARAMETER;
881 		goto err_unlock_mailbox;
882 	}
883 
884 	req = mbox->tx_buffer;
885 
886 	if (req->flags != 0U) {
887 		WARN("%s: unsupported flags 0x%x\n", __func__, req->flags);
888 		ret = FFA_ERROR_INVALID_PARAMETER;
889 		goto err_unlock_mailbox;
890 	}
891 
892 	if (req->endpoint_count == 0) {
893 		WARN("%s: endpoint count cannot be 0.\n", __func__);
894 		ret = FFA_ERROR_INVALID_PARAMETER;
895 		goto err_unlock_mailbox;
896 	}
897 
898 	spin_lock(&spmc_shmem_obj_state.lock);
899 
900 	obj = spmc_shmem_obj_lookup(&spmc_shmem_obj_state, req->handle);
901 	if (obj == NULL) {
902 		ret = FFA_ERROR_INVALID_PARAMETER;
903 		goto err_unlock_all;
904 	}
905 
906 	if (obj->desc.emad_count != req->endpoint_count) {
907 		WARN("%s: mismatch of endpoint count %u != %u\n", __func__,
908 		     obj->desc.emad_count, req->endpoint_count);
909 		ret = FFA_ERROR_INVALID_PARAMETER;
910 		goto err_unlock_all;
911 	}
912 
913 	/* Validate requested endpoint IDs match descriptor. */
914 	for (size_t i = 0; i < req->endpoint_count; i++) {
915 		bool found = false;
916 
917 		for (unsigned int j = 0; j < obj->desc.emad_count; j++) {
918 			if (req->endpoint_array[i] ==
919 			    obj->desc.emad[j].mapd.endpoint_id) {
920 				found = true;
921 				break;
922 			}
923 		}
924 
925 		if (!found) {
926 			WARN("%s: Invalid endpoint ID (0x%x).\n",
927 			     __func__, req->endpoint_array[i]);
928 			ret = FFA_ERROR_INVALID_PARAMETER;
929 			goto err_unlock_all;
930 		}
931 	}
932 
933 	if (obj->in_use == 0U) {
934 		ret = FFA_ERROR_INVALID_PARAMETER;
935 		goto err_unlock_all;
936 	}
937 	obj->in_use--;
938 
939 	spin_unlock(&spmc_shmem_obj_state.lock);
940 	spin_unlock(&mbox->lock);
941 
942 	SMC_RET1(handle, FFA_SUCCESS_SMC32);
943 
944 err_unlock_all:
945 	spin_unlock(&spmc_shmem_obj_state.lock);
946 err_unlock_mailbox:
947 	spin_unlock(&mbox->lock);
948 	return spmc_ffa_error_return(handle, ret);
949 }
950 
951 /**
952  * spmc_ffa_mem_reclaim - FFA_MEM_RECLAIM implementation.
953  * @client:         Client state.
954  * @handle_low:     Unique handle of shared memory object to reclaim. Bit[31:0].
955  * @handle_high:    Unique handle of shared memory object to reclaim.
956  *                  Bit[63:32].
957  * @flags:          Unsupported, ignored.
958  *
959  * Implements a subset of the FF-A FFA_MEM_RECLAIM call.
960  * Used by non-secure os reclaim memory previously shared with secure os.
961  *
962  * Return: 0 on success, error code on failure.
963  */
964 int spmc_ffa_mem_reclaim(uint32_t smc_fid,
965 			 bool secure_origin,
966 			 uint32_t handle_low,
967 			 uint32_t handle_high,
968 			 uint32_t mem_flags,
969 			 uint64_t x4,
970 			 void *cookie,
971 			 void *handle,
972 			 uint64_t flags)
973 {
974 	int ret;
975 	struct spmc_shmem_obj *obj;
976 	uint64_t mem_handle = handle_low | (((uint64_t)handle_high) << 32);
977 
978 	if (secure_origin) {
979 		WARN("%s: unsupported reclaim direction.\n", __func__);
980 		return spmc_ffa_error_return(handle,
981 					     FFA_ERROR_INVALID_PARAMETER);
982 	}
983 
984 	if (mem_flags != 0U) {
985 		WARN("%s: unsupported flags 0x%x\n", __func__, mem_flags);
986 		return spmc_ffa_error_return(handle,
987 					     FFA_ERROR_INVALID_PARAMETER);
988 	}
989 
990 	spin_lock(&spmc_shmem_obj_state.lock);
991 
992 	obj = spmc_shmem_obj_lookup(&spmc_shmem_obj_state, mem_handle);
993 	if (obj == NULL) {
994 		ret = FFA_ERROR_INVALID_PARAMETER;
995 		goto err_unlock;
996 	}
997 	if (obj->in_use != 0U) {
998 		ret = FFA_ERROR_DENIED;
999 		goto err_unlock;
1000 	}
1001 	spmc_shmem_obj_free(&spmc_shmem_obj_state, obj);
1002 	spin_unlock(&spmc_shmem_obj_state.lock);
1003 
1004 	SMC_RET1(handle, FFA_SUCCESS_SMC32);
1005 
1006 err_unlock:
1007 	spin_unlock(&spmc_shmem_obj_state.lock);
1008 	return spmc_ffa_error_return(handle, ret);
1009 }
1010