From: Snehal Koukuntla <snehalreddy@google.com>
To: Marc Zyngier <maz@kernel.org>, Oliver Upton <oupton@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will@kernel.org>,
Sudeep Holla <sudeep.holla@kernel.org>
Cc: Vincent Donnefort <vdonnefort@google.com>,
Fuad Tabba <fuad.tabba@linux.dev>,
Joey Gouly <joey.gouly@arm.com>,
Suzuki K Poulose <suzuki.poulose@arm.com>,
Mark Rutland <mark.rutland@arm.com>,
Sebastian Ene <sebastianene@google.com>,
Mostafa Saleh <smostafa@google.com>,
Snehal Koukuntla <snehalreddy@google.com>,
linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/2] KVM: arm64: Support FFA_FN64_MEM_RECLAIM2 in host handler
Date: Mon, 21 Sep 2026 16:47:48 +0000 [thread overview]
Message-ID: <20260921164748.2958578-3-snehalreddy@google.com> (raw)
In-Reply-To: <20260921164748.2958578-1-snehalreddy@google.com>
FF-A v1.3 ALP5 (DEN0140 rev J) adds the FFA_MEM_RECLAIM2 interface,
allowing an Owner to reclaim a subset of pages from a shared or lent
memory region by populating constituent memory region descriptors in
its TX buffer along with a starting descriptor byte offset and initial
page index. Upon completion, the Relayer returns the number of 4K pages
reclaimed in x3.
Support FFA_FN64_MEM_RECLAIM2 in the host FF-A proxy handler. Validate
the register arguments, descriptor bounds, and initial page index
against the host TX buffer before forwarding the SMC call to the SPMD,
and unshare the reclaimed page ranges in the host stage-2 page tables.
Link: https://support.arm.com/documentation/den0140/j
Signed-off-by: Snehal Koukuntla <snehalreddy@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 117 ++++++++++++++++++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 5ad74ab265b5..e0fba07a67bc 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -232,6 +232,19 @@ static void ffa_mem_reclaim(struct arm_smccc_1_2_regs *res, u32 handle_lo,
}, res);
}
+static void ffa_mem_reclaim2(struct arm_smccc_1_2_regs *res, u64 handle,
+ u64 flags, u64 x3, u64 x4, u64 x5)
+{
+ hyp_smccc_1_2_smc(&(struct arm_smccc_1_2_regs) {
+ .a0 = FFA_FN64_MEM_RECLAIM2,
+ .a1 = handle,
+ .a2 = flags,
+ .a3 = x3,
+ .a4 = x4,
+ .a5 = x5,
+ }, res);
+}
+
static void ffa_retrieve_req(struct arm_smccc_1_2_regs *res, u32 len)
{
hyp_smccc_1_2_smc(&(struct arm_smccc_1_2_regs) {
@@ -611,6 +624,107 @@ static void __do_ffa_mem_xfer(const u64 func_id,
__do_ffa_mem_xfer((fid), (res), (ctxt)); \
} while (0);
+static void do_ffa_mem_reclaim2(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u64, handle, ctxt, 1);
+ DECLARE_REG(u64, flags, ctxt, 2);
+ DECLARE_REG(u64, x3, ctxt, 3);
+ DECLARE_REG(u64, x4, ctxt, 4);
+ DECLARE_REG(u64, x5, ctxt, 5);
+ u32 req_desc_cnt = (u32)(x3 >> 32);
+ u32 total_pages = (u32)x3;
+ u32 desc_size = (u32)x4;
+ u32 offset = (u32)x5;
+ u32 page_index = (u32)(x5 >> 32);
+ struct ffa_mem_region_addr_range *range;
+ u32 reclaimed_pages;
+ u32 reclaimed_count = 0;
+ u32 in_idx;
+ int ret = 0;
+
+ if (ffa_check_unused_args_sbz(ctxt, 6) || (flags & ~1ULL) || (x4 >> 32)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (!req_desc_cnt || !total_pages) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (desc_size != sizeof(struct ffa_mem_region_addr_range)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if ((u64)req_desc_cnt * desc_size > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (offset % desc_size != 0) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (offset >= (u64)req_desc_cnt * desc_size) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ hyp_spin_lock(&host_buffers.lock);
+ if (!host_buffers.tx) {
+ ret = FFA_RET_INVALID_PARAMETERS;
+ goto out_unlock;
+ }
+
+ memcpy(hyp_buffers.tx, host_buffers.tx, (u64)req_desc_cnt * desc_size);
+
+ range = (void *)hyp_buffers.tx + offset;
+ if (page_index >= range->pg_cnt) {
+ ret = FFA_RET_INVALID_PARAMETERS;
+ goto out_unlock;
+ }
+
+ ffa_mem_reclaim2(res, handle, flags, x3, x4, x5);
+ if (res->a0 != FFA_SUCCESS)
+ goto out_unlock;
+
+ reclaimed_pages = res->a3;
+
+ for (in_idx = offset / desc_size; in_idx < req_desc_cnt; in_idx++) {
+ struct ffa_mem_region_addr_range temp;
+ u32 pg_cnt, to_reclaim;
+
+ if (reclaimed_count >= reclaimed_pages)
+ break;
+
+ range = (void *)hyp_buffers.tx + in_idx * desc_size;
+ if (!range->pg_cnt)
+ continue;
+
+ pg_cnt = range->pg_cnt - page_index;
+ to_reclaim = min(pg_cnt, reclaimed_pages - reclaimed_count);
+
+ temp = (struct ffa_mem_region_addr_range) {
+ .address = range->address + (u64)page_index * FFA_PAGE_SIZE,
+ .pg_cnt = to_reclaim,
+ };
+
+ WARN_ON(ffa_host_unshare_ranges(&temp, 1));
+
+ reclaimed_count += to_reclaim;
+ page_index = 0;
+ }
+
+out_unlock:
+ hyp_spin_unlock(&host_buffers.lock);
+
+ if (ret)
+ ffa_to_smccc_res(res, ret);
+}
+
static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
struct kvm_cpu_context *ctxt)
{
@@ -1107,6 +1221,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_MEM_RECLAIM:
do_ffa_mem_reclaim(&res, host_ctxt);
goto out_handled;
+ case FFA_FN64_MEM_RECLAIM2:
+ do_ffa_mem_reclaim2(&res, 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);
--
2.55.0.1082.g2b9226bbc0-goog
next prev parent reply other threads:[~2026-09-21 16:48 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-21 16:47 [PATCH 0/2] " Snehal Koukuntla
2026-09-21 16:47 ` [PATCH 1/2] firmware: arm_ffa: Add FFA_FN64_MEM_RECLAIM2 function ID Snehal Koukuntla
2026-09-22 12:15 ` Sudeep Holla
2026-09-21 16:47 ` Snehal Koukuntla [this message]
2026-09-22 10:07 ` [PATCH 2/2] KVM: arm64: Support FFA_FN64_MEM_RECLAIM2 in host handler Vincent Donnefort
2026-09-22 11:16 ` Snehal Koukuntla
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260921164748.2958578-3-snehalreddy@google.com \
--to=snehalreddy@google.com \
--cc=catalin.marinas@arm.com \
--cc=fuad.tabba@linux.dev \
--cc=joey.gouly@arm.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=sebastianene@google.com \
--cc=smostafa@google.com \
--cc=sudeep.holla@kernel.org \
--cc=suzuki.poulose@arm.com \
--cc=vdonnefort@google.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®