xref: /linux/arch/arm64/kvm/hyp/nvhe/ffa.c (revision 1b0975ee3bdd3eb19a47371c26fd7ef8f7f6b599)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * FF-A v1.0 proxy to filter out invalid memory-sharing SMC calls issued by
4  * the host. FF-A is a slightly more palatable abbreviation of "Arm Firmware
5  * Framework for Arm A-profile", which is specified by Arm in document
6  * number DEN0077.
7  *
8  * Copyright (C) 2022 - Google LLC
9  * Author: Andrew Walbran <qwandor@google.com>
10  *
11  * This driver hooks into the SMC trapping logic for the host and intercepts
12  * all calls falling within the FF-A range. Each call is either:
13  *
14  *	- Forwarded on unmodified to the SPMD at EL3
15  *	- Rejected as "unsupported"
16  *	- Accompanied by a host stage-2 page-table check/update and reissued
17  *
18  * Consequently, any attempts by the host to make guest memory pages
19  * accessible to the secure world using FF-A will be detected either here
20  * (in the case that the memory is already owned by the guest) or during
21  * donation to the guest (in the case that the memory was previously shared
22  * with the secure world).
23  *
24  * To allow the rolling-back of page-table updates and FF-A calls in the
25  * event of failure, operations involving the RXTX buffers are locked for
26  * the duration and are therefore serialised.
27  */
28 
29 #include <linux/arm-smccc.h>
30 #include <linux/arm_ffa.h>
31 #include <asm/kvm_pkvm.h>
32 
33 #include <nvhe/ffa.h>
34 #include <nvhe/mem_protect.h>
35 #include <nvhe/memory.h>
36 #include <nvhe/trap_handler.h>
37 #include <nvhe/spinlock.h>
38 
39 /*
40  * "ID value 0 must be returned at the Non-secure physical FF-A instance"
41  * We share this ID with the host.
42  */
43 #define HOST_FFA_ID	0
44 
45 /*
46  * A buffer to hold the maximum descriptor size we can see from the host,
47  * which is required when the SPMD returns a fragmented FFA_MEM_RETRIEVE_RESP
48  * when resolving the handle on the reclaim path.
49  */
50 struct kvm_ffa_descriptor_buffer {
51 	void	*buf;
52 	size_t	len;
53 };
54 
55 static struct kvm_ffa_descriptor_buffer ffa_desc_buf;
56 
57 struct kvm_ffa_buffers {
58 	hyp_spinlock_t lock;
59 	void *tx;
60 	void *rx;
61 };
62 
63 /*
64  * Note that we don't currently lock these buffers explicitly, instead
65  * relying on the locking of the host FFA buffers as we only have one
66  * client.
67  */
68 static struct kvm_ffa_buffers hyp_buffers;
69 static struct kvm_ffa_buffers host_buffers;
70 
71 static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
72 {
73 	*res = (struct arm_smccc_res) {
74 		.a0	= FFA_ERROR,
75 		.a2	= ffa_errno,
76 	};
77 }
78 
79 static void ffa_to_smccc_res_prop(struct arm_smccc_res *res, int ret, u64 prop)
80 {
81 	if (ret == FFA_RET_SUCCESS) {
82 		*res = (struct arm_smccc_res) { .a0 = FFA_SUCCESS,
83 						.a2 = prop };
84 	} else {
85 		ffa_to_smccc_error(res, ret);
86 	}
87 }
88 
89 static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret)
90 {
91 	ffa_to_smccc_res_prop(res, ret, 0);
92 }
93 
94 static void ffa_set_retval(struct kvm_cpu_context *ctxt,
95 			   struct arm_smccc_res *res)
96 {
97 	cpu_reg(ctxt, 0) = res->a0;
98 	cpu_reg(ctxt, 1) = res->a1;
99 	cpu_reg(ctxt, 2) = res->a2;
100 	cpu_reg(ctxt, 3) = res->a3;
101 }
102 
103 static bool is_ffa_call(u64 func_id)
104 {
105 	return ARM_SMCCC_IS_FAST_CALL(func_id) &&
106 	       ARM_SMCCC_OWNER_NUM(func_id) == ARM_SMCCC_OWNER_STANDARD &&
107 	       ARM_SMCCC_FUNC_NUM(func_id) >= FFA_MIN_FUNC_NUM &&
108 	       ARM_SMCCC_FUNC_NUM(func_id) <= FFA_MAX_FUNC_NUM;
109 }
110 
111 static int ffa_map_hyp_buffers(u64 ffa_page_count)
112 {
113 	struct arm_smccc_res res;
114 
115 	arm_smccc_1_1_smc(FFA_FN64_RXTX_MAP,
116 			  hyp_virt_to_phys(hyp_buffers.tx),
117 			  hyp_virt_to_phys(hyp_buffers.rx),
118 			  ffa_page_count,
119 			  0, 0, 0, 0,
120 			  &res);
121 
122 	return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
123 }
124 
125 static int ffa_unmap_hyp_buffers(void)
126 {
127 	struct arm_smccc_res res;
128 
129 	arm_smccc_1_1_smc(FFA_RXTX_UNMAP,
130 			  HOST_FFA_ID,
131 			  0, 0, 0, 0, 0, 0,
132 			  &res);
133 
134 	return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
135 }
136 
137 static void ffa_mem_frag_tx(struct arm_smccc_res *res, u32 handle_lo,
138 			     u32 handle_hi, u32 fraglen, u32 endpoint_id)
139 {
140 	arm_smccc_1_1_smc(FFA_MEM_FRAG_TX,
141 			  handle_lo, handle_hi, fraglen, endpoint_id,
142 			  0, 0, 0,
143 			  res);
144 }
145 
146 static void ffa_mem_frag_rx(struct arm_smccc_res *res, u32 handle_lo,
147 			     u32 handle_hi, u32 fragoff)
148 {
149 	arm_smccc_1_1_smc(FFA_MEM_FRAG_RX,
150 			  handle_lo, handle_hi, fragoff, HOST_FFA_ID,
151 			  0, 0, 0,
152 			  res);
153 }
154 
155 static void ffa_mem_xfer(struct arm_smccc_res *res, u64 func_id, u32 len,
156 			  u32 fraglen)
157 {
158 	arm_smccc_1_1_smc(func_id, len, fraglen,
159 			  0, 0, 0, 0, 0,
160 			  res);
161 }
162 
163 static void ffa_mem_reclaim(struct arm_smccc_res *res, u32 handle_lo,
164 			     u32 handle_hi, u32 flags)
165 {
166 	arm_smccc_1_1_smc(FFA_MEM_RECLAIM,
167 			  handle_lo, handle_hi, flags,
168 			  0, 0, 0, 0,
169 			  res);
170 }
171 
172 static void ffa_retrieve_req(struct arm_smccc_res *res, u32 len)
173 {
174 	arm_smccc_1_1_smc(FFA_FN64_MEM_RETRIEVE_REQ,
175 			  len, len,
176 			  0, 0, 0, 0, 0,
177 			  res);
178 }
179 
180 static void do_ffa_rxtx_map(struct arm_smccc_res *res,
181 			    struct kvm_cpu_context *ctxt)
182 {
183 	DECLARE_REG(phys_addr_t, tx, ctxt, 1);
184 	DECLARE_REG(phys_addr_t, rx, ctxt, 2);
185 	DECLARE_REG(u32, npages, ctxt, 3);
186 	int ret = 0;
187 	void *rx_virt, *tx_virt;
188 
189 	if (npages != (KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) / FFA_PAGE_SIZE) {
190 		ret = FFA_RET_INVALID_PARAMETERS;
191 		goto out;
192 	}
193 
194 	if (!PAGE_ALIGNED(tx) || !PAGE_ALIGNED(rx)) {
195 		ret = FFA_RET_INVALID_PARAMETERS;
196 		goto out;
197 	}
198 
199 	hyp_spin_lock(&host_buffers.lock);
200 	if (host_buffers.tx) {
201 		ret = FFA_RET_DENIED;
202 		goto out_unlock;
203 	}
204 
205 	/*
206 	 * Map our hypervisor buffers into the SPMD before mapping and
207 	 * pinning the host buffers in our own address space.
208 	 */
209 	ret = ffa_map_hyp_buffers(npages);
210 	if (ret)
211 		goto out_unlock;
212 
213 	ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(tx));
214 	if (ret) {
215 		ret = FFA_RET_INVALID_PARAMETERS;
216 		goto err_unmap;
217 	}
218 
219 	ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(rx));
220 	if (ret) {
221 		ret = FFA_RET_INVALID_PARAMETERS;
222 		goto err_unshare_tx;
223 	}
224 
225 	tx_virt = hyp_phys_to_virt(tx);
226 	ret = hyp_pin_shared_mem(tx_virt, tx_virt + 1);
227 	if (ret) {
228 		ret = FFA_RET_INVALID_PARAMETERS;
229 		goto err_unshare_rx;
230 	}
231 
232 	rx_virt = hyp_phys_to_virt(rx);
233 	ret = hyp_pin_shared_mem(rx_virt, rx_virt + 1);
234 	if (ret) {
235 		ret = FFA_RET_INVALID_PARAMETERS;
236 		goto err_unpin_tx;
237 	}
238 
239 	host_buffers.tx = tx_virt;
240 	host_buffers.rx = rx_virt;
241 
242 out_unlock:
243 	hyp_spin_unlock(&host_buffers.lock);
244 out:
245 	ffa_to_smccc_res(res, ret);
246 	return;
247 
248 err_unpin_tx:
249 	hyp_unpin_shared_mem(tx_virt, tx_virt + 1);
250 err_unshare_rx:
251 	__pkvm_host_unshare_hyp(hyp_phys_to_pfn(rx));
252 err_unshare_tx:
253 	__pkvm_host_unshare_hyp(hyp_phys_to_pfn(tx));
254 err_unmap:
255 	ffa_unmap_hyp_buffers();
256 	goto out_unlock;
257 }
258 
259 static void do_ffa_rxtx_unmap(struct arm_smccc_res *res,
260 			      struct kvm_cpu_context *ctxt)
261 {
262 	DECLARE_REG(u32, id, ctxt, 1);
263 	int ret = 0;
264 
265 	if (id != HOST_FFA_ID) {
266 		ret = FFA_RET_INVALID_PARAMETERS;
267 		goto out;
268 	}
269 
270 	hyp_spin_lock(&host_buffers.lock);
271 	if (!host_buffers.tx) {
272 		ret = FFA_RET_INVALID_PARAMETERS;
273 		goto out_unlock;
274 	}
275 
276 	hyp_unpin_shared_mem(host_buffers.tx, host_buffers.tx + 1);
277 	WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.tx)));
278 	host_buffers.tx = NULL;
279 
280 	hyp_unpin_shared_mem(host_buffers.rx, host_buffers.rx + 1);
281 	WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.rx)));
282 	host_buffers.rx = NULL;
283 
284 	ffa_unmap_hyp_buffers();
285 
286 out_unlock:
287 	hyp_spin_unlock(&host_buffers.lock);
288 out:
289 	ffa_to_smccc_res(res, ret);
290 }
291 
292 static u32 __ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges,
293 				   u32 nranges)
294 {
295 	u32 i;
296 
297 	for (i = 0; i < nranges; ++i) {
298 		struct ffa_mem_region_addr_range *range = &ranges[i];
299 		u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE;
300 		u64 pfn = hyp_phys_to_pfn(range->address);
301 
302 		if (!PAGE_ALIGNED(sz))
303 			break;
304 
305 		if (__pkvm_host_share_ffa(pfn, sz / PAGE_SIZE))
306 			break;
307 	}
308 
309 	return i;
310 }
311 
312 static u32 __ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges,
313 				     u32 nranges)
314 {
315 	u32 i;
316 
317 	for (i = 0; i < nranges; ++i) {
318 		struct ffa_mem_region_addr_range *range = &ranges[i];
319 		u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE;
320 		u64 pfn = hyp_phys_to_pfn(range->address);
321 
322 		if (!PAGE_ALIGNED(sz))
323 			break;
324 
325 		if (__pkvm_host_unshare_ffa(pfn, sz / PAGE_SIZE))
326 			break;
327 	}
328 
329 	return i;
330 }
331 
332 static int ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges,
333 				 u32 nranges)
334 {
335 	u32 nshared = __ffa_host_share_ranges(ranges, nranges);
336 	int ret = 0;
337 
338 	if (nshared != nranges) {
339 		WARN_ON(__ffa_host_unshare_ranges(ranges, nshared) != nshared);
340 		ret = FFA_RET_DENIED;
341 	}
342 
343 	return ret;
344 }
345 
346 static int ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges,
347 				   u32 nranges)
348 {
349 	u32 nunshared = __ffa_host_unshare_ranges(ranges, nranges);
350 	int ret = 0;
351 
352 	if (nunshared != nranges) {
353 		WARN_ON(__ffa_host_share_ranges(ranges, nunshared) != nunshared);
354 		ret = FFA_RET_DENIED;
355 	}
356 
357 	return ret;
358 }
359 
360 static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
361 			       struct kvm_cpu_context *ctxt)
362 {
363 	DECLARE_REG(u32, handle_lo, ctxt, 1);
364 	DECLARE_REG(u32, handle_hi, ctxt, 2);
365 	DECLARE_REG(u32, fraglen, ctxt, 3);
366 	DECLARE_REG(u32, endpoint_id, ctxt, 4);
367 	struct ffa_mem_region_addr_range *buf;
368 	int ret = FFA_RET_INVALID_PARAMETERS;
369 	u32 nr_ranges;
370 
371 	if (fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)
372 		goto out;
373 
374 	if (fraglen % sizeof(*buf))
375 		goto out;
376 
377 	hyp_spin_lock(&host_buffers.lock);
378 	if (!host_buffers.tx)
379 		goto out_unlock;
380 
381 	buf = hyp_buffers.tx;
382 	memcpy(buf, host_buffers.tx, fraglen);
383 	nr_ranges = fraglen / sizeof(*buf);
384 
385 	ret = ffa_host_share_ranges(buf, nr_ranges);
386 	if (ret) {
387 		/*
388 		 * We're effectively aborting the transaction, so we need
389 		 * to restore the global state back to what it was prior to
390 		 * transmission of the first fragment.
391 		 */
392 		ffa_mem_reclaim(res, handle_lo, handle_hi, 0);
393 		WARN_ON(res->a0 != FFA_SUCCESS);
394 		goto out_unlock;
395 	}
396 
397 	ffa_mem_frag_tx(res, handle_lo, handle_hi, fraglen, endpoint_id);
398 	if (res->a0 != FFA_SUCCESS && res->a0 != FFA_MEM_FRAG_RX)
399 		WARN_ON(ffa_host_unshare_ranges(buf, nr_ranges));
400 
401 out_unlock:
402 	hyp_spin_unlock(&host_buffers.lock);
403 out:
404 	if (ret)
405 		ffa_to_smccc_res(res, ret);
406 
407 	/*
408 	 * If for any reason this did not succeed, we're in trouble as we have
409 	 * now lost the content of the previous fragments and we can't rollback
410 	 * the host stage-2 changes. The pages previously marked as shared will
411 	 * remain stuck in that state forever, hence preventing the host from
412 	 * sharing/donating them again and may possibly lead to subsequent
413 	 * failures, but this will not compromise confidentiality.
414 	 */
415 	return;
416 }
417 
418 static __always_inline void do_ffa_mem_xfer(const u64 func_id,
419 					    struct arm_smccc_res *res,
420 					    struct kvm_cpu_context *ctxt)
421 {
422 	DECLARE_REG(u32, len, ctxt, 1);
423 	DECLARE_REG(u32, fraglen, ctxt, 2);
424 	DECLARE_REG(u64, addr_mbz, ctxt, 3);
425 	DECLARE_REG(u32, npages_mbz, ctxt, 4);
426 	struct ffa_composite_mem_region *reg;
427 	struct ffa_mem_region *buf;
428 	u32 offset, nr_ranges;
429 	int ret = 0;
430 
431 	BUILD_BUG_ON(func_id != FFA_FN64_MEM_SHARE &&
432 		     func_id != FFA_FN64_MEM_LEND);
433 
434 	if (addr_mbz || npages_mbz || fraglen > len ||
435 	    fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
436 		ret = FFA_RET_INVALID_PARAMETERS;
437 		goto out;
438 	}
439 
440 	if (fraglen < sizeof(struct ffa_mem_region) +
441 		      sizeof(struct ffa_mem_region_attributes)) {
442 		ret = FFA_RET_INVALID_PARAMETERS;
443 		goto out;
444 	}
445 
446 	hyp_spin_lock(&host_buffers.lock);
447 	if (!host_buffers.tx) {
448 		ret = FFA_RET_INVALID_PARAMETERS;
449 		goto out_unlock;
450 	}
451 
452 	buf = hyp_buffers.tx;
453 	memcpy(buf, host_buffers.tx, fraglen);
454 
455 	offset = buf->ep_mem_access[0].composite_off;
456 	if (!offset || buf->ep_count != 1 || buf->sender_id != HOST_FFA_ID) {
457 		ret = FFA_RET_INVALID_PARAMETERS;
458 		goto out_unlock;
459 	}
460 
461 	if (fraglen < offset + sizeof(struct ffa_composite_mem_region)) {
462 		ret = FFA_RET_INVALID_PARAMETERS;
463 		goto out_unlock;
464 	}
465 
466 	reg = (void *)buf + offset;
467 	nr_ranges = ((void *)buf + fraglen) - (void *)reg->constituents;
468 	if (nr_ranges % sizeof(reg->constituents[0])) {
469 		ret = FFA_RET_INVALID_PARAMETERS;
470 		goto out_unlock;
471 	}
472 
473 	nr_ranges /= sizeof(reg->constituents[0]);
474 	ret = ffa_host_share_ranges(reg->constituents, nr_ranges);
475 	if (ret)
476 		goto out_unlock;
477 
478 	ffa_mem_xfer(res, func_id, len, fraglen);
479 	if (fraglen != len) {
480 		if (res->a0 != FFA_MEM_FRAG_RX)
481 			goto err_unshare;
482 
483 		if (res->a3 != fraglen)
484 			goto err_unshare;
485 	} else if (res->a0 != FFA_SUCCESS) {
486 		goto err_unshare;
487 	}
488 
489 out_unlock:
490 	hyp_spin_unlock(&host_buffers.lock);
491 out:
492 	if (ret)
493 		ffa_to_smccc_res(res, ret);
494 	return;
495 
496 err_unshare:
497 	WARN_ON(ffa_host_unshare_ranges(reg->constituents, nr_ranges));
498 	goto out_unlock;
499 }
500 
501 static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
502 			       struct kvm_cpu_context *ctxt)
503 {
504 	DECLARE_REG(u32, handle_lo, ctxt, 1);
505 	DECLARE_REG(u32, handle_hi, ctxt, 2);
506 	DECLARE_REG(u32, flags, ctxt, 3);
507 	struct ffa_composite_mem_region *reg;
508 	u32 offset, len, fraglen, fragoff;
509 	struct ffa_mem_region *buf;
510 	int ret = 0;
511 	u64 handle;
512 
513 	handle = PACK_HANDLE(handle_lo, handle_hi);
514 
515 	hyp_spin_lock(&host_buffers.lock);
516 
517 	buf = hyp_buffers.tx;
518 	*buf = (struct ffa_mem_region) {
519 		.sender_id	= HOST_FFA_ID,
520 		.handle		= handle,
521 	};
522 
523 	ffa_retrieve_req(res, sizeof(*buf));
524 	buf = hyp_buffers.rx;
525 	if (res->a0 != FFA_MEM_RETRIEVE_RESP)
526 		goto out_unlock;
527 
528 	len = res->a1;
529 	fraglen = res->a2;
530 
531 	offset = buf->ep_mem_access[0].composite_off;
532 	/*
533 	 * We can trust the SPMD to get this right, but let's at least
534 	 * check that we end up with something that doesn't look _completely_
535 	 * bogus.
536 	 */
537 	if (WARN_ON(offset > len ||
538 		    fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
539 		ret = FFA_RET_ABORTED;
540 		goto out_unlock;
541 	}
542 
543 	if (len > ffa_desc_buf.len) {
544 		ret = FFA_RET_NO_MEMORY;
545 		goto out_unlock;
546 	}
547 
548 	buf = ffa_desc_buf.buf;
549 	memcpy(buf, hyp_buffers.rx, fraglen);
550 
551 	for (fragoff = fraglen; fragoff < len; fragoff += fraglen) {
552 		ffa_mem_frag_rx(res, handle_lo, handle_hi, fragoff);
553 		if (res->a0 != FFA_MEM_FRAG_TX) {
554 			ret = FFA_RET_INVALID_PARAMETERS;
555 			goto out_unlock;
556 		}
557 
558 		fraglen = res->a3;
559 		memcpy((void *)buf + fragoff, hyp_buffers.rx, fraglen);
560 	}
561 
562 	ffa_mem_reclaim(res, handle_lo, handle_hi, flags);
563 	if (res->a0 != FFA_SUCCESS)
564 		goto out_unlock;
565 
566 	reg = (void *)buf + offset;
567 	/* If the SPMD was happy, then we should be too. */
568 	WARN_ON(ffa_host_unshare_ranges(reg->constituents,
569 					reg->addr_range_cnt));
570 out_unlock:
571 	hyp_spin_unlock(&host_buffers.lock);
572 
573 	if (ret)
574 		ffa_to_smccc_res(res, ret);
575 }
576 
577 /*
578  * Is a given FFA function supported, either by forwarding on directly
579  * or by handling at EL2?
580  */
581 static bool ffa_call_supported(u64 func_id)
582 {
583 	switch (func_id) {
584 	/* Unsupported memory management calls */
585 	case FFA_FN64_MEM_RETRIEVE_REQ:
586 	case FFA_MEM_RETRIEVE_RESP:
587 	case FFA_MEM_RELINQUISH:
588 	case FFA_MEM_OP_PAUSE:
589 	case FFA_MEM_OP_RESUME:
590 	case FFA_MEM_FRAG_RX:
591 	case FFA_FN64_MEM_DONATE:
592 	/* Indirect message passing via RX/TX buffers */
593 	case FFA_MSG_SEND:
594 	case FFA_MSG_POLL:
595 	case FFA_MSG_WAIT:
596 	/* 32-bit variants of 64-bit calls */
597 	case FFA_MSG_SEND_DIRECT_REQ:
598 	case FFA_MSG_SEND_DIRECT_RESP:
599 	case FFA_RXTX_MAP:
600 	case FFA_MEM_DONATE:
601 	case FFA_MEM_RETRIEVE_REQ:
602 		return false;
603 	}
604 
605 	return true;
606 }
607 
608 static bool do_ffa_features(struct arm_smccc_res *res,
609 			    struct kvm_cpu_context *ctxt)
610 {
611 	DECLARE_REG(u32, id, ctxt, 1);
612 	u64 prop = 0;
613 	int ret = 0;
614 
615 	if (!ffa_call_supported(id)) {
616 		ret = FFA_RET_NOT_SUPPORTED;
617 		goto out_handled;
618 	}
619 
620 	switch (id) {
621 	case FFA_MEM_SHARE:
622 	case FFA_FN64_MEM_SHARE:
623 	case FFA_MEM_LEND:
624 	case FFA_FN64_MEM_LEND:
625 		ret = FFA_RET_SUCCESS;
626 		prop = 0; /* No support for dynamic buffers */
627 		goto out_handled;
628 	default:
629 		return false;
630 	}
631 
632 out_handled:
633 	ffa_to_smccc_res_prop(res, ret, prop);
634 	return true;
635 }
636 
637 bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt)
638 {
639 	DECLARE_REG(u64, func_id, host_ctxt, 0);
640 	struct arm_smccc_res res;
641 
642 	/*
643 	 * There's no way we can tell what a non-standard SMC call might
644 	 * be up to. Ideally, we would terminate these here and return
645 	 * an error to the host, but sadly devices make use of custom
646 	 * firmware calls for things like power management, debugging,
647 	 * RNG access and crash reporting.
648 	 *
649 	 * Given that the architecture requires us to trust EL3 anyway,
650 	 * we forward unrecognised calls on under the assumption that
651 	 * the firmware doesn't expose a mechanism to access arbitrary
652 	 * non-secure memory. Short of a per-device table of SMCs, this
653 	 * is the best we can do.
654 	 */
655 	if (!is_ffa_call(func_id))
656 		return false;
657 
658 	switch (func_id) {
659 	case FFA_FEATURES:
660 		if (!do_ffa_features(&res, host_ctxt))
661 			return false;
662 		goto out_handled;
663 	/* Memory management */
664 	case FFA_FN64_RXTX_MAP:
665 		do_ffa_rxtx_map(&res, host_ctxt);
666 		goto out_handled;
667 	case FFA_RXTX_UNMAP:
668 		do_ffa_rxtx_unmap(&res, host_ctxt);
669 		goto out_handled;
670 	case FFA_MEM_SHARE:
671 	case FFA_FN64_MEM_SHARE:
672 		do_ffa_mem_xfer(FFA_FN64_MEM_SHARE, &res, host_ctxt);
673 		goto out_handled;
674 	case FFA_MEM_RECLAIM:
675 		do_ffa_mem_reclaim(&res, host_ctxt);
676 		goto out_handled;
677 	case FFA_MEM_LEND:
678 	case FFA_FN64_MEM_LEND:
679 		do_ffa_mem_xfer(FFA_FN64_MEM_LEND, &res, host_ctxt);
680 		goto out_handled;
681 	case FFA_MEM_FRAG_TX:
682 		do_ffa_mem_frag_tx(&res, host_ctxt);
683 		goto out_handled;
684 	}
685 
686 	if (ffa_call_supported(func_id))
687 		return false; /* Pass through */
688 
689 	ffa_to_smccc_error(&res, FFA_RET_NOT_SUPPORTED);
690 out_handled:
691 	ffa_set_retval(host_ctxt, &res);
692 	return true;
693 }
694 
695 int hyp_ffa_init(void *pages)
696 {
697 	struct arm_smccc_res res;
698 	size_t min_rxtx_sz;
699 	void *tx, *rx;
700 
701 	if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
702 		return 0;
703 
704 	arm_smccc_1_1_smc(FFA_VERSION, FFA_VERSION_1_0, 0, 0, 0, 0, 0, 0, &res);
705 	if (res.a0 == FFA_RET_NOT_SUPPORTED)
706 		return 0;
707 
708 	if (res.a0 != FFA_VERSION_1_0)
709 		return -EOPNOTSUPP;
710 
711 	arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res);
712 	if (res.a0 != FFA_SUCCESS)
713 		return -EOPNOTSUPP;
714 
715 	if (res.a2 != HOST_FFA_ID)
716 		return -EINVAL;
717 
718 	arm_smccc_1_1_smc(FFA_FEATURES, FFA_FN64_RXTX_MAP,
719 			  0, 0, 0, 0, 0, 0, &res);
720 	if (res.a0 != FFA_SUCCESS)
721 		return -EOPNOTSUPP;
722 
723 	switch (res.a2) {
724 	case FFA_FEAT_RXTX_MIN_SZ_4K:
725 		min_rxtx_sz = SZ_4K;
726 		break;
727 	case FFA_FEAT_RXTX_MIN_SZ_16K:
728 		min_rxtx_sz = SZ_16K;
729 		break;
730 	case FFA_FEAT_RXTX_MIN_SZ_64K:
731 		min_rxtx_sz = SZ_64K;
732 		break;
733 	default:
734 		return -EINVAL;
735 	}
736 
737 	if (min_rxtx_sz > PAGE_SIZE)
738 		return -EOPNOTSUPP;
739 
740 	tx = pages;
741 	pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE;
742 	rx = pages;
743 	pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE;
744 
745 	ffa_desc_buf = (struct kvm_ffa_descriptor_buffer) {
746 		.buf	= pages,
747 		.len	= PAGE_SIZE *
748 			  (hyp_ffa_proxy_pages() - (2 * KVM_FFA_MBOX_NR_PAGES)),
749 	};
750 
751 	hyp_buffers = (struct kvm_ffa_buffers) {
752 		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
753 		.tx	= tx,
754 		.rx	= rx,
755 	};
756 
757 	host_buffers = (struct kvm_ffa_buffers) {
758 		.lock	= __HYP_SPIN_LOCK_UNLOCKED,
759 	};
760 
761 	return 0;
762 }
763