[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250226214853.3267057-3-sebastianene@google.com>
Date: Wed, 26 Feb 2025 21:48:52 +0000
From: Sebastian Ene <sebastianene@...gle.com>
To: catalin.marinas@....com, joey.gouly@....com, maz@...nel.org,
oliver.upton@...ux.dev, sebastianene@...gle.com, snehalreddy@...gle.com,
sudeep.holla@....com, suzuki.poulose@....com, vdonnefort@...gle.com,
will@...nel.org, yuzenghui@...wei.com
Cc: kvmarm@...ts.linux.dev, linux-arm-kernel@...ts.infradead.org,
linux-kernel@...r.kernel.org, kernel-team@...roid.com
Subject: [PATCH 2/3] KVM: arm64: Map the hypervisor FF-A buffers on ffa init
Map the hypervisor's buffers irrespective to the host and return
a linux error code from the FF-A error code on failure. Remove
the unmap ff-a buffers calls from the hypervisor as it will
never be called and move the definition of the
ffa_to_linux_error map in the header where it should belong to.
Prevent the host from using FF-A if the hypervisor could not
map its own buffers with Trustzone.
Signed-off-by: Sebastian Ene <sebastianene@...gle.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 46 ++++++++++++-------------------
drivers/firmware/arm_ffa/driver.c | 24 ----------------
include/linux/arm_ffa.h | 24 ++++++++++++++++
3 files changed, 41 insertions(+), 53 deletions(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 6df6131f1107..861f24de97cb 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -69,6 +69,7 @@ static struct kvm_ffa_buffers hyp_buffers;
static struct kvm_ffa_buffers host_buffers;
static u32 hyp_ffa_version;
static bool has_version_negotiated;
+static bool has_ffa_supported;
static DEFINE_HYP_SPINLOCK(version_lock);
static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
@@ -111,30 +112,18 @@ static bool is_ffa_call(u64 func_id)
ARM_SMCCC_FUNC_NUM(func_id) <= FFA_MAX_FUNC_NUM;
}
-static int ffa_map_hyp_buffers(u64 ffa_page_count)
+static int ffa_map_hyp_buffers(void)
{
struct arm_smccc_res res;
arm_smccc_1_1_smc(FFA_FN64_RXTX_MAP,
hyp_virt_to_phys(hyp_buffers.tx),
hyp_virt_to_phys(hyp_buffers.rx),
- ffa_page_count,
+ KVM_FFA_MBOX_NR_PAGES,
0, 0, 0, 0,
&res);
- return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
-}
-
-static int ffa_unmap_hyp_buffers(void)
-{
- struct arm_smccc_res res;
-
- arm_smccc_1_1_smc(FFA_RXTX_UNMAP,
- HOST_FFA_ID,
- 0, 0, 0, 0, 0, 0,
- &res);
-
- return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
+ return res.a0 == FFA_SUCCESS ? 0 : ffa_to_linux_errno(res.a2);
}
static void ffa_mem_frag_tx(struct arm_smccc_res *res, u32 handle_lo,
@@ -213,18 +202,10 @@ static void do_ffa_rxtx_map(struct arm_smccc_res *res,
goto out_unlock;
}
- /*
- * Map our hypervisor buffers into the SPMD before mapping and
- * pinning the host buffers in our own address space.
- */
- ret = ffa_map_hyp_buffers(npages);
- if (ret)
- goto out_unlock;
-
ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(tx));
if (ret) {
ret = FFA_RET_INVALID_PARAMETERS;
- goto err_unmap;
+ goto out_unlock;
}
ret = __pkvm_host_share_hyp(hyp_phys_to_pfn(rx));
@@ -262,8 +243,6 @@ static void do_ffa_rxtx_map(struct arm_smccc_res *res,
__pkvm_host_unshare_hyp(hyp_phys_to_pfn(rx));
err_unshare_tx:
__pkvm_host_unshare_hyp(hyp_phys_to_pfn(tx));
-err_unmap:
- ffa_unmap_hyp_buffers();
goto out_unlock;
}
@@ -291,9 +270,6 @@ static void do_ffa_rxtx_unmap(struct arm_smccc_res *res,
hyp_unpin_shared_mem(host_buffers.rx, host_buffers.rx + 1);
WARN_ON(__pkvm_host_unshare_hyp(hyp_virt_to_pfn(host_buffers.rx)));
host_buffers.rx = NULL;
-
- ffa_unmap_hyp_buffers();
-
out_unlock:
hyp_spin_unlock(&host_buffers.lock);
out:
@@ -809,6 +785,11 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
if (!is_ffa_call(func_id))
return false;
+ if (!has_ffa_supported) {
+ ffa_to_smccc_error(&res, FFA_RET_NOT_SUPPORTED);
+ goto out_handled;
+ }
+
if (!has_version_negotiated && func_id != FFA_VERSION) {
ffa_to_smccc_error(&res, FFA_RET_INVALID_PARAMETERS);
goto out_handled;
@@ -861,6 +842,7 @@ int hyp_ffa_init(void *pages)
{
struct arm_smccc_res res;
void *tx, *rx;
+ int ret;
if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
return 0;
@@ -911,5 +893,11 @@ int hyp_ffa_init(void *pages)
.lock = __HYP_SPIN_LOCK_UNLOCKED,
};
+ /* Map our hypervisor buffers into the SPMD */
+ ret = ffa_map_hyp_buffers();
+ if (ret)
+ return ret;
+
+ has_ffa_supported = true;
return 0;
}
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index 2c2ec3c35f15..b02b80f3dfe8 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -61,30 +61,6 @@
static ffa_fn *invoke_ffa_fn;
-static const int ffa_linux_errmap[] = {
- /* better than switch case as long as return value is continuous */
- 0, /* FFA_RET_SUCCESS */
- -EOPNOTSUPP, /* FFA_RET_NOT_SUPPORTED */
- -EINVAL, /* FFA_RET_INVALID_PARAMETERS */
- -ENOMEM, /* FFA_RET_NO_MEMORY */
- -EBUSY, /* FFA_RET_BUSY */
- -EINTR, /* FFA_RET_INTERRUPTED */
- -EACCES, /* FFA_RET_DENIED */
- -EAGAIN, /* FFA_RET_RETRY */
- -ECANCELED, /* FFA_RET_ABORTED */
- -ENODATA, /* FFA_RET_NO_DATA */
- -EAGAIN, /* FFA_RET_NOT_READY */
-};
-
-static inline int ffa_to_linux_errno(int errno)
-{
- int err_idx = -errno;
-
- if (err_idx >= 0 && err_idx < ARRAY_SIZE(ffa_linux_errmap))
- return ffa_linux_errmap[err_idx];
- return -EINVAL;
-}
-
struct ffa_pcpu_irq {
struct ffa_drv_info *info;
};
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 74169dd0f659..850577edadbc 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -475,4 +475,28 @@ struct ffa_ops {
const struct ffa_notifier_ops *notifier_ops;
};
+static const int ffa_linux_errmap[] = {
+ /* better than switch case as long as return value is continuous */
+ 0, /* FFA_RET_SUCCESS */
+ -EOPNOTSUPP, /* FFA_RET_NOT_SUPPORTED */
+ -EINVAL, /* FFA_RET_INVALID_PARAMETERS */
+ -ENOMEM, /* FFA_RET_NO_MEMORY */
+ -EBUSY, /* FFA_RET_BUSY */
+ -EINTR, /* FFA_RET_INTERRUPTED */
+ -EACCES, /* FFA_RET_DENIED */
+ -EAGAIN, /* FFA_RET_RETRY */
+ -ECANCELED, /* FFA_RET_ABORTED */
+ -ENODATA, /* FFA_RET_NO_DATA */
+ -EAGAIN, /* FFA_RET_NOT_READY */
+};
+
+static inline int ffa_to_linux_errno(int errno)
+{
+ int err_idx = -errno;
+
+ if (err_idx >= 0 && err_idx < ARRAY_SIZE(ffa_linux_errmap))
+ return ffa_linux_errmap[err_idx];
+ return -EINVAL;
+}
+
#endif /* _LINUX_ARM_FFA_H */
--
2.48.1.658.g4767266eb4-goog
Powered by blists - more mailing lists