* [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI
@ 2025-06-19 9:02 Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 1/6] KVM: arm64: Correct return value on host version downgrade attempt Per Larsen via B4 Relay
` (5 more replies)
0 siblings, 6 replies; 8+ messages in thread
From: Per Larsen via B4 Relay @ 2025-06-19 9:02 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sudeep Holla
Cc: linux-arm-kernel, kvmarm, linux-kernel, Per Larsen, Ayrton Munoz
Hi,
The FF-A 1.2 specification introduces a new SEND_DIRECT2 ABI which
allows registers x4-x17 to be used for the message payload. This patch
set prevents the host from using a lower FF-A version than what has
already been negotiated with the hypervisor. This is necessary because
the hypervisor does not have the necessary compatibility paths to
translate from the hypervisor FF-A version to a previous version.
Support for FF-A 1.2 in the hypervisor is added as a precursor to the
addition of the FFA_MSG_SEND_DIRECT_REQ2 messaging interface. The bulk
of this change has to do with the upgrade to SMCCC 1.2 required by
FF-A 1.2. Additionally, unimplemented FF-A 1.2 interfaces are added to
the list of unsupported functions.
Tested by booting Android under QEMU and loading Trusty as the guest
VM and observing the SEND_DIRECT2 ABI being used successfully during
guest boot.
Changes since v4:
- 1/5 -> 1/6: Added Acked-by: Will Deacon <will@kernel.org>
Reworded patch subject and description
- 2/5: Dropped patch: zero x4-x7 in ffa_set_retval
- 2/6: New: use SMCCC 1.2 during hyp init
- 3/6: New: use SMCCC 1.2 in host FF-A handler
- 3/5 -> 4/6: No change; can revisit denylist design in later patchset
Added Acked-by: Will Deacon <will@kernel.org>
- 4/5 -> 5/6: No change
- 5/5 -> 6/6: No change
- Link to v4: https://lore.kernel.org/r/20250516-virtio-msg-ffa-v4-0-580ee70e5081@google.com
Changes since v3:
- all: Remove Signed-off-by: Per Larsen <perl@immunant.com>
- 2/5: Split out from 2/3, zero x4-x7 in set_ffa_retval
- 3/5: Split out from 2/3, Mark FFA_NOTIFICATION_* calls as
unsupported
- 2/3 -> 4/5: Drop ffa_get_hypervisor_version, access hyp_ffa_version
directly when version negotiation is complete.
- 3/3 -> 5/5: Call ffa_to_smccc_1_2_error directly in
do_do_ffa_direct_msg2
Push call to ffa_call_needs_smccc_1_2 lower down by adding
ffa_get_func_id and ffa_set_retval_smccc_1_x.
Drop ffa_to_smccc_1_2_regs and ffa_to_smccc_1_2_regs_prop
as they are no longer used.
- Link to v3: https://lore.kernel.org/r/20250513-virtio-msg-ffa-v3-0-d66c76ff1b2c@google.com
Changes since v2:
- 2/3: Removed files added by mistake.
Add and use ffa_get_hypervisor_version to access hyp_ffa_version
- 3/3: Use ffa_get_hypervisor_version to access hyp_ffa_version safely
- Link to v2: https://lore.kernel.org/r/20250508-virtio-msg-ffa-v2-0-ed84f8053965@google.com
Changes since v1:
- 1/3: Simplify commit message; drop long comment in do_ffa_version
- 2/3: Correct use of Co-developed-by: footer
s/arm_smccc_1_2_smc_fallback/arm_smccc_1_x_smc/
Always access hyp_ffa_version w/lock held
Remove superfluous comments in ffa_call_supported
Add and use FFA_FEAT_RXTX_MIN_SZ_MASK instead of constant
Add FFA_PARTITION_INFO_GET_REGS to calls that require SMCCC 1.2
- 3/3: Always access hyp_ffa_version w/lock held
Correct formatting
Thanks,
Per Larsen
--
2.49.0
---
To: Marc Zyngier <maz@kernel.org>
To: Oliver Upton <oliver.upton@linux.dev>
To: Joey Gouly <joey.gouly@arm.com>
To: Suzuki K Poulose <suzuki.poulose@arm.com>
To: Zenghui Yu <yuzenghui@huawei.com>
To: Catalin Marinas <catalin.marinas@arm.com>
To: Will Deacon <will@kernel.org>
To: Sudeep Holla <sudeep.holla@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: kvmarm@lists.linux.dev
Cc: linux-kernel@vger.kernel.org
---
---
Per Larsen (6):
KVM: arm64: Correct return value on host version downgrade attempt
KVM: arm64: Use SMCCC 1.2 in hyp_ffa_{init,post_init}
KVM: arm64: Use SMCCC 1.2 in host FF-A handler
KVM: arm64: Mark FFA_NOTIFICATION_* calls as unsupported
KVM: arm64: Bump the supported version of FF-A to 1.2
KVM: arm64: Support FFA_MSG_SEND_DIRECT_REQ2 in host handler
arch/arm64/kvm/hyp/nvhe/Makefile | 1 +
arch/arm64/kvm/hyp/nvhe/ffa.c | 373 ++++++++++++++++++++++++---------------
include/linux/arm_ffa.h | 3 +
3 files changed, 239 insertions(+), 138 deletions(-)
---
base-commit: fb4d33ab452ea254e2c319bac5703d1b56d895bf
change-id: 20250506-virtio-msg-ffa-22af72c92150
Best regards,
--
Per Larsen <perlarsen@google.com>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 1/6] KVM: arm64: Correct return value on host version downgrade attempt
2025-06-19 9:02 [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI Per Larsen via B4 Relay
@ 2025-06-19 9:02 ` Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 2/6] KVM: arm64: Use SMCCC 1.2 in hyp_ffa_{init,post_init} Per Larsen via B4 Relay
` (4 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Per Larsen via B4 Relay @ 2025-06-19 9:02 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sudeep Holla
Cc: linux-arm-kernel, kvmarm, linux-kernel, Per Larsen
From: Per Larsen <perlarsen@google.com>
Once the hypervisor negotiates the FF-A version with the host, it should
remain locked-in. However, it is possible to load FF-A as a module first
supporting version 1.1 and then 1.0.
Without this patch, the FF-A 1.0 driver will use 1.0 data structures to
make calls which the hypervisor will incorrectly interpret as 1.1 data
structures. With this patch, negotiation will fail.
This patch does not change existing functionality in the case where a
FF-A 1.2 driver is loaded after a 1.1 driver; the 1.2 driver will need
to use 1.1 in order to proceed.
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Per Larsen <perlarsen@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 3369dd0c4009f84ad3cf9481c747bdc57a162370..2c199d40811efb5bfae199c4a67d8ae3d9307357 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -712,7 +712,10 @@ static void do_ffa_version(struct arm_smccc_res *res,
hyp_spin_lock(&version_lock);
if (has_version_negotiated) {
- res->a0 = hyp_ffa_version;
+ if (FFA_MINOR_VERSION(ffa_req_version) < FFA_MINOR_VERSION(hyp_ffa_version))
+ res->a0 = FFA_RET_NOT_SUPPORTED;
+ else
+ res->a0 = hyp_ffa_version;
goto unlock;
}
--
2.50.0.rc2.701.gf1e915cc24-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 2/6] KVM: arm64: Use SMCCC 1.2 in hyp_ffa_{init,post_init}
2025-06-19 9:02 [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 1/6] KVM: arm64: Correct return value on host version downgrade attempt Per Larsen via B4 Relay
@ 2025-06-19 9:02 ` Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 3/6] KVM: arm64: Use SMCCC 1.2 in host FF-A handler Per Larsen via B4 Relay
` (3 subsequent siblings)
5 siblings, 0 replies; 8+ messages in thread
From: Per Larsen via B4 Relay @ 2025-06-19 9:02 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sudeep Holla
Cc: linux-arm-kernel, kvmarm, linux-kernel, Per Larsen
From: Per Larsen <perlarsen@google.com>
FF-A is based on SMCCC 1.2. Move the FF-A initialization code to SMCCC
1.2 as it simplifies later changes in this patchset.
Signed-off-by: Per Larsen <perlarsen@google.com>
---
arch/arm64/kvm/hyp/nvhe/Makefile | 1 +
arch/arm64/kvm/hyp/nvhe/ffa.c | 37 +++++++++++++++++++++++--------------
2 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
index a76522d63c3e630795db5972a99abc3d24bc5e26..f859a8fb41a25effea1edd977bef889423153399 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile
@@ -27,6 +27,7 @@ hyp-obj-y := timer-sr.o sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o host.o
cache.o setup.o mm.o mem_protect.o sys_regs.o pkvm.o stacktrace.o ffa.o
hyp-obj-y += ../vgic-v3-sr.o ../aarch32.o ../vgic-v2-cpuif-proxy.o ../entry.o \
../fpsimd.o ../hyp-entry.o ../exception.o ../pgtable.o
+hyp-obj-y += ../../../kernel/smccc-call.o
hyp-obj-$(CONFIG_LIST_HARDENED) += list_debug.o
hyp-obj-y += $(lib-objs)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 2c199d40811efb5bfae199c4a67d8ae3d9307357..51bbe8f9c94584e9001ee769cbfd608d930ff723 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -666,21 +666,26 @@ static bool do_ffa_features(struct arm_smccc_res *res,
static int hyp_ffa_post_init(void)
{
size_t min_rxtx_sz;
- struct arm_smccc_res res;
+ struct arm_smccc_1_2_regs regs = {
+ .a0 = FFA_ID_GET,
+ };
- arm_smccc_1_1_smc(FFA_ID_GET, 0, 0, 0, 0, 0, 0, 0, &res);
- if (res.a0 != FFA_SUCCESS)
+ arm_smccc_1_2_smc(®s, ®s);
+ if (regs.a0 != FFA_SUCCESS)
return -EOPNOTSUPP;
- if (res.a2 != HOST_FFA_ID)
+ if (regs.a2 != HOST_FFA_ID)
return -EINVAL;
- arm_smccc_1_1_smc(FFA_FEATURES, FFA_FN64_RXTX_MAP,
- 0, 0, 0, 0, 0, 0, &res);
- if (res.a0 != FFA_SUCCESS)
+ regs = (struct arm_smccc_1_2_regs){
+ .a0 = FFA_FEATURES,
+ .a1 = FFA_FN64_RXTX_MAP,
+ };
+ arm_smccc_1_2_smc(®s, ®s);
+ if (regs.a0 != FFA_SUCCESS)
return -EOPNOTSUPP;
- switch (res.a2) {
+ switch (regs.a2) {
case FFA_FEAT_RXTX_MIN_SZ_4K:
min_rxtx_sz = SZ_4K;
break;
@@ -863,14 +868,18 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
int hyp_ffa_init(void *pages)
{
- struct arm_smccc_res res;
+ struct arm_smccc_1_2_regs regs;
void *tx, *rx;
if (kvm_host_psci_config.smccc_version < ARM_SMCCC_VERSION_1_2)
return 0;
- arm_smccc_1_1_smc(FFA_VERSION, FFA_VERSION_1_1, 0, 0, 0, 0, 0, 0, &res);
- if (res.a0 == FFA_RET_NOT_SUPPORTED)
+ regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_VERSION,
+ .a1 = FFA_VERSION_1_1,
+ };
+ arm_smccc_1_2_smc(®s, ®s);
+ if (regs.a0 == FFA_RET_NOT_SUPPORTED)
return 0;
/*
@@ -886,11 +895,11 @@ int hyp_ffa_init(void *pages)
* ABI return NOT_SUPPORTED rather than a version number, according to
* DEN0077A v1.1 REL0 18.6.4.
*/
- if (FFA_MAJOR_VERSION(res.a0) != 1)
+ if (FFA_MAJOR_VERSION(regs.a0) != 1)
return -EOPNOTSUPP;
- if (FFA_MINOR_VERSION(res.a0) < FFA_MINOR_VERSION(FFA_VERSION_1_1))
- hyp_ffa_version = res.a0;
+ if (FFA_MINOR_VERSION(regs.a0) < FFA_MINOR_VERSION(FFA_VERSION_1_1))
+ hyp_ffa_version = regs.a0;
else
hyp_ffa_version = FFA_VERSION_1_1;
--
2.50.0.rc2.701.gf1e915cc24-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 3/6] KVM: arm64: Use SMCCC 1.2 in host FF-A handler
2025-06-19 9:02 [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 1/6] KVM: arm64: Correct return value on host version downgrade attempt Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 2/6] KVM: arm64: Use SMCCC 1.2 in hyp_ffa_{init,post_init} Per Larsen via B4 Relay
@ 2025-06-19 9:02 ` Per Larsen via B4 Relay
2025-06-22 13:01 ` Marc Zyngier
2025-06-19 9:02 ` [PATCH v5 4/6] KVM: arm64: Mark FFA_NOTIFICATION_* calls as unsupported Per Larsen via B4 Relay
` (2 subsequent siblings)
5 siblings, 1 reply; 8+ messages in thread
From: Per Larsen via B4 Relay @ 2025-06-19 9:02 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sudeep Holla
Cc: linux-arm-kernel, kvmarm, linux-kernel, Per Larsen
From: Per Larsen <perlarsen@google.com>
SMCCC 1.1 and prior allows four registers to be sent back as a result
of an FF-A interface. SMCCC 1.2 increases the number of results that can
(and often must) be sent back to 8 and 16 for 32-bit and 64-bit SMC/HVCs
respectively.
FF-A 1.0 references SMCCC 1.2 (reference [4] on page xi) and FF-A 1.2
explicitly requires SMCCC 1.2 so it should be safe to use this version
unconditionally. Moreover, it is simpler to implement FF-A features
without having to worry about compatibility with SMCCC 1.1 and older.
Add SMCCC 1.2 helper routines and use this version unconditionally.
Signed-off-by: Per Larsen <perlarsen@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 297 ++++++++++++++++++++++++------------------
1 file changed, 173 insertions(+), 124 deletions(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 51bbe8f9c94584e9001ee769cbfd608d930ff723..23b75b9f0bcc62724f0d0d185ac2ed2526375da4 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -71,36 +71,55 @@ static u32 hyp_ffa_version;
static bool has_version_negotiated;
static hyp_spinlock_t version_lock;
-static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
+static void ffa_to_smccc_1_2_error(struct arm_smccc_1_2_regs *regs, u64 ffa_errno)
{
- *res = (struct arm_smccc_res) {
+ *regs = (struct arm_smccc_1_2_regs) {
.a0 = FFA_ERROR,
.a2 = ffa_errno,
};
}
-static void ffa_to_smccc_res_prop(struct arm_smccc_res *res, int ret, u64 prop)
+static void ffa_to_smccc_regs_prop(struct arm_smccc_1_2_regs *regs, int ret,
+ u64 prop)
{
if (ret == FFA_RET_SUCCESS) {
- *res = (struct arm_smccc_res) { .a0 = FFA_SUCCESS,
- .a2 = prop };
+ *regs = (struct arm_smccc_1_2_regs) { .a0 = FFA_SUCCESS,
+ .a2 = prop };
} else {
- ffa_to_smccc_error(res, ret);
+ ffa_to_smccc_1_2_error(regs, ret);
}
}
-static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret)
+static void ffa_to_smccc_regs(struct arm_smccc_1_2_regs *regs, int ret)
{
- ffa_to_smccc_res_prop(res, ret, 0);
+ ffa_to_smccc_regs_prop(regs, ret, 0);
}
static void ffa_set_retval(struct kvm_cpu_context *ctxt,
- struct arm_smccc_res *res)
+ struct arm_smccc_1_2_regs *regs)
{
- cpu_reg(ctxt, 0) = res->a0;
- cpu_reg(ctxt, 1) = res->a1;
- cpu_reg(ctxt, 2) = res->a2;
- cpu_reg(ctxt, 3) = res->a3;
+ cpu_reg(ctxt, 0) = regs->a0;
+ cpu_reg(ctxt, 1) = regs->a1;
+ cpu_reg(ctxt, 2) = regs->a2;
+ cpu_reg(ctxt, 3) = regs->a3;
+ cpu_reg(ctxt, 4) = regs->a4;
+ cpu_reg(ctxt, 5) = regs->a5;
+ cpu_reg(ctxt, 6) = regs->a6;
+ cpu_reg(ctxt, 7) = regs->a7;
+
+ /* DEN0028C 2.6: SMC32/HVC32 call from aarch64 must preserve x8-x30 */
+ if (ARM_SMCCC_IS_64(regs->a0)) {
+ cpu_reg(ctxt, 8) = regs->a8;
+ cpu_reg(ctxt, 9) = regs->a9;
+ cpu_reg(ctxt, 10) = regs->a10;
+ cpu_reg(ctxt, 11) = regs->a11;
+ cpu_reg(ctxt, 12) = regs->a12;
+ cpu_reg(ctxt, 13) = regs->a13;
+ cpu_reg(ctxt, 14) = regs->a14;
+ cpu_reg(ctxt, 15) = regs->a15;
+ cpu_reg(ctxt, 16) = regs->a16;
+ cpu_reg(ctxt, 17) = regs->a17;
+ }
}
static bool is_ffa_call(u64 func_id)
@@ -113,82 +132,104 @@ static bool is_ffa_call(u64 func_id)
static int ffa_map_hyp_buffers(u64 ffa_page_count)
{
- struct arm_smccc_res res;
+ struct arm_smccc_1_2_regs regs;
- 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,
- 0, 0, 0, 0,
- &res);
+ regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_FN64_RXTX_MAP,
+ .a1 = hyp_virt_to_phys(hyp_buffers.tx),
+ .a2 = hyp_virt_to_phys(hyp_buffers.rx),
+ .a3 = ffa_page_count,
+ };
+ arm_smccc_1_2_smc(®s, ®s);
+ if (regs.a0 != FFA_SUCCESS)
+ return regs.a2;
- return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
+ return regs.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : regs.a2;
}
static int ffa_unmap_hyp_buffers(void)
{
- struct arm_smccc_res res;
+ struct arm_smccc_1_2_regs regs;
- arm_smccc_1_1_smc(FFA_RXTX_UNMAP,
- HOST_FFA_ID,
- 0, 0, 0, 0, 0, 0,
- &res);
+ regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_RXTX_UNMAP,
+ .a1 = HOST_FFA_ID,
+ };
+ arm_smccc_1_2_smc(®s, ®s);
+ if (regs.a0 != FFA_SUCCESS)
+ return regs.a2;
- return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
+ return regs.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : regs.a2;
}
-static void ffa_mem_frag_tx(struct arm_smccc_res *res, u32 handle_lo,
+static void ffa_mem_frag_tx(struct arm_smccc_1_2_regs *regs, u32 handle_lo,
u32 handle_hi, u32 fraglen, u32 endpoint_id)
{
- arm_smccc_1_1_smc(FFA_MEM_FRAG_TX,
- handle_lo, handle_hi, fraglen, endpoint_id,
- 0, 0, 0,
- res);
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_MEM_FRAG_TX,
+ .a1 = handle_lo,
+ .a2 = handle_hi,
+ .a3 = fraglen,
+ .a4 = endpoint_id,
+ };
+ arm_smccc_1_2_smc(regs, regs);
}
-static void ffa_mem_frag_rx(struct arm_smccc_res *res, u32 handle_lo,
+static void ffa_mem_frag_rx(struct arm_smccc_1_2_regs *regs, u32 handle_lo,
u32 handle_hi, u32 fragoff)
{
- arm_smccc_1_1_smc(FFA_MEM_FRAG_RX,
- handle_lo, handle_hi, fragoff, HOST_FFA_ID,
- 0, 0, 0,
- res);
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_MEM_FRAG_RX,
+ .a1 = handle_lo,
+ .a2 = handle_hi,
+ .a3 = fragoff,
+ .a4 = HOST_FFA_ID,
+ };
+ arm_smccc_1_2_smc(regs, regs);
}
-static void ffa_mem_xfer(struct arm_smccc_res *res, u64 func_id, u32 len,
+static void ffa_mem_xfer(struct arm_smccc_1_2_regs *regs, u64 func_id, u32 len,
u32 fraglen)
{
- arm_smccc_1_1_smc(func_id, len, fraglen,
- 0, 0, 0, 0, 0,
- res);
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = func_id,
+ .a1 = len,
+ .a2 = fraglen,
+ };
+ arm_smccc_1_2_smc(regs, regs);
}
-static void ffa_mem_reclaim(struct arm_smccc_res *res, u32 handle_lo,
+static void ffa_mem_reclaim(struct arm_smccc_1_2_regs *regs, u32 handle_lo,
u32 handle_hi, u32 flags)
{
- arm_smccc_1_1_smc(FFA_MEM_RECLAIM,
- handle_lo, handle_hi, flags,
- 0, 0, 0, 0,
- res);
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_MEM_RECLAIM,
+ .a1 = handle_lo,
+ .a2 = handle_hi,
+ .a3 = flags,
+ };
+ arm_smccc_1_2_smc(regs, regs);
}
-static void ffa_retrieve_req(struct arm_smccc_res *res, u32 len)
+static void ffa_retrieve_req(struct arm_smccc_1_2_regs *regs, u32 len)
{
- arm_smccc_1_1_smc(FFA_FN64_MEM_RETRIEVE_REQ,
- len, len,
- 0, 0, 0, 0, 0,
- res);
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_FN64_MEM_RETRIEVE_REQ,
+ .a1 = len,
+ .a2 = len,
+ };
+ arm_smccc_1_2_smc(regs, regs);
}
-static void ffa_rx_release(struct arm_smccc_res *res)
+static void ffa_rx_release(struct arm_smccc_1_2_regs *regs)
{
- arm_smccc_1_1_smc(FFA_RX_RELEASE,
- 0, 0,
- 0, 0, 0, 0, 0,
- res);
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_RX_RELEASE,
+ };
+ arm_smccc_1_2_smc(regs, regs);
}
-static void do_ffa_rxtx_map(struct arm_smccc_res *res,
+static void do_ffa_rxtx_map(struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(phys_addr_t, tx, ctxt, 1);
@@ -253,7 +294,7 @@ static void do_ffa_rxtx_map(struct arm_smccc_res *res,
out_unlock:
hyp_spin_unlock(&host_buffers.lock);
out:
- ffa_to_smccc_res(res, ret);
+ ffa_to_smccc_regs(regs, ret);
return;
err_unpin_tx:
@@ -267,7 +308,7 @@ static void do_ffa_rxtx_map(struct arm_smccc_res *res,
goto out_unlock;
}
-static void do_ffa_rxtx_unmap(struct arm_smccc_res *res,
+static void do_ffa_rxtx_unmap(struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, id, ctxt, 1);
@@ -297,7 +338,7 @@ static void do_ffa_rxtx_unmap(struct arm_smccc_res *res,
out_unlock:
hyp_spin_unlock(&host_buffers.lock);
out:
- ffa_to_smccc_res(res, ret);
+ ffa_to_smccc_regs(regs, ret);
}
static u32 __ffa_host_share_ranges(struct ffa_mem_region_addr_range *ranges,
@@ -368,7 +409,7 @@ static int ffa_host_unshare_ranges(struct ffa_mem_region_addr_range *ranges,
return ret;
}
-static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
+static void do_ffa_mem_frag_tx(struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, handle_lo, ctxt, 1);
@@ -400,20 +441,20 @@ static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
* to restore the global state back to what it was prior to
* transmission of the first fragment.
*/
- ffa_mem_reclaim(res, handle_lo, handle_hi, 0);
- WARN_ON(res->a0 != FFA_SUCCESS);
+ ffa_mem_reclaim(regs, handle_lo, handle_hi, 0);
+ WARN_ON(regs->a0 != FFA_SUCCESS);
goto out_unlock;
}
- ffa_mem_frag_tx(res, handle_lo, handle_hi, fraglen, endpoint_id);
- if (res->a0 != FFA_SUCCESS && res->a0 != FFA_MEM_FRAG_RX)
+ ffa_mem_frag_tx(regs, handle_lo, handle_hi, fraglen, endpoint_id);
+ if (regs->a0 != FFA_SUCCESS && regs->a0 != FFA_MEM_FRAG_RX)
WARN_ON(ffa_host_unshare_ranges(buf, nr_ranges));
out_unlock:
hyp_spin_unlock(&host_buffers.lock);
out:
if (ret)
- ffa_to_smccc_res(res, ret);
+ ffa_to_smccc_regs(regs, ret);
/*
* If for any reason this did not succeed, we're in trouble as we have
@@ -427,7 +468,7 @@ static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
}
static void __do_ffa_mem_xfer(const u64 func_id,
- struct arm_smccc_res *res,
+ struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, len, ctxt, 1);
@@ -491,14 +532,14 @@ static void __do_ffa_mem_xfer(const u64 func_id,
if (ret)
goto out_unlock;
- ffa_mem_xfer(res, func_id, len, fraglen);
+ ffa_mem_xfer(regs, func_id, len, fraglen);
if (fraglen != len) {
- if (res->a0 != FFA_MEM_FRAG_RX)
+ if (regs->a0 != FFA_MEM_FRAG_RX)
goto err_unshare;
- if (res->a3 != fraglen)
+ if (regs->a3 != fraglen)
goto err_unshare;
- } else if (res->a0 != FFA_SUCCESS) {
+ } else if (regs->a0 != FFA_SUCCESS) {
goto err_unshare;
}
@@ -506,7 +547,7 @@ static void __do_ffa_mem_xfer(const u64 func_id,
hyp_spin_unlock(&host_buffers.lock);
out:
if (ret)
- ffa_to_smccc_res(res, ret);
+ ffa_to_smccc_regs(regs, ret);
return;
err_unshare:
@@ -514,14 +555,14 @@ static void __do_ffa_mem_xfer(const u64 func_id,
goto out_unlock;
}
-#define do_ffa_mem_xfer(fid, res, ctxt) \
+#define do_ffa_mem_xfer(fid, regs, ctxt) \
do { \
BUILD_BUG_ON((fid) != FFA_FN64_MEM_SHARE && \
(fid) != FFA_FN64_MEM_LEND); \
- __do_ffa_mem_xfer((fid), (res), (ctxt)); \
- } while (0);
+ __do_ffa_mem_xfer((fid), (regs), (ctxt)); \
+ } while (0)
-static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
+static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, handle_lo, ctxt, 1);
@@ -544,13 +585,13 @@ static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
.handle = handle,
};
- ffa_retrieve_req(res, sizeof(*buf));
+ ffa_retrieve_req(regs, sizeof(*buf));
buf = hyp_buffers.rx;
- if (res->a0 != FFA_MEM_RETRIEVE_RESP)
+ if (regs->a0 != FFA_MEM_RETRIEVE_RESP)
goto out_unlock;
- len = res->a1;
- fraglen = res->a2;
+ len = regs->a1;
+ fraglen = regs->a2;
ep_mem_access = (void *)buf +
ffa_mem_desc_offset(buf, 0, hyp_ffa_version);
@@ -563,34 +604,34 @@ static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
if (WARN_ON(offset > len ||
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)) {
ret = FFA_RET_ABORTED;
- ffa_rx_release(res);
+ ffa_rx_release(regs);
goto out_unlock;
}
if (len > ffa_desc_buf.len) {
ret = FFA_RET_NO_MEMORY;
- ffa_rx_release(res);
+ ffa_rx_release(regs);
goto out_unlock;
}
buf = ffa_desc_buf.buf;
memcpy(buf, hyp_buffers.rx, fraglen);
- ffa_rx_release(res);
+ ffa_rx_release(regs);
for (fragoff = fraglen; fragoff < len; fragoff += fraglen) {
- ffa_mem_frag_rx(res, handle_lo, handle_hi, fragoff);
- if (res->a0 != FFA_MEM_FRAG_TX) {
+ ffa_mem_frag_rx(regs, handle_lo, handle_hi, fragoff);
+ if (regs->a0 != FFA_MEM_FRAG_TX) {
ret = FFA_RET_INVALID_PARAMETERS;
goto out_unlock;
}
- fraglen = res->a3;
+ fraglen = regs->a3;
memcpy((void *)buf + fragoff, hyp_buffers.rx, fraglen);
- ffa_rx_release(res);
+ ffa_rx_release(regs);
}
- ffa_mem_reclaim(res, handle_lo, handle_hi, flags);
- if (res->a0 != FFA_SUCCESS)
+ ffa_mem_reclaim(regs, handle_lo, handle_hi, flags);
+ if (regs->a0 != FFA_SUCCESS)
goto out_unlock;
reg = (void *)buf + offset;
@@ -601,7 +642,7 @@ static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
hyp_spin_unlock(&host_buffers.lock);
if (ret)
- ffa_to_smccc_res(res, ret);
+ ffa_to_smccc_regs(regs, ret);
}
/*
@@ -634,7 +675,7 @@ static bool ffa_call_supported(u64 func_id)
return true;
}
-static bool do_ffa_features(struct arm_smccc_res *res,
+static bool do_ffa_features(struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, id, ctxt, 1);
@@ -659,7 +700,7 @@ static bool do_ffa_features(struct arm_smccc_res *res,
}
out_handled:
- ffa_to_smccc_res_prop(res, ret, prop);
+ ffa_to_smccc_regs_prop(regs, ret, prop);
return true;
}
@@ -705,22 +746,22 @@ static int hyp_ffa_post_init(void)
return 0;
}
-static void do_ffa_version(struct arm_smccc_res *res,
+static void do_ffa_version(struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, ffa_req_version, ctxt, 1);
if (FFA_MAJOR_VERSION(ffa_req_version) != 1) {
- res->a0 = FFA_RET_NOT_SUPPORTED;
+ regs->a0 = FFA_RET_NOT_SUPPORTED;
return;
}
hyp_spin_lock(&version_lock);
if (has_version_negotiated) {
if (FFA_MINOR_VERSION(ffa_req_version) < FFA_MINOR_VERSION(hyp_ffa_version))
- res->a0 = FFA_RET_NOT_SUPPORTED;
+ regs->a0 = FFA_RET_NOT_SUPPORTED;
else
- res->a0 = hyp_ffa_version;
+ regs->a0 = hyp_ffa_version;
goto unlock;
}
@@ -729,26 +770,28 @@ static void do_ffa_version(struct arm_smccc_res *res,
* first if TEE supports it.
*/
if (FFA_MINOR_VERSION(ffa_req_version) < FFA_MINOR_VERSION(hyp_ffa_version)) {
- arm_smccc_1_1_smc(FFA_VERSION, ffa_req_version, 0,
- 0, 0, 0, 0, 0,
- res);
- if (res->a0 == FFA_RET_NOT_SUPPORTED)
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_VERSION,
+ .a1 = ffa_req_version,
+ };
+ arm_smccc_1_2_smc(regs, regs);
+ if (regs->a0 == FFA_RET_NOT_SUPPORTED)
goto unlock;
hyp_ffa_version = ffa_req_version;
}
if (hyp_ffa_post_init()) {
- res->a0 = FFA_RET_NOT_SUPPORTED;
+ regs->a0 = FFA_RET_NOT_SUPPORTED;
} else {
smp_store_release(&has_version_negotiated, true);
- res->a0 = hyp_ffa_version;
+ regs->a0 = hyp_ffa_version;
}
unlock:
hyp_spin_unlock(&version_lock);
}
-static void do_ffa_part_get(struct arm_smccc_res *res,
+static void do_ffa_part_get(struct arm_smccc_1_2_regs *regs,
struct kvm_cpu_context *ctxt)
{
DECLARE_REG(u32, uuid0, ctxt, 1);
@@ -760,18 +803,24 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
hyp_spin_lock(&host_buffers.lock);
if (!host_buffers.rx) {
- ffa_to_smccc_res(res, FFA_RET_BUSY);
+ ffa_to_smccc_regs(regs, FFA_RET_BUSY);
goto out_unlock;
}
- arm_smccc_1_1_smc(FFA_PARTITION_INFO_GET, uuid0, uuid1,
- uuid2, uuid3, flags, 0, 0,
- res);
+ *regs = (struct arm_smccc_1_2_regs) {
+ .a0 = FFA_PARTITION_INFO_GET,
+ .a1 = uuid0,
+ .a2 = uuid1,
+ .a3 = uuid2,
+ .a4 = uuid3,
+ .a5 = flags,
+ };
+ arm_smccc_1_2_smc(regs, regs);
- if (res->a0 != FFA_SUCCESS)
+ if (regs->a0 != FFA_SUCCESS)
goto out_unlock;
- count = res->a2;
+ count = regs->a2;
if (!count)
goto out_unlock;
@@ -780,7 +829,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
if (flags & 0x1)
goto out_unlock;
- partition_sz = res->a3;
+ partition_sz = regs->a3;
} else {
/* FFA_VERSION_1_0 lacks the size in the response */
partition_sz = FFA_1_0_PARTITON_INFO_SZ;
@@ -788,7 +837,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
copy_sz = partition_sz * count;
if (copy_sz > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
- ffa_to_smccc_res(res, FFA_RET_ABORTED);
+ ffa_to_smccc_regs(regs, FFA_RET_ABORTED);
goto out_unlock;
}
@@ -799,7 +848,7 @@ static void do_ffa_part_get(struct arm_smccc_res *res,
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
- struct arm_smccc_res res;
+ struct arm_smccc_1_2_regs regs;
/*
* There's no way we can tell what a non-standard SMC call might
@@ -819,50 +868,50 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
if (func_id != FFA_VERSION &&
!smp_load_acquire(&has_version_negotiated)) {
- ffa_to_smccc_error(&res, FFA_RET_INVALID_PARAMETERS);
+ ffa_to_smccc_1_2_error(®s, FFA_RET_INVALID_PARAMETERS);
goto out_handled;
}
switch (func_id) {
case FFA_FEATURES:
- if (!do_ffa_features(&res, host_ctxt))
+ if (!do_ffa_features(®s, host_ctxt))
return false;
goto out_handled;
/* Memory management */
case FFA_FN64_RXTX_MAP:
- do_ffa_rxtx_map(&res, host_ctxt);
+ do_ffa_rxtx_map(®s, host_ctxt);
goto out_handled;
case FFA_RXTX_UNMAP:
- do_ffa_rxtx_unmap(&res, host_ctxt);
+ do_ffa_rxtx_unmap(®s, host_ctxt);
goto out_handled;
case FFA_MEM_SHARE:
case FFA_FN64_MEM_SHARE:
- do_ffa_mem_xfer(FFA_FN64_MEM_SHARE, &res, host_ctxt);
+ do_ffa_mem_xfer(FFA_FN64_MEM_SHARE, ®s, host_ctxt);
goto out_handled;
case FFA_MEM_RECLAIM:
- do_ffa_mem_reclaim(&res, host_ctxt);
+ do_ffa_mem_reclaim(®s, host_ctxt);
goto out_handled;
case FFA_MEM_LEND:
case FFA_FN64_MEM_LEND:
- do_ffa_mem_xfer(FFA_FN64_MEM_LEND, &res, host_ctxt);
+ do_ffa_mem_xfer(FFA_FN64_MEM_LEND, ®s, host_ctxt);
goto out_handled;
case FFA_MEM_FRAG_TX:
- do_ffa_mem_frag_tx(&res, host_ctxt);
+ do_ffa_mem_frag_tx(®s, host_ctxt);
goto out_handled;
case FFA_VERSION:
- do_ffa_version(&res, host_ctxt);
+ do_ffa_version(®s, host_ctxt);
goto out_handled;
case FFA_PARTITION_INFO_GET:
- do_ffa_part_get(&res, host_ctxt);
+ do_ffa_part_get(®s, host_ctxt);
goto out_handled;
}
if (ffa_call_supported(func_id))
return false; /* Pass through */
- ffa_to_smccc_error(&res, FFA_RET_NOT_SUPPORTED);
+ ffa_to_smccc_1_2_error(®s, FFA_RET_NOT_SUPPORTED);
out_handled:
- ffa_set_retval(host_ctxt, &res);
+ ffa_set_retval(host_ctxt, ®s);
return true;
}
--
2.50.0.rc2.701.gf1e915cc24-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 4/6] KVM: arm64: Mark FFA_NOTIFICATION_* calls as unsupported
2025-06-19 9:02 [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI Per Larsen via B4 Relay
` (2 preceding siblings ...)
2025-06-19 9:02 ` [PATCH v5 3/6] KVM: arm64: Use SMCCC 1.2 in host FF-A handler Per Larsen via B4 Relay
@ 2025-06-19 9:02 ` Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 5/6] KVM: arm64: Bump the supported version of FF-A to 1.2 Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 6/6] KVM: arm64: Support FFA_MSG_SEND_DIRECT_REQ2 in host handler Per Larsen via B4 Relay
5 siblings, 0 replies; 8+ messages in thread
From: Per Larsen via B4 Relay @ 2025-06-19 9:02 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sudeep Holla
Cc: linux-arm-kernel, kvmarm, linux-kernel, Per Larsen
From: Per Larsen <perlarsen@google.com>
Prevent FFA_NOTIFICATION_* interfaces from being passed through to TZ.
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Per Larsen <perlarsen@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 23b75b9f0bcc62724f0d0d185ac2ed2526375da4..6965aa947fb4529c35872ee3976ab8d0b02becca 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -669,6 +669,14 @@ static bool ffa_call_supported(u64 func_id)
case FFA_RXTX_MAP:
case FFA_MEM_DONATE:
case FFA_MEM_RETRIEVE_REQ:
+ /* Optional notification interfaces added in FF-A 1.1 */
+ case FFA_NOTIFICATION_BITMAP_CREATE:
+ case FFA_NOTIFICATION_BITMAP_DESTROY:
+ case FFA_NOTIFICATION_BIND:
+ case FFA_NOTIFICATION_UNBIND:
+ case FFA_NOTIFICATION_SET:
+ case FFA_NOTIFICATION_GET:
+ case FFA_NOTIFICATION_INFO_GET:
return false;
}
--
2.50.0.rc2.701.gf1e915cc24-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 5/6] KVM: arm64: Bump the supported version of FF-A to 1.2
2025-06-19 9:02 [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI Per Larsen via B4 Relay
` (3 preceding siblings ...)
2025-06-19 9:02 ` [PATCH v5 4/6] KVM: arm64: Mark FFA_NOTIFICATION_* calls as unsupported Per Larsen via B4 Relay
@ 2025-06-19 9:02 ` Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 6/6] KVM: arm64: Support FFA_MSG_SEND_DIRECT_REQ2 in host handler Per Larsen via B4 Relay
5 siblings, 0 replies; 8+ messages in thread
From: Per Larsen via B4 Relay @ 2025-06-19 9:02 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sudeep Holla
Cc: linux-arm-kernel, kvmarm, linux-kernel, Ayrton Munoz, Per Larsen
From: Per Larsen <perlarsen@google.com>
FF-A version 1.2 introduces the DIRECT_REQ2 ABI. Bump the FF-A version
preferred by the hypervisor as a precursor to implementing the 1.2-only
FFA_MSG_SEND_DIRECT_REQ2 and FFA_MSG_SEND_RESP2 messaging interfaces.
We must also use SMCCC 1.2 for 64-bit SMCs if hypervisor negotiated FF-A
1.2, so ffa_set_retval is updated and a new function to call 64-bit smcs
using SMCCC 1.2 with fallback to SMCCC 1.1 is introduced.
Update ffa_call_supported to mark FF-A 1.2 interfaces as unsupported
lest they get forwarded.
Co-developed-by: Ayrton Munoz <ayrton@google.com>
Signed-off-by: Ayrton Munoz <ayrton@google.com>
Signed-off-by: Per Larsen <perlarsen@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 14 ++++++++++----
include/linux/arm_ffa.h | 1 +
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 6965aa947fb4529c35872ee3976ab8d0b02becca..7b43279aded7d7ef4cce2c294d208c5a66b684e3 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -677,6 +677,12 @@ static bool ffa_call_supported(u64 func_id)
case FFA_NOTIFICATION_SET:
case FFA_NOTIFICATION_GET:
case FFA_NOTIFICATION_INFO_GET:
+ /* Unimplemented interfaces added in FF-A 1.2 */
+ case FFA_MSG_SEND_DIRECT_REQ2:
+ case FFA_MSG_SEND_DIRECT_RESP2:
+ case FFA_CONSOLE_LOG:
+ case FFA_PARTITION_INFO_GET_REGS:
+ case FFA_EL3_INTR_HANDLE:
return false;
}
@@ -734,7 +740,7 @@ static int hyp_ffa_post_init(void)
if (regs.a0 != FFA_SUCCESS)
return -EOPNOTSUPP;
- switch (regs.a2) {
+ switch (regs.a2 & FFA_FEAT_RXTX_MIN_SZ_MASK) {
case FFA_FEAT_RXTX_MIN_SZ_4K:
min_rxtx_sz = SZ_4K;
break;
@@ -933,7 +939,7 @@ int hyp_ffa_init(void *pages)
regs = (struct arm_smccc_1_2_regs) {
.a0 = FFA_VERSION,
- .a1 = FFA_VERSION_1_1,
+ .a1 = FFA_VERSION_1_2,
};
arm_smccc_1_2_smc(®s, ®s);
if (regs.a0 == FFA_RET_NOT_SUPPORTED)
@@ -955,10 +961,10 @@ int hyp_ffa_init(void *pages)
if (FFA_MAJOR_VERSION(regs.a0) != 1)
return -EOPNOTSUPP;
- if (FFA_MINOR_VERSION(regs.a0) < FFA_MINOR_VERSION(FFA_VERSION_1_1))
+ if (FFA_MINOR_VERSION(regs.a0) < FFA_MINOR_VERSION(FFA_VERSION_1_2))
hyp_ffa_version = regs.a0;
else
- hyp_ffa_version = FFA_VERSION_1_1;
+ hyp_ffa_version = FFA_VERSION_1_2;
tx = pages;
pages += KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE;
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index 5bded24dc24fea8cdcbe42bf79c7c025c3fa5f4b..c0dd6183d956043192114a522b7eef465e7078ac 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -128,6 +128,7 @@
#define FFA_FEAT_RXTX_MIN_SZ_4K 0
#define FFA_FEAT_RXTX_MIN_SZ_64K 1
#define FFA_FEAT_RXTX_MIN_SZ_16K 2
+#define FFA_FEAT_RXTX_MIN_SZ_MASK 3
/* FFA Bus/Device/Driver related */
struct ffa_device {
--
2.50.0.rc2.701.gf1e915cc24-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH v5 6/6] KVM: arm64: Support FFA_MSG_SEND_DIRECT_REQ2 in host handler
2025-06-19 9:02 [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI Per Larsen via B4 Relay
` (4 preceding siblings ...)
2025-06-19 9:02 ` [PATCH v5 5/6] KVM: arm64: Bump the supported version of FF-A to 1.2 Per Larsen via B4 Relay
@ 2025-06-19 9:02 ` Per Larsen via B4 Relay
5 siblings, 0 replies; 8+ messages in thread
From: Per Larsen via B4 Relay @ 2025-06-19 9:02 UTC (permalink / raw)
To: Marc Zyngier, Oliver Upton, Joey Gouly, Suzuki K Poulose,
Zenghui Yu, Catalin Marinas, Will Deacon, Sudeep Holla
Cc: linux-arm-kernel, kvmarm, linux-kernel, Per Larsen
From: Per Larsen <perlarsen@google.com>
FF-A 1.2 adds the DIRECT_REQ2 messaging interface which is similar to
the existing FFA_MSG_SEND_DIRECT_{REQ,RESP} functions except that it
uses the SMC calling convention v1.2 which allows calls to use x4-x17 as
argument and return registers. Add support for FFA_MSG_SEND_DIRECT_REQ2
in the host ffa handler.
Signed-off-by: Per Larsen <perlarsen@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 24 +++++++++++++++++++++++-
include/linux/arm_ffa.h | 2 ++
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 7b43279aded7d7ef4cce2c294d208c5a66b684e3..37bde2ea2219e37ea68f859e6f211c868585285d 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -678,7 +678,6 @@ static bool ffa_call_supported(u64 func_id)
case FFA_NOTIFICATION_GET:
case FFA_NOTIFICATION_INFO_GET:
/* Unimplemented interfaces added in FF-A 1.2 */
- case FFA_MSG_SEND_DIRECT_REQ2:
case FFA_MSG_SEND_DIRECT_RESP2:
case FFA_CONSOLE_LOG:
case FFA_PARTITION_INFO_GET_REGS:
@@ -860,6 +859,22 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *regs,
hyp_spin_unlock(&host_buffers.lock);
}
+static void do_ffa_direct_msg2(struct arm_smccc_1_2_regs *regs,
+ struct kvm_cpu_context *ctxt,
+ u64 vm_handle)
+{
+ DECLARE_REG(u32, endp, ctxt, 1);
+
+ struct arm_smccc_1_2_regs *args = (void *)&ctxt->regs.regs[0];
+
+ if (FIELD_GET(FFA_SRC_ENDPOINT_MASK, endp) != vm_handle) {
+ ffa_to_smccc_1_2_error(regs, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ arm_smccc_1_2_smc(args, regs);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs regs;
@@ -918,11 +933,18 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_PARTITION_INFO_GET:
do_ffa_part_get(®s, host_ctxt);
goto out_handled;
+ case FFA_MSG_SEND_DIRECT_REQ2:
+ if (hyp_ffa_version >= FFA_VERSION_1_2) {
+ do_ffa_direct_msg2(®s, host_ctxt, HOST_FFA_ID);
+ goto out_handled;
+ }
+ goto out_not_supported;
}
if (ffa_call_supported(func_id))
return false; /* Pass through */
+out_not_supported:
ffa_to_smccc_1_2_error(®s, FFA_RET_NOT_SUPPORTED);
out_handled:
ffa_set_retval(host_ctxt, ®s);
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index c0dd6183d956043192114a522b7eef465e7078ac..82a35a3b22de426f7e9a8894e76fdf1e933b3d6b 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -269,6 +269,8 @@ bool ffa_partition_check_property(struct ffa_device *dev, u32 property)
(ffa_partition_check_property(dev, FFA_PARTITION_DIRECT_REQ2_RECV) && \
!dev->mode_32bit)
+#define FFA_SRC_ENDPOINT_MASK GENMASK(31, 16)
+
/* For use with FFA_MSG_SEND_DIRECT_{REQ,RESP} which pass data via registers */
struct ffa_send_direct_data {
unsigned long data0; /* w3/x3 */
--
2.50.0.rc2.701.gf1e915cc24-goog
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v5 3/6] KVM: arm64: Use SMCCC 1.2 in host FF-A handler
2025-06-19 9:02 ` [PATCH v5 3/6] KVM: arm64: Use SMCCC 1.2 in host FF-A handler Per Larsen via B4 Relay
@ 2025-06-22 13:01 ` Marc Zyngier
0 siblings, 0 replies; 8+ messages in thread
From: Marc Zyngier @ 2025-06-22 13:01 UTC (permalink / raw)
To: perlarsen
Cc: Oliver Upton, Joey Gouly, Suzuki K Poulose, Zenghui Yu,
Catalin Marinas, Will Deacon, Sudeep Holla, linux-arm-kernel,
kvmarm, linux-kernel
On Thu, 19 Jun 2025 10:02:56 +0100,
Per Larsen via B4 Relay <devnull+perlarsen.google.com@kernel.org> wrote:
>
> From: Per Larsen <perlarsen@google.com>
>
> SMCCC 1.1 and prior allows four registers to be sent back as a result
> of an FF-A interface. SMCCC 1.2 increases the number of results that can
> (and often must) be sent back to 8 and 16 for 32-bit and 64-bit SMC/HVCs
> respectively.
>
> FF-A 1.0 references SMCCC 1.2 (reference [4] on page xi) and FF-A 1.2
> explicitly requires SMCCC 1.2 so it should be safe to use this version
> unconditionally. Moreover, it is simpler to implement FF-A features
> without having to worry about compatibility with SMCCC 1.1 and older.
>
> Add SMCCC 1.2 helper routines and use this version unconditionally.
Well, the previous patch already mandates that, so I wonder why you
have two patches tackling the same thing.
>
> Signed-off-by: Per Larsen <perlarsen@google.com>
> ---
> arch/arm64/kvm/hyp/nvhe/ffa.c | 297 ++++++++++++++++++++++++------------------
> 1 file changed, 173 insertions(+), 124 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index 51bbe8f9c94584e9001ee769cbfd608d930ff723..23b75b9f0bcc62724f0d0d185ac2ed2526375da4 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -71,36 +71,55 @@ static u32 hyp_ffa_version;
> static bool has_version_negotiated;
> static hyp_spinlock_t version_lock;
>
> -static void ffa_to_smccc_error(struct arm_smccc_res *res, u64 ffa_errno)
> +static void ffa_to_smccc_1_2_error(struct arm_smccc_1_2_regs *regs, u64 ffa_errno)
> {
> - *res = (struct arm_smccc_res) {
> + *regs = (struct arm_smccc_1_2_regs) {
> .a0 = FFA_ERROR,
> .a2 = ffa_errno,
> };
> }
>
> -static void ffa_to_smccc_res_prop(struct arm_smccc_res *res, int ret, u64 prop)
> +static void ffa_to_smccc_regs_prop(struct arm_smccc_1_2_regs *regs, int ret,
> + u64 prop)
> {
> if (ret == FFA_RET_SUCCESS) {
> - *res = (struct arm_smccc_res) { .a0 = FFA_SUCCESS,
> - .a2 = prop };
> + *regs = (struct arm_smccc_1_2_regs) { .a0 = FFA_SUCCESS,
> + .a2 = prop };
> } else {
> - ffa_to_smccc_error(res, ret);
> + ffa_to_smccc_1_2_error(regs, ret);
> }
> }
>
> -static void ffa_to_smccc_res(struct arm_smccc_res *res, int ret)
> +static void ffa_to_smccc_regs(struct arm_smccc_1_2_regs *regs, int ret)
> {
> - ffa_to_smccc_res_prop(res, ret, 0);
> + ffa_to_smccc_regs_prop(regs, ret, 0);
> }
>
> static void ffa_set_retval(struct kvm_cpu_context *ctxt,
> - struct arm_smccc_res *res)
> + struct arm_smccc_1_2_regs *regs)
> {
> - cpu_reg(ctxt, 0) = res->a0;
> - cpu_reg(ctxt, 1) = res->a1;
> - cpu_reg(ctxt, 2) = res->a2;
> - cpu_reg(ctxt, 3) = res->a3;
> + cpu_reg(ctxt, 0) = regs->a0;
> + cpu_reg(ctxt, 1) = regs->a1;
> + cpu_reg(ctxt, 2) = regs->a2;
> + cpu_reg(ctxt, 3) = regs->a3;
> + cpu_reg(ctxt, 4) = regs->a4;
> + cpu_reg(ctxt, 5) = regs->a5;
> + cpu_reg(ctxt, 6) = regs->a6;
> + cpu_reg(ctxt, 7) = regs->a7;
> +
But my main problem with this patch is this sort of pointless
churn. Changing "res" to "regs" just for the sake of it is completely
pointless, and makes everything harder to read.
Please do yourself (and everybody else) a favour by keeping the
variable name the same.
> + /* DEN0028C 2.6: SMC32/HVC32 call from aarch64 must preserve x8-x30 */
> + if (ARM_SMCCC_IS_64(regs->a0)) {
This is the *return value*, right? Not the function number. How can
you tell about the 64-bitness of the function number based on that?
> + cpu_reg(ctxt, 8) = regs->a8;
> + cpu_reg(ctxt, 9) = regs->a9;
> + cpu_reg(ctxt, 10) = regs->a10;
> + cpu_reg(ctxt, 11) = regs->a11;
> + cpu_reg(ctxt, 12) = regs->a12;
> + cpu_reg(ctxt, 13) = regs->a13;
> + cpu_reg(ctxt, 14) = regs->a14;
> + cpu_reg(ctxt, 15) = regs->a15;
> + cpu_reg(ctxt, 16) = regs->a16;
> + cpu_reg(ctxt, 17) = regs->a17;
> + }
> }
>
> static bool is_ffa_call(u64 func_id)
> @@ -113,82 +132,104 @@ static bool is_ffa_call(u64 func_id)
>
> static int ffa_map_hyp_buffers(u64 ffa_page_count)
> {
> - struct arm_smccc_res res;
> + struct arm_smccc_1_2_regs regs;
>
> - 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,
> - 0, 0, 0, 0,
> - &res);
> + regs = (struct arm_smccc_1_2_regs) {
> + .a0 = FFA_FN64_RXTX_MAP,
> + .a1 = hyp_virt_to_phys(hyp_buffers.tx),
> + .a2 = hyp_virt_to_phys(hyp_buffers.rx),
> + .a3 = ffa_page_count,
> + };
> + arm_smccc_1_2_smc(®s, ®s);
To expand on my previous comment about this res/regs repainting, I'd
rather see something like:
struct arm_smccc_1_2_regs res;
arm_smccc_1_2_smc(&(struct arm_smccc_1_2_regs){
.a0 = FFA_FN64_RXTX_MAP,
.a1 = hyp_virt_to_phys(hyp_buffers.tx),
.a2 = hyp_virt_to_phys(hyp_buffers.rx),
.a3 = ffa_page_count,
}, &res);
> + if (regs.a0 != FFA_SUCCESS)
> + return regs.a2;
>
> - return res.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : res.a2;
> + return regs.a0 == FFA_SUCCESS ? FFA_RET_SUCCESS : regs.a2;
Why are you writing the same thing twice?
I stopped reading here.
M.
--
Jazz isn't dead. It just smells funny.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-06-22 13:01 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-19 9:02 [PATCH v5 0/6] KVM: arm64: Support FF-A 1.2 and SEND_DIRECT2 ABI Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 1/6] KVM: arm64: Correct return value on host version downgrade attempt Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 2/6] KVM: arm64: Use SMCCC 1.2 in hyp_ffa_{init,post_init} Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 3/6] KVM: arm64: Use SMCCC 1.2 in host FF-A handler Per Larsen via B4 Relay
2025-06-22 13:01 ` Marc Zyngier
2025-06-19 9:02 ` [PATCH v5 4/6] KVM: arm64: Mark FFA_NOTIFICATION_* calls as unsupported Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 5/6] KVM: arm64: Bump the supported version of FF-A to 1.2 Per Larsen via B4 Relay
2025-06-19 9:02 ` [PATCH v5 6/6] KVM: arm64: Support FFA_MSG_SEND_DIRECT_REQ2 in host handler Per Larsen via B4 Relay
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).