]> www.infradead.org Git - nvme.git/commitdiff
KVM: arm64: Add support for FFA_PARTITION_INFO_GET
authorSebastian Ene <sebastianene@google.com>
Thu, 13 Jun 2024 13:20:33 +0000 (13:20 +0000)
committerOliver Upton <oliver.upton@linux.dev>
Fri, 14 Jun 2024 20:28:29 +0000 (20:28 +0000)
Handle the FFA_PARTITION_INFO_GET host call inside the pKVM hypervisor
and copy the response message back to the host buffers.

Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
Tested-by: Sudeep Holla <sudeep.holla@arm.com>
Acked-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240613132035.1070360-3-sebastianene@google.com
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/hyp/nvhe/ffa.c
include/linux/arm_ffa.h

index c8ab51c331f00d0de888b3a15ee9ad0a8287894d..4eaef673e98d7785247898cee476396abcb142dc 100644 (file)
@@ -719,6 +719,55 @@ unlock:
        hyp_spin_unlock(&version_lock);
 }
 
+static void do_ffa_part_get(struct arm_smccc_res *res,
+                           struct kvm_cpu_context *ctxt)
+{
+       DECLARE_REG(u32, uuid0, ctxt, 1);
+       DECLARE_REG(u32, uuid1, ctxt, 2);
+       DECLARE_REG(u32, uuid2, ctxt, 3);
+       DECLARE_REG(u32, uuid3, ctxt, 4);
+       DECLARE_REG(u32, flags, ctxt, 5);
+       u32 count, partition_sz, copy_sz;
+
+       hyp_spin_lock(&host_buffers.lock);
+       if (!host_buffers.rx) {
+               ffa_to_smccc_res(res, FFA_RET_BUSY);
+               goto out_unlock;
+       }
+
+       arm_smccc_1_1_smc(FFA_PARTITION_INFO_GET, uuid0, uuid1,
+                         uuid2, uuid3, flags, 0, 0,
+                         res);
+
+       if (res->a0 != FFA_SUCCESS)
+               goto out_unlock;
+
+       count = res->a2;
+       if (!count)
+               goto out_unlock;
+
+       if (hyp_ffa_version > FFA_VERSION_1_0) {
+               /* Get the number of partitions deployed in the system */
+               if (flags & 0x1)
+                       goto out_unlock;
+
+               partition_sz  = res->a3;
+       } else {
+               /* FFA_VERSION_1_0 lacks the size in the response */
+               partition_sz = FFA_1_0_PARTITON_INFO_SZ;
+       }
+
+       copy_sz = partition_sz * count;
+       if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
+               ffa_to_smccc_res(res, FFA_RET_ABORTED);
+               goto out_unlock;
+       }
+
+       memcpy(host_buffers.rx, hyp_buffers.rx, copy_sz);
+out_unlock:
+       hyp_spin_unlock(&host_buffers.lock);
+}
+
 bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
 {
        struct arm_smccc_res res;
@@ -773,6 +822,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
        case FFA_VERSION:
                do_ffa_version(&res, host_ctxt);
                goto out_handled;
+       case FFA_PARTITION_INFO_GET:
+               do_ffa_part_get(&res, host_ctxt);
+               goto out_handled;
        }
 
        if (ffa_call_supported(func_id))
index c82d56768101395c36763373705c9315d2acb8c6..c6d18f50f6712ce5d2a3bbbfc741df6d3e62a154 100644 (file)
@@ -212,6 +212,9 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev) { return false; }
 
 extern const struct bus_type ffa_bus_type;
 
+/* The FF-A 1.0 partition structure lacks the uuid[4] */
+#define FFA_1_0_PARTITON_INFO_SZ       (8)
+
 /* FFA transport related */
 struct ffa_partition_info {
        u16 id;