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