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 static u32 hyp_ffa_version;
71 static bool has_version_negotiated;
72 static hyp_spinlock_t version_lock;
73
ffa_to_smccc_error(struct arm_smccc_res * res,u64 ffa_errno)74 static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
75 {
76 *res = (struct arm_smccc_res) {
77 .a0 = FFA_ERROR,
78 .a2 = ffa_errno,
79 };
80 }
81
ffa_to_smccc_res_prop(struct arm_smccc_res * res,int ret,u64 prop)82 static void ffa_to_smccc_res_prop(struct arm_smccc_res *res, int ret, u64 prop)
83 {
84 if (ret == FFA_RET_SUCCESS) {
85 *res = (struct arm_smccc_res) { .a0 = FFA_SUCCESS,
86 .a2 = prop };
87 } else {
88 ffa_to_smccc_error(res, ret);
89 }
90 }
91
ffa_to_smccc_res(struct arm_smccc_res * res,int ret)92 static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret)
93 {
94 ffa_to_smccc_res_prop(res, ret, 0);
95 }
96
ffa_set_retval(struct kvm_cpu_context * ctxt,struct arm_smccc_res * res)97 static void ffa_set_retval(struct kvm_cpu_context *ctxt,
98 struct arm_smccc_res *res)
99 {
100 cpu_reg(ctxt, 0) = res->a0;
101 cpu_reg(ctxt, 1) = res->a1;
102 cpu_reg(ctxt, 2) = res->a2;
103 cpu_reg(ctxt, 3) = res->a3;
104 }
105
is_ffa_call(u64 func_id)106 static bool is_ffa_call(u64 func_id)
107 {
108 return ARM_SMCCC_IS_FAST_CALL(func_id) &&
109 ARM_SMCCC_OWNER_NUM(func_id) == ARM_SMCCC_OWNER_STANDARD &&
110 ARM_SMCCC_FUNC_NUM(func_id) >= FFA_MIN_FUNC_NUM &&
111 ARM_SMCCC_FUNC_NUM(func_id) <= FFA_MAX_FUNC_NUM;
112 }
113
ffa_map_hyp_buffers(u64 ffa_page_count)114 static int ffa_map_hyp_buffers(u64 ffa_page_count)
115 {
116 struct arm_smccc_res res;
117
118 arm_smccc_1_1_smc(FFA_FN64_RXTX_MAP,
119 hyp_virt_to_phys(hyp_buffers.tx),
120 hyp_virt_to_phys(hyp_buffers.rx),
121 ffa_page_count,
122 0, 0, 0, 0,
123 &res);
124
125 return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
126 }
127
ffa_unmap_hyp_buffers(void)128 static int ffa_unmap_hyp_buffers(void)
129 {
130 struct arm_smccc_res res;
131
132 arm_smccc_1_1_smc(FFA_RXTX_UNMAP,
133 HOST_FFA_ID,
134 0, 0, 0, 0, 0, 0,
135 &res);
136
137 return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
138 }
139
ffa_mem_frag_tx(struct arm_smccc_res * res,u32 handle_lo,u32 handle_hi,u32 fraglen,u32 endpoint_id)140 static void ffa_mem_frag_tx(struct arm_smccc_res *res, u32 handle_lo,
141 u32 handle_hi, u32 fraglen, u32 endpoint_id)
142 {
143 arm_smccc_1_1_smc(FFA_MEM_FRAG_TX,
144 handle_lo, handle_hi, fraglen, endpoint_id,
145 0, 0, 0,
146 res);
147 }
148
ffa_mem_frag_rx(struct arm_smccc_res * res,u32 handle_lo,u32 handle_hi,u32 fragoff)149 static void ffa_mem_frag_rx(struct arm_smccc_res *res, u32 handle_lo,
150 u32 handle_hi, u32 fragoff)
151 {
152 arm_smccc_1_1_smc(FFA_MEM_FRAG_RX,
153 handle_lo, handle_hi, fragoff, HOST_FFA_ID,
154 0, 0, 0,
155 res);
156 }
157
ffa_mem_xfer(struct arm_smccc_res * res,u64 func_id,u32 len,u32 fraglen)158 static void ffa_mem_xfer(struct arm_smccc_res *res, u64 func_id, u32 len,
159 u32 fraglen)
160 {
161 arm_smccc_1_1_smc(func_id, len, fraglen,
162 0, 0, 0, 0, 0,
163 res);
164 }
165
ffa_mem_reclaim(struct arm_smccc_res * res,u32 handle_lo,u32 handle_hi,u32 flags)166 static void ffa_mem_reclaim(struct arm_smccc_res *res, u32 handle_lo,
167 u32 handle_hi, u32 flags)
168 {
169 arm_smccc_1_1_smc(FFA_MEM_RECLAIM,
170 handle_lo, handle_hi, flags,
171 0, 0, 0, 0,
172 res);
173 }
174
ffa_retrieve_req(struct arm_smccc_res * res,u32 len)175 static void ffa_retrieve_req(struct arm_smccc_res *res, u32 len)
176 {
177 arm_smccc_1_1_smc(FFA_FN64_MEM_RETRIEVE_REQ,
178 len, len,
179 0, 0, 0, 0, 0,
180 res);
181 }
182
ffa_rx_release(struct arm_smccc_res * res)183 static void ffa_rx_release(struct arm_smccc_res *res)
184 {
185 arm_smccc_1_1_smc(FFA_RX_RELEASE,
186 0, 0,
187 0, 0, 0, 0, 0,
188 res);
189 }
190
do_ffa_rxtx_map(struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)191 static void do_ffa_rxtx_map(struct arm_smccc_res *res,
192 struct kvm_cpu_context *ctxt)
193 {
194 DECLARE_REG(phys_addr_t, tx, ctxt, 1);
195 DECLARE_REG(phys_addr_t, rx, ctxt, 2);
196 DECLARE_REG(u32, npages, ctxt, 3);
197 int ret = 0;
198 void *rx_virt, *tx_virt;
199
200 if (npages != (KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) / FFA_PAGE_SIZE) {
201 ret = FFA_RET_INVALID_PARAMETERS;
202 goto out;
203 }
204
205 if (!PAGE_ALIGNED(tx) || !PAGE_ALIGNED(rx)) {
206 ret = FFA_RET_INVALID_PARAMETERS;
207 goto out;
208 }
209
210 hyp_spin_lock(&host_buffers.lock);
211 if (host_buffers.tx) {
212 ret = FFA_RET_DENIED;
213 goto out_unlock;
214 }
215
216 /*
217 * Map our hypervisor buffers into the SPMD before mapping and
218 * pinning the host buffers in our own address space.
219 */
220 ret = ffa_map_hyp_buffers(npages);
221 if (ret)
222 goto out_unlock;
223
224 ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(tx));
225 if (ret) {
226 ret = FFA_RET_INVALID_PARAMETERS;
227 goto err_unmap;
228 }
229
230 ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(rx));
231 if (ret) {
232 ret = FFA_RET_INVALID_PARAMETERS;
233 goto err_unshare_tx;
234 }
235
236 tx_virt = hyp_phys_to_virt(tx);
237 ret = hyp_pin_shared_mem(tx_virt, tx_virt + 1);
238 if (ret) {
239 ret = FFA_RET_INVALID_PARAMETERS;
240 goto err_unshare_rx;
241 }
242
243 rx_virt = hyp_phys_to_virt(rx);
244 ret = hyp_pin_shared_mem(rx_virt, rx_virt + 1);
245 if (ret) {
246 ret = FFA_RET_INVALID_PARAMETERS;
247 goto err_unpin_tx;
248 }
249
250 host_buffers.tx = tx_virt;
251 host_buffers.rx = rx_virt;
252
253 out_unlock:
254 hyp_spin_unlock(&host_buffers.lock);
255 out:
256 ffa_to_smccc_res(res, ret);
257 return;
258
259 err_unpin_tx:
260 hyp_unpin_shared_mem(tx_virt, tx_virt + 1);
261 err_unshare_rx:
262 __pkvm_host_unshare_hyp(hyp_phys_to_pfn(rx));
263 err_unshare_tx:
264 __pkvm_host_unshare_hyp(hyp_phys_to_pfn(tx));
265 err_unmap:
266 ffa_unmap_hyp_buffers();
267 goto out_unlock;
268 }
269
do_ffa_rxtx_unmap(struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)270 static void do_ffa_rxtx_unmap(struct arm_smccc_res *res,
271 struct kvm_cpu_context *ctxt)
272 {
273 DECLARE_REG(u32, id, ctxt, 1);
274 int ret = 0;
275
276 if (id != HOST_FFA_ID) {
277 ret = FFA_RET_INVALID_PARAMETERS;
278 goto out;
279 }
280
281 hyp_spin_lock(&host_buffers.lock);
282 if (!host_buffers.tx) {
283 ret = FFA_RET_INVALID_PARAMETERS;
284 goto out_unlock;
285 }
286
287 hyp_unpin_shared_mem(host_buffers.tx, host_buffers.tx + 1);
288 WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.tx)));
289 host_buffers.tx = NULL;
290
291 hyp_unpin_shared_mem(host_buffers.rx, host_buffers.rx + 1);
292 WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.rx)));
293 host_buffers.rx = NULL;
294
295 ffa_unmap_hyp_buffers();
296
297 out_unlock:
298 hyp_spin_unlock(&host_buffers.lock);
299 out:
300 ffa_to_smccc_res(res, ret);
301 }
302
__ffa_host_share_ranges(struct ffa_mem_region_addr_range * ranges,u32 nranges)303 static u32 __ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges,
304 u32 nranges)
305 {
306 u32 i;
307
308 for (i = 0; i < nranges; ++i) {
309 struct ffa_mem_region_addr_range *range = &ranges[i];
310 u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE;
311 u64 pfn = hyp_phys_to_pfn(range->address);
312
313 if (!PAGE_ALIGNED(sz))
314 break;
315
316 if (__pkvm_host_share_ffa(pfn, sz / PAGE_SIZE))
317 break;
318 }
319
320 return i;
321 }
322
__ffa_host_unshare_ranges(struct ffa_mem_region_addr_range * ranges,u32 nranges)323 static u32 __ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges,
324 u32 nranges)
325 {
326 u32 i;
327
328 for (i = 0; i < nranges; ++i) {
329 struct ffa_mem_region_addr_range *range = &ranges[i];
330 u64 sz = (u64)range->pg_cnt * FFA_PAGE_SIZE;
331 u64 pfn = hyp_phys_to_pfn(range->address);
332
333 if (!PAGE_ALIGNED(sz))
334 break;
335
336 if (__pkvm_host_unshare_ffa(pfn, sz / PAGE_SIZE))
337 break;
338 }
339
340 return i;
341 }
342
ffa_host_share_ranges(struct ffa_mem_region_addr_range * ranges,u32 nranges)343 static int ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges,
344 u32 nranges)
345 {
346 u32 nshared = __ffa_host_share_ranges(ranges, nranges);
347 int ret = 0;
348
349 if (nshared != nranges) {
350 WARN_ON(__ffa_host_unshare_ranges(ranges, nshared) != nshared);
351 ret = FFA_RET_DENIED;
352 }
353
354 return ret;
355 }
356
ffa_host_unshare_ranges(struct ffa_mem_region_addr_range * ranges,u32 nranges)357 static int ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges,
358 u32 nranges)
359 {
360 u32 nunshared = __ffa_host_unshare_ranges(ranges, nranges);
361 int ret = 0;
362
363 if (nunshared != nranges) {
364 WARN_ON(__ffa_host_share_ranges(ranges, nunshared) != nunshared);
365 ret = FFA_RET_DENIED;
366 }
367
368 return ret;
369 }
370
do_ffa_mem_frag_tx(struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)371 static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
372 struct kvm_cpu_context *ctxt)
373 {
374 DECLARE_REG(u32, handle_lo, ctxt, 1);
375 DECLARE_REG(u32, handle_hi, ctxt, 2);
376 DECLARE_REG(u32, fraglen, ctxt, 3);
377 DECLARE_REG(u32, endpoint_id, ctxt, 4);
378 struct ffa_mem_region_addr_range *buf;
379 int ret = FFA_RET_INVALID_PARAMETERS;
380 u32 nr_ranges;
381
382 if (fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)
383 goto out;
384
385 if (fraglen % sizeof(*buf))
386 goto out;
387
388 hyp_spin_lock(&host_buffers.lock);
389 if (!host_buffers.tx)
390 goto out_unlock;
391
392 buf = hyp_buffers.tx;
393 memcpy(buf, host_buffers.tx, fraglen);
394 nr_ranges = fraglen / sizeof(*buf);
395
396 ret = ffa_host_share_ranges(buf, nr_ranges);
397 if (ret) {
398 /*
399 * We're effectively aborting the transaction, so we need
400 * to restore the global state back to what it was prior to
401 * transmission of the first fragment.
402 */
403 ffa_mem_reclaim(res, handle_lo, handle_hi, 0);
404 WARN_ON(res->a0 != FFA_SUCCESS);
405 goto out_unlock;
406 }
407
408 ffa_mem_frag_tx(res, handle_lo, handle_hi, fraglen, endpoint_id);
409 if (res->a0 != FFA_SUCCESS && res->a0 != FFA_MEM_FRAG_RX)
410 WARN_ON(ffa_host_unshare_ranges(buf, nr_ranges));
411
412 out_unlock:
413 hyp_spin_unlock(&host_buffers.lock);
414 out:
415 if (ret)
416 ffa_to_smccc_res(res, ret);
417
418 /*
419 * If for any reason this did not succeed, we're in trouble as we have
420 * now lost the content of the previous fragments and we can't rollback
421 * the host stage-2 changes. The pages previously marked as shared will
422 * remain stuck in that state forever, hence preventing the host from
423 * sharing/donating them again and may possibly lead to subsequent
424 * failures, but this will not compromise confidentiality.
425 */
426 return;
427 }
428
__do_ffa_mem_xfer(const u64 func_id,struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)429 static void __do_ffa_mem_xfer(const u64 func_id,
430 struct arm_smccc_res *res,
431 struct kvm_cpu_context *ctxt)
432 {
433 DECLARE_REG(u32, len, ctxt, 1);
434 DECLARE_REG(u32, fraglen, ctxt, 2);
435 DECLARE_REG(u64, addr_mbz, ctxt, 3);
436 DECLARE_REG(u32, npages_mbz, ctxt, 4);
437 struct ffa_mem_region_attributes *ep_mem_access;
438 struct ffa_composite_mem_region *reg;
439 struct ffa_mem_region *buf;
440 u32 offset, nr_ranges;
441 int ret = 0;
442
443 if (addr_mbz || npages_mbz || fraglen > len ||
444 fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
445 ret = FFA_RET_INVALID_PARAMETERS;
446 goto out;
447 }
448
449 if (fraglen < sizeof(struct ffa_mem_region) +
450 sizeof(struct ffa_mem_region_attributes)) {
451 ret = FFA_RET_INVALID_PARAMETERS;
452 goto out;
453 }
454
455 hyp_spin_lock(&host_buffers.lock);
456 if (!host_buffers.tx) {
457 ret = FFA_RET_INVALID_PARAMETERS;
458 goto out_unlock;
459 }
460
461 if (len > ffa_desc_buf.len) {
462 ret = FFA_RET_NO_MEMORY;
463 goto out_unlock;
464 }
465
466 buf = hyp_buffers.tx;
467 memcpy(buf, host_buffers.tx, fraglen);
468
469 ep_mem_access = (void *)buf +
470 ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
471 offset = ep_mem_access->composite_off;
472 if (!offset || buf->ep_count != 1 || buf->sender_id != HOST_FFA_ID) {
473 ret = FFA_RET_INVALID_PARAMETERS;
474 goto out_unlock;
475 }
476
477 if (fraglen < offset + sizeof(struct ffa_composite_mem_region)) {
478 ret = FFA_RET_INVALID_PARAMETERS;
479 goto out_unlock;
480 }
481
482 reg = (void *)buf + offset;
483 nr_ranges = ((void *)buf + fraglen) - (void *)reg->constituents;
484 if (nr_ranges % sizeof(reg->constituents[0])) {
485 ret = FFA_RET_INVALID_PARAMETERS;
486 goto out_unlock;
487 }
488
489 nr_ranges /= sizeof(reg->constituents[0]);
490 ret = ffa_host_share_ranges(reg->constituents, nr_ranges);
491 if (ret)
492 goto out_unlock;
493
494 ffa_mem_xfer(res, func_id, len, fraglen);
495 if (fraglen != len) {
496 if (res->a0 != FFA_MEM_FRAG_RX)
497 goto err_unshare;
498
499 if (res->a3 != fraglen)
500 goto err_unshare;
501 } else if (res->a0 != FFA_SUCCESS) {
502 goto err_unshare;
503 }
504
505 out_unlock:
506 hyp_spin_unlock(&host_buffers.lock);
507 out:
508 if (ret)
509 ffa_to_smccc_res(res, ret);
510 return;
511
512 err_unshare:
513 WARN_ON(ffa_host_unshare_ranges(reg->constituents, nr_ranges));
514 goto out_unlock;
515 }
516
517 #define do_ffa_mem_xfer(fid, res, ctxt) \
518 do { \
519 BUILD_BUG_ON((fid) != FFA_FN64_MEM_SHARE && \
520 (fid) != FFA_FN64_MEM_LEND); \
521 __do_ffa_mem_xfer((fid), (res), (ctxt)); \
522 } while (0);
523
do_ffa_mem_reclaim(struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)524 static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
525 struct kvm_cpu_context *ctxt)
526 {
527 DECLARE_REG(u32, handle_lo, ctxt, 1);
528 DECLARE_REG(u32, handle_hi, ctxt, 2);
529 DECLARE_REG(u32, flags, ctxt, 3);
530 struct ffa_mem_region_attributes *ep_mem_access;
531 struct ffa_composite_mem_region *reg;
532 u32 offset, len, fraglen, fragoff;
533 struct ffa_mem_region *buf;
534 int ret = 0;
535 u64 handle;
536
537 handle = PACK_HANDLE(handle_lo, handle_hi);
538
539 hyp_spin_lock(&host_buffers.lock);
540
541 buf = hyp_buffers.tx;
542 *buf = (struct ffa_mem_region) {
543 .sender_id = HOST_FFA_ID,
544 .handle = handle,
545 };
546
547 ffa_retrieve_req(res, sizeof(*buf));
548 buf = hyp_buffers.rx;
549 if (res->a0 != FFA_MEM_RETRIEVE_RESP)
550 goto out_unlock;
551
552 len = res->a1;
553 fraglen = res->a2;
554
555 ep_mem_access = (void *)buf +
556 ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
557 offset = ep_mem_access->composite_off;
558 /*
559 * We can trust the SPMD to get this right, but let's at least
560 * check that we end up with something that doesn't look _completely_
561 * bogus.
562 */
563 if (WARN_ON(offset > len ||
564 fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
565 ret = FFA_RET_ABORTED;
566 ffa_rx_release(res);
567 goto out_unlock;
568 }
569
570 if (len > ffa_desc_buf.len) {
571 ret = FFA_RET_NO_MEMORY;
572 ffa_rx_release(res);
573 goto out_unlock;
574 }
575
576 buf = ffa_desc_buf.buf;
577 memcpy(buf, hyp_buffers.rx, fraglen);
578 ffa_rx_release(res);
579
580 for (fragoff = fraglen; fragoff < len; fragoff += fraglen) {
581 ffa_mem_frag_rx(res, handle_lo, handle_hi, fragoff);
582 if (res->a0 != FFA_MEM_FRAG_TX) {
583 ret = FFA_RET_INVALID_PARAMETERS;
584 goto out_unlock;
585 }
586
587 fraglen = res->a3;
588 memcpy((void *)buf + fragoff, hyp_buffers.rx, fraglen);
589 ffa_rx_release(res);
590 }
591
592 ffa_mem_reclaim(res, handle_lo, handle_hi, flags);
593 if (res->a0 != FFA_SUCCESS)
594 goto out_unlock;
595
596 reg = (void *)buf + offset;
597 /* If the SPMD was happy, then we should be too. */
598 WARN_ON(ffa_host_unshare_ranges(reg->constituents,
599 reg->addr_range_cnt));
600 out_unlock:
601 hyp_spin_unlock(&host_buffers.lock);
602
603 if (ret)
604 ffa_to_smccc_res(res, ret);
605 }
606
607 /*
608 * Is a given FFA function supported, either by forwarding on directly
609 * or by handling at EL2?
610 */
ffa_call_supported(u64 func_id)611 static bool ffa_call_supported(u64 func_id)
612 {
613 switch (func_id) {
614 /* Unsupported memory management calls */
615 case FFA_FN64_MEM_RETRIEVE_REQ:
616 case FFA_MEM_RETRIEVE_RESP:
617 case FFA_MEM_RELINQUISH:
618 case FFA_MEM_OP_PAUSE:
619 case FFA_MEM_OP_RESUME:
620 case FFA_MEM_FRAG_RX:
621 case FFA_FN64_MEM_DONATE:
622 /* Indirect message passing via RX/TX buffers */
623 case FFA_MSG_SEND:
624 case FFA_MSG_POLL:
625 case FFA_MSG_WAIT:
626 /* 32-bit variants of 64-bit calls */
627 case FFA_MSG_SEND_DIRECT_RESP:
628 case FFA_RXTX_MAP:
629 case FFA_MEM_DONATE:
630 case FFA_MEM_RETRIEVE_REQ:
631 return false;
632 }
633
634 return true;
635 }
636
do_ffa_features(struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)637 static bool do_ffa_features(struct arm_smccc_res *res,
638 struct kvm_cpu_context *ctxt)
639 {
640 DECLARE_REG(u32, id, ctxt, 1);
641 u64 prop = 0;
642 int ret = 0;
643
644 if (!ffa_call_supported(id)) {
645 ret = FFA_RET_NOT_SUPPORTED;
646 goto out_handled;
647 }
648
649 switch (id) {
650 case FFA_MEM_SHARE:
651 case FFA_FN64_MEM_SHARE:
652 case FFA_MEM_LEND:
653 case FFA_FN64_MEM_LEND:
654 ret = FFA_RET_SUCCESS;
655 prop = 0; /* No support for dynamic buffers */
656 goto out_handled;
657 default:
658 return false;
659 }
660
661 out_handled:
662 ffa_to_smccc_res_prop(res, ret, prop);
663 return true;
664 }
665
hyp_ffa_post_init(void)666 static int hyp_ffa_post_init(void)
667 {
668 size_t min_rxtx_sz;
669 struct arm_smccc_res res;
670
671 arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res);
672 if (res.a0 != FFA_SUCCESS)
673 return -EOPNOTSUPP;
674
675 if (res.a2 != HOST_FFA_ID)
676 return -EINVAL;
677
678 arm_smccc_1_1_smc(FFA_FEATURES, FFA_FN64_RXTX_MAP,
679 0, 0, 0, 0, 0, 0, &res);
680 if (res.a0 != FFA_SUCCESS)
681 return -EOPNOTSUPP;
682
683 switch (res.a2) {
684 case FFA_FEAT_RXTX_MIN_SZ_4K:
685 min_rxtx_sz = SZ_4K;
686 break;
687 case FFA_FEAT_RXTX_MIN_SZ_16K:
688 min_rxtx_sz = SZ_16K;
689 break;
690 case FFA_FEAT_RXTX_MIN_SZ_64K:
691 min_rxtx_sz = SZ_64K;
692 break;
693 default:
694 return -EINVAL;
695 }
696
697 if (min_rxtx_sz > PAGE_SIZE)
698 return -EOPNOTSUPP;
699
700 return 0;
701 }
702
do_ffa_version(struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)703 static void do_ffa_version(struct arm_smccc_res *res,
704 struct kvm_cpu_context *ctxt)
705 {
706 DECLARE_REG(u32, ffa_req_version, ctxt, 1);
707
708 if (FFA_MAJOR_VERSION(ffa_req_version) != 1) {
709 res->a0 = FFA_RET_NOT_SUPPORTED;
710 return;
711 }
712
713 hyp_spin_lock(&version_lock);
714 if (has_version_negotiated) {
715 res->a0 = hyp_ffa_version;
716 goto unlock;
717 }
718
719 /*
720 * If the client driver tries to downgrade the version, we need to ask
721 * first if TEE supports it.
722 */
723 if (FFA_MINOR_VERSION(ffa_req_version) < FFA_MINOR_VERSION(hyp_ffa_version)) {
724 arm_smccc_1_1_smc(FFA_VERSION, ffa_req_version, 0,
725 0, 0, 0, 0, 0,
726 res);
727 if (res->a0 == FFA_RET_NOT_SUPPORTED)
728 goto unlock;
729
730 hyp_ffa_version = ffa_req_version;
731 }
732
733 if (hyp_ffa_post_init())
734 res->a0 = FFA_RET_NOT_SUPPORTED;
735 else {
736 has_version_negotiated = true;
737 res->a0 = hyp_ffa_version;
738 }
739 unlock:
740 hyp_spin_unlock(&version_lock);
741 }
742
do_ffa_part_get(struct arm_smccc_res * res,struct kvm_cpu_context * ctxt)743 static void do_ffa_part_get(struct arm_smccc_res *res,
744 struct kvm_cpu_context *ctxt)
745 {
746 DECLARE_REG(u32, uuid0, ctxt, 1);
747 DECLARE_REG(u32, uuid1, ctxt, 2);
748 DECLARE_REG(u32, uuid2, ctxt, 3);
749 DECLARE_REG(u32, uuid3, ctxt, 4);
750 DECLARE_REG(u32, flags, ctxt, 5);
751 u32 count, partition_sz, copy_sz;
752
753 hyp_spin_lock(&host_buffers.lock);
754 if (!host_buffers.rx) {
755 ffa_to_smccc_res(res, FFA_RET_BUSY);
756 goto out_unlock;
757 }
758
759 arm_smccc_1_1_smc(FFA_PARTITION_INFO_GET, uuid0, uuid1,
760 uuid2, uuid3, flags, 0, 0,
761 res);
762
763 if (res->a0 != FFA_SUCCESS)
764 goto out_unlock;
765
766 count = res->a2;
767 if (!count)
768 goto out_unlock;
769
770 if (hyp_ffa_version > FFA_VERSION_1_0) {
771 /* Get the number of partitions deployed in the system */
772 if (flags & 0x1)
773 goto out_unlock;
774
775 partition_sz = res->a3;
776 } else {
777 /* FFA_VERSION_1_0 lacks the size in the response */
778 partition_sz = FFA_1_0_PARTITON_INFO_SZ;
779 }
780
781 copy_sz = partition_sz * count;
782 if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
783 ffa_to_smccc_res(res, FFA_RET_ABORTED);
784 goto out_unlock;
785 }
786
787 memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
788 out_unlock:
789 hyp_spin_unlock(&host_buffers.lock);
790 }
791
kvm_host_ffa_handler(struct kvm_cpu_context * host_ctxt,u32 func_id)792 bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
793 {
794 struct arm_smccc_res res;
795
796 /*
797 * There's no way we can tell what a non-standard SMC call might
798 * be up to. Ideally, we would terminate these here and return
799 * an error to the host, but sadly devices make use of custom
800 * firmware calls for things like power management, debugging,
801 * RNG access and crash reporting.
802 *
803 * Given that the architecture requires us to trust EL3 anyway,
804 * we forward unrecognised calls on under the assumption that
805 * the firmware doesn't expose a mechanism to access arbitrary
806 * non-secure memory. Short of a per-device table of SMCs, this
807 * is the best we can do.
808 */
809 if (!is_ffa_call(func_id))
810 return false;
811
812 if (!has_version_negotiated && func_id != FFA_VERSION) {
813 ffa_to_smccc_error(&res, FFA_RET_INVALID_PARAMETERS);
814 goto out_handled;
815 }
816
817 switch (func_id) {
818 case FFA_FEATURES:
819 if (!do_ffa_features(&res, host_ctxt))
820 return false;
821 goto out_handled;
822 /* Memory management */
823 case FFA_FN64_RXTX_MAP:
824 do_ffa_rxtx_map(&res, host_ctxt);
825 goto out_handled;
826 case FFA_RXTX_UNMAP:
827 do_ffa_rxtx_unmap(&res, host_ctxt);
828 goto out_handled;
829 case FFA_MEM_SHARE:
830 case FFA_FN64_MEM_SHARE:
831 do_ffa_mem_xfer(FFA_FN64_MEM_SHARE, &res, host_ctxt);
832 goto out_handled;
833 case FFA_MEM_RECLAIM:
834 do_ffa_mem_reclaim(&res, host_ctxt);
835 goto out_handled;
836 case FFA_MEM_LEND:
837 case FFA_FN64_MEM_LEND:
838 do_ffa_mem_xfer(FFA_FN64_MEM_LEND, &res, host_ctxt);
839 goto out_handled;
840 case FFA_MEM_FRAG_TX:
841 do_ffa_mem_frag_tx(&res, host_ctxt);
842 goto out_handled;
843 case FFA_VERSION:
844 do_ffa_version(&res, host_ctxt);
845 goto out_handled;
846 case FFA_PARTITION_INFO_GET:
847 do_ffa_part_get(&res, host_ctxt);
848 goto out_handled;
849 }
850
851 if (ffa_call_supported(func_id))
852 return false; /* Pass through */
853
854 ffa_to_smccc_error(&res, FFA_RET_NOT_SUPPORTED);
855 out_handled:
856 ffa_set_retval(host_ctxt, &res);
857 return true;
858 }
859
hyp_ffa_init(void * pages)860 int hyp_ffa_init(void *pages)
861 {
862 struct arm_smccc_res res;
863 void *tx, *rx;
864
865 if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
866 return 0;
867
868 arm_smccc_1_1_smc(FFA_VERSION, FFA_VERSION_1_1, 0, 0, 0, 0, 0, 0, &res);
869 if (res.a0 == FFA_RET_NOT_SUPPORTED)
870 return 0;
871
872 /*
873 * Firmware returns the maximum supported version of the FF-A
874 * implementation. Check that the returned version is
875 * backwards-compatible with the hyp according to the rules in DEN0077A
876 * v1.1 REL0 13.2.1.
877 *
878 * Of course, things are never simple when dealing with firmware. v1.1
879 * broke ABI with v1.0 on several structures, which is itself
880 * incompatible with the aforementioned versioning scheme. The
881 * expectation is that v1.x implementations that do not support the v1.0
882 * ABI return NOT_SUPPORTED rather than a version number, according to
883 * DEN0077A v1.1 REL0 18.6.4.
884 */
885 if (FFA_MAJOR_VERSION(res.a0) != 1)
886 return -EOPNOTSUPP;
887
888 if (FFA_MINOR_VERSION(res.a0) < FFA_MINOR_VERSION(FFA_VERSION_1_1))
889 hyp_ffa_version = res.a0;
890 else
891 hyp_ffa_version = FFA_VERSION_1_1;
892
893 tx = pages;
894 pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE;
895 rx = pages;
896 pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE;
897
898 ffa_desc_buf = (struct kvm_ffa_descriptor_buffer) {
899 .buf = pages,
900 .len = PAGE_SIZE *
901 (hyp_ffa_proxy_pages() - (2 * KVM_FFA_MBOX_NR_PAGES)),
902 };
903
904 hyp_buffers = (struct kvm_ffa_buffers) {
905 .lock = __HYP_SPIN_LOCK_UNLOCKED,
906 .tx = tx,
907 .rx = rx,
908 };
909
910 host_buffers = (struct kvm_ffa_buffers) {
911 .lock = __HYP_SPIN_LOCK_UNLOCKED,
912 };
913
914 version_lock = __HYP_SPIN_LOCK_UNLOCKED;
915 return 0;
916 }
917