29 #include <linux/arm-smccc.h>
30 #include <linux/arm_ffa.h>
31 #include <asm/kvm_pkvm.h>
73 *res = (
struct arm_smccc_res) {
81 if (ret == FFA_RET_SUCCESS) {
82 *res = (
struct arm_smccc_res) { .a0 = FFA_SUCCESS,
95 struct arm_smccc_res *res)
105 return ARM_SMCCC_IS_FAST_CALL(func_id) &&
106 ARM_SMCCC_OWNER_NUM(func_id) == ARM_SMCCC_OWNER_STANDARD &&
113 struct arm_smccc_res res;
115 arm_smccc_1_1_smc(FFA_FN64_RXTX_MAP,
122 return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
127 struct arm_smccc_res res;
129 arm_smccc_1_1_smc(FFA_RXTX_UNMAP,
134 return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
138 u32 handle_hi, u32 fraglen, u32 endpoint_id)
140 arm_smccc_1_1_smc(FFA_MEM_FRAG_TX,
141 handle_lo, handle_hi, fraglen, endpoint_id,
147 u32 handle_hi, u32 fragoff)
149 arm_smccc_1_1_smc(FFA_MEM_FRAG_RX,
155 static void ffa_mem_xfer(
struct arm_smccc_res *res, u64 func_id, u32 len,
158 arm_smccc_1_1_smc(func_id, len, fraglen,
164 u32 handle_hi, u32 flags)
166 arm_smccc_1_1_smc(FFA_MEM_RECLAIM,
167 handle_lo, handle_hi, flags,
174 arm_smccc_1_1_smc(FFA_FN64_MEM_RETRIEVE_REQ,
181 struct kvm_cpu_context *ctxt)
187 void *rx_virt, *tx_virt;
189 if (npages != (KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) / FFA_PAGE_SIZE) {
190 ret = FFA_RET_INVALID_PARAMETERS;
194 if (!PAGE_ALIGNED(tx) || !PAGE_ALIGNED(rx)) {
195 ret = FFA_RET_INVALID_PARAMETERS;
201 ret = FFA_RET_DENIED;
215 ret = FFA_RET_INVALID_PARAMETERS;
221 ret = FFA_RET_INVALID_PARAMETERS;
228 ret = FFA_RET_INVALID_PARAMETERS;
235 ret = FFA_RET_INVALID_PARAMETERS;
260 struct kvm_cpu_context *ctxt)
266 ret = FFA_RET_INVALID_PARAMETERS;
272 ret = FFA_RET_INVALID_PARAMETERS;
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;
302 if (!PAGE_ALIGNED(sz))
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;
322 if (!PAGE_ALIGNED(sz))
338 if (nshared != nranges) {
340 ret = FFA_RET_DENIED;
352 if (nunshared != nranges) {
354 ret = FFA_RET_DENIED;
361 struct kvm_cpu_context *ctxt)
367 struct ffa_mem_region_addr_range *buf;
368 int ret = FFA_RET_INVALID_PARAMETERS;
371 if (fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)
374 if (fraglen %
sizeof(*buf))
383 nr_ranges = fraglen /
sizeof(*buf);
393 WARN_ON(res->a0 != FFA_SUCCESS);
398 if (res->a0 != FFA_SUCCESS && res->a0 != FFA_MEM_FRAG_RX)
419 struct arm_smccc_res *res,
420 struct kvm_cpu_context *ctxt)
426 struct ffa_mem_region_attributes *ep_mem_access;
427 struct ffa_composite_mem_region *reg;
428 struct ffa_mem_region *buf;
429 u32 offset, nr_ranges;
432 BUILD_BUG_ON(func_id != FFA_FN64_MEM_SHARE &&
433 func_id != FFA_FN64_MEM_LEND);
435 if (addr_mbz || npages_mbz || fraglen > len ||
436 fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
437 ret = FFA_RET_INVALID_PARAMETERS;
441 if (fraglen <
sizeof(
struct ffa_mem_region) +
442 sizeof(
struct ffa_mem_region_attributes)) {
443 ret = FFA_RET_INVALID_PARAMETERS;
449 ret = FFA_RET_INVALID_PARAMETERS;
456 ep_mem_access = (
void *)buf +
457 ffa_mem_desc_offset(buf, 0, FFA_VERSION_1_0);
458 offset = ep_mem_access->composite_off;
459 if (!offset || buf->ep_count != 1 || buf->sender_id !=
HOST_FFA_ID) {
460 ret = FFA_RET_INVALID_PARAMETERS;
464 if (fraglen < offset +
sizeof(
struct ffa_composite_mem_region)) {
465 ret = FFA_RET_INVALID_PARAMETERS;
469 reg = (
void *)buf + offset;
470 nr_ranges = ((
void *)buf + fraglen) - (
void *)reg->constituents;
471 if (nr_ranges %
sizeof(reg->constituents[0])) {
472 ret = FFA_RET_INVALID_PARAMETERS;
476 nr_ranges /=
sizeof(reg->constituents[0]);
482 if (fraglen != len) {
483 if (res->a0 != FFA_MEM_FRAG_RX)
486 if (res->a3 != fraglen)
488 }
else if (res->a0 != FFA_SUCCESS) {
505 struct kvm_cpu_context *ctxt)
510 struct ffa_mem_region_attributes *ep_mem_access;
511 struct ffa_composite_mem_region *reg;
512 u32 offset, len, fraglen, fragoff;
513 struct ffa_mem_region *buf;
517 handle = PACK_HANDLE(handle_lo, handle_hi);
522 *buf = (
struct ffa_mem_region) {
529 if (res->a0 != FFA_MEM_RETRIEVE_RESP)
535 ep_mem_access = (
void *)buf +
536 ffa_mem_desc_offset(buf, 0, FFA_VERSION_1_0);
537 offset = ep_mem_access->composite_off;
543 if (WARN_ON(offset > len ||
544 fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
545 ret = FFA_RET_ABORTED;
550 ret = FFA_RET_NO_MEMORY;
557 for (fragoff = fraglen; fragoff < len; fragoff += fraglen) {
559 if (res->a0 != FFA_MEM_FRAG_TX) {
560 ret = FFA_RET_INVALID_PARAMETERS;
569 if (res->a0 != FFA_SUCCESS)
572 reg = (
void *)buf + offset;
575 reg->addr_range_cnt));
591 case FFA_FN64_MEM_RETRIEVE_REQ:
592 case FFA_MEM_RETRIEVE_RESP:
593 case FFA_MEM_RELINQUISH:
594 case FFA_MEM_OP_PAUSE:
595 case FFA_MEM_OP_RESUME:
596 case FFA_MEM_FRAG_RX:
597 case FFA_FN64_MEM_DONATE:
603 case FFA_MSG_SEND_DIRECT_REQ:
604 case FFA_MSG_SEND_DIRECT_RESP:
607 case FFA_MEM_RETRIEVE_REQ:
615 struct kvm_cpu_context *ctxt)
622 ret = FFA_RET_NOT_SUPPORTED;
628 case FFA_FN64_MEM_SHARE:
630 case FFA_FN64_MEM_LEND:
631 ret = FFA_RET_SUCCESS;
645 struct arm_smccc_res res;
669 case FFA_FN64_RXTX_MAP:
676 case FFA_FN64_MEM_SHARE:
679 case FFA_MEM_RECLAIM:
683 case FFA_FN64_MEM_LEND:
686 case FFA_MEM_FRAG_TX:
702 struct arm_smccc_res res;
709 arm_smccc_1_1_smc(FFA_VERSION, FFA_VERSION_1_0, 0, 0, 0, 0, 0, 0, &res);
710 if (res.a0 == FFA_RET_NOT_SUPPORTED)
726 if (FFA_MAJOR_VERSION(res.a0) != 1)
729 arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res);
730 if (res.a0 != FFA_SUCCESS)
736 arm_smccc_1_1_smc(FFA_FEATURES, FFA_FN64_RXTX_MAP,
737 0, 0, 0, 0, 0, 0, &res);
738 if (res.a0 != FFA_SUCCESS)
742 case FFA_FEAT_RXTX_MIN_SZ_4K:
745 case FFA_FEAT_RXTX_MIN_SZ_16K:
746 min_rxtx_sz = SZ_16K;
748 case FFA_FEAT_RXTX_MIN_SZ_64K:
749 min_rxtx_sz = SZ_64K;
755 if (min_rxtx_sz > PAGE_SIZE)
759 pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE;
761 pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE;
766 (hyp_ffa_proxy_pages() - (2 * KVM_FFA_MBOX_NR_PAGES)),
static bool do_ffa_features(struct arm_smccc_res *res, struct kvm_cpu_context *ctxt)
static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
static void do_ffa_rxtx_map(struct arm_smccc_res *res, struct kvm_cpu_context *ctxt)
static void ffa_mem_frag_tx(struct arm_smccc_res *res, u32 handle_lo, u32 handle_hi, u32 fraglen, u32 endpoint_id)
static void ffa_set_retval(struct kvm_cpu_context *ctxt, struct arm_smccc_res *res)
static int ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges, u32 nranges)
static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret)
static void do_ffa_mem_reclaim(struct arm_smccc_res *res, struct kvm_cpu_context *ctxt)
static void ffa_retrieve_req(struct arm_smccc_res *res, u32 len)
static int ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges, u32 nranges)
static void ffa_mem_frag_rx(struct arm_smccc_res *res, u32 handle_lo, u32 handle_hi, u32 fragoff)
static __always_inline void do_ffa_mem_xfer(const u64 func_id, struct arm_smccc_res *res, struct kvm_cpu_context *ctxt)
int hyp_ffa_init(void *pages)
static u32 __ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges, u32 nranges)
static struct kvm_ffa_buffers host_buffers
static void ffa_mem_xfer(struct arm_smccc_res *res, u64 func_id, u32 len, u32 fraglen)
static void do_ffa_rxtx_unmap(struct arm_smccc_res *res, struct kvm_cpu_context *ctxt)
static u32 __ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges, u32 nranges)
static void ffa_mem_reclaim(struct arm_smccc_res *res, u32 handle_lo, u32 handle_hi, u32 flags)
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
static int ffa_unmap_hyp_buffers(void)
static int ffa_map_hyp_buffers(u64 ffa_page_count)
static struct kvm_ffa_buffers hyp_buffers
static void do_ffa_mem_frag_tx(struct arm_smccc_res *res, struct kvm_cpu_context *ctxt)
static struct kvm_ffa_descriptor_buffer ffa_desc_buf
static bool ffa_call_supported(u64 func_id)
static bool is_ffa_call(u64 func_id)
static void ffa_to_smccc_res_prop(struct arm_smccc_res *res, int ret, u64 prop)
int __pkvm_host_unshare_ffa(u64 pfn, u64 nr_pages)
void hyp_unpin_shared_mem(void *from, void *to)
int __pkvm_host_unshare_hyp(u64 pfn)
int __pkvm_host_share_hyp(u64 pfn)
int hyp_pin_shared_mem(void *from, void *to)
int __pkvm_host_share_ffa(u64 pfn, u64 nr_pages)
static void * hyp_phys_to_virt(phys_addr_t phys)
#define hyp_phys_to_pfn(phys)
static phys_addr_t hyp_virt_to_phys(void *addr)
#define hyp_virt_to_pfn(virt)
struct kvm_host_psci_config __ro_after_init kvm_host_psci_config
static void hyp_spin_unlock(hyp_spinlock_t *lock)
#define __HYP_SPIN_LOCK_UNLOCKED
static void hyp_spin_lock(hyp_spinlock_t *lock)
#define DECLARE_REG(type, name, ctxt, reg)