KVM: arm64: Handle FFA_FEATURES call from the host
authorFuad Tabba <tabba@google.com>
Tue, 23 May 2023 10:18:26 +0000 (11:18 +0100)
committerOliver Upton <oliver.upton@linux.dev>
Thu, 1 Jun 2023 21:34:51 +0000 (21:34 +0000)
Filter out advertising unsupported features, and only advertise
features and properties that are supported by the hypervisor proxy.

Signed-off-by: Fuad Tabba <tabba@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20230523101828.7328-10-will@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/hyp/nvhe/ffa.c

index d90ab1c9ec72920156f9faa58a88f60e232a927e..926314a9b9d77d46e12336f68b427a87270fe4aa 100644 (file)
@@ -64,15 +64,21 @@ static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
        };
 }
 
-static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret)
+static void ffa_to_smccc_res_prop(struct arm_smccc_res *res, int ret, u64 prop)
 {
        if (ret == FFA_RET_SUCCESS) {
-               *res = (struct arm_smccc_res) { .a0 = FFA_SUCCESS };
+               *res = (struct arm_smccc_res) { .a0 = FFA_SUCCESS,
+                                               .a2 = prop };
        } else {
                ffa_to_smccc_error(res, ret);
        }
 }
 
+static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret)
+{
+       ffa_to_smccc_res_prop(res, ret, 0);
+}
+
 static void ffa_set_retval(struct kvm_cpu_context *ctxt,
                           struct arm_smccc_res *res)
 {
@@ -484,14 +490,41 @@ static bool ffa_call_supported(u64 func_id)
        case FFA_RXTX_MAP:
        case FFA_MEM_DONATE:
        case FFA_MEM_RETRIEVE_REQ:
-       /* Don't advertise any features just yet */
-       case FFA_FEATURES:
                return false;
        }
 
        return true;
 }
 
+static bool do_ffa_features(struct arm_smccc_res *res,
+                           struct kvm_cpu_context *ctxt)
+{
+       DECLARE_REG(u32, id, ctxt, 1);
+       u64 prop = 0;
+       int ret = 0;
+
+       if (!ffa_call_supported(id)) {
+               ret = FFA_RET_NOT_SUPPORTED;
+               goto out_handled;
+       }
+
+       switch (id) {
+       case FFA_MEM_SHARE:
+       case FFA_FN64_MEM_SHARE:
+       case FFA_MEM_LEND:
+       case FFA_FN64_MEM_LEND:
+               ret = FFA_RET_SUCCESS;
+               prop = 0; /* No support for dynamic buffers */
+               goto out_handled;
+       default:
+               return false;
+       }
+
+out_handled:
+       ffa_to_smccc_res_prop(res, ret, prop);
+       return true;
+}
+
 bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt)
 {
        DECLARE_REG(u64, func_id, host_ctxt, 0);
@@ -514,6 +547,10 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt)
                return false;
 
        switch (func_id) {
+       case FFA_FEATURES:
+               if (!do_ffa_features(&res, host_ctxt))
+                       return false;
+               goto out_handled;
        /* Memory management */
        case FFA_FN64_RXTX_MAP:
                do_ffa_rxtx_map(&res, host_ctxt);