From: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
To: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: kvm@vger.kernel.org, kvmarm@lists.linux.dev, maz@kernel.org,
will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, steven.price@arm.com,
aneesh.kumar@kernel.org, oupton@kernel.org, gshan@redhat.com,
joey.gouly@arm.com, tabba@google.com, yuzenghui@huawei.com,
linux-coco@lists.linux.dev, gankulkarni@os.amperecomputing.com,
sdonthineni@nvidia.com, alpergun@google.com,
fj0570is@fujitsu.com, WeiLin.Chang@arm.com,
lpieralisi@kernel.org, enju.kohei@fujitsu.com,
sudeep.holla@arm.com
Subject: Re: [PATCH v19 4/7] firmware: arm_rmm: Add support for SRO
Date: Thu, 24 Sep 2026 12:13:56 -0700 [thread overview]
Message-ID: <20260924121356.00000d4d@oss.qualcomm.com> (raw)
In-Reply-To: <20260924135201.850038-5-suzuki.poulose@arm.com>
On Thu, 24 Sep 2026 14:51:58 +0100
Suzuki K Poulose <suzuki.poulose@arm.com> wrote:
> From: Steven Price <steven.price@arm.com>
>
> RMM v2.0 introduces the concept of "Stateful RMI Operations" (SRO). This
> means that an SMC can return with an operation still in progress. The
> host is expected to continue the operation until it reaches a conclusion
> (either success or failure). During this process the RMM can request
> additional memory ('donate') or hand memory back to the host
> ('reclaim'). The host can request an in progress operation is cancelled,
> but still continue the operation until it has completed (otherwise the
> incomplete operation may cause future RMM operations to fail).
>
> The SRO is tracked using a struct rmi_sro_state object which keeps track
> of any memory which has been allocated but not yet consumed by the RMM
> or reclaimed from the RMM. This allows the memory to be reused in a
> future request within the same operation. It will also permit an
> operation to be done in a context where memory allocation may be
> difficult (e.g. atomic context) with the option to abort the operation
> and retry the memory allocation outside of the atomic context. The
> memory stored in the struct rmi_sro_state object can then be reused on
> the subsequent attempt.
>
> Wrappers for SRO RMI commands are also provided here because they depend
> on the rmi_sro_execute() implementation added by this patch.
> Delegate/undelegate handles are also added here because they now use the
> SRO/stateful command infrastructure and are also used for the memory
> DONATE/RECLAIM flows.
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> Co-developed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Nice. Everything I spotted this time around is pretty trivial.
So assuming you'll clean up and bits that make sense to you for v20
Reviewed-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
> ---
> drivers/firmware/arm_rmm/rmi.c | 666 +++++++++++++++++++++++++++++++++
> include/linux/arm-rmi-cmds.h | 41 ++
> 2 files changed, 707 insertions(+)
>
> diff --git a/drivers/firmware/arm_rmm/rmi.c b/drivers/firmware/arm_rmm/rmi.c
> index c9ea964fd9081..035f21d3f26b6 100644
> --- a/drivers/firmware/arm_rmm/rmi.c
> +++ b/drivers/firmware/arm_rmm/rmi.c
> +
> +int rmi_undelegate_range(phys_addr_t phys,
> + unsigned long size)
> +{
> + long ret = 0;
> + unsigned long top = phys + size;
> + unsigned long out_top;
> +
> + while (phys < top) {
> + ret = rmi_granule_range_undelegate(phys, top, &out_top);
> +
> + if (ret == RMI_SUCCESS) {
> + /* Buggy RMM ? Let the caller leak the pages */
> + if (WARN_ON(out_top <= phys))
> + return -ENXIO;
> + phys = out_top;
> + } else {
Similar to below, why not deal with error case first and reduce indent of
the good path.
> + break;
> + }
> + }
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(rmi_undelegate_range);
> +/*
> + * rmi_delegate_range: Delegate a physically contiguous range.
> + * We iterate over the range until we hit an error. So we may
> + * return an error, but with a partially delegated range. The
> + * caller must always look at the @out_phys to figure out, how
> + * much progress was made.
> + *
> + * @phys: Base of the physical address range
> + * @size: Size of the physical address range
> + * @out_phys: Top of the range that was completed. This is always
> + * valid, irrespective of the result.
> + *
> + * Returns RMI_SUCCESS on successful completion. Otherwise, returns
> + * the Linux error number or the RMI status code as described
> + * by the RMM spec for RMI_GRANULE_DELEGATE_RANGE or RMI_BLOCKED.
> + */
> +int rmi_delegate_range(phys_addr_t phys,
> + unsigned long size,
> + phys_addr_t *out_phys)
> +{
> + long ret = 0;
> + unsigned long top = phys + size;
> + unsigned long out_top;
> +
> + while (phys < top) {
> + ret = rmi_granule_range_delegate(phys, top, &out_top);
> +
> + if (ret == RMI_SUCCESS) {
My instinct here would be to flip this and have the error out of line given
it breaks anyway and that gives you smaller indent for that ocmment block.
if (ret != RMI_SUCCESS)
break;
/*
* Buggy RMM ? Let the caller handle the failure. We can't know
* how far the RMM delegated in this iteration, so we return
* the best known good limit. RMM can deal with granules
* already in "undelegated" in a given range. So, it is fine
* for the caller to try the range we return.
*/
if (WARN_ON...
> + /*
> + * Buggy RMM ? Let the caller handle the failure.
> + * We can't know how far the RMM delegated in this
> + * iteration, so we return the best known good limit.
> + * RMM can deal with granules already in "undelegated"
> + * in a given range. So, it is fine for the caller to
> + * try the range we return.
> + */
> + if (WARN_ON(out_top <= phys)) {
> + ret = -ENXIO;
> + break;
> + }
> + phys = out_top;
> + } else {
> + break;
> + }
> + }
> +
> + if (out_phys)
> + *out_phys = phys;
> +
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(rmi_delegate_range);
...
> +
> +static int rmi_sro_donate_noncontig(struct rmi_sro_state *sro,
> + unsigned long sro_handle,
> + unsigned long donatereq,
> + struct arm_smccc_1_2_regs *out_regs,
> + gfp_t gfp)
> +{
...
> +
> + /* Gather the suitable entries to the end of the list */
> + i = 0;
> + while (i < addr_list_start && found < count) {
> + unsigned long entry = sro->addr_list[i];
> +
> + if (RMI_ADDR_RANGE_BLOCK_SIZE(entry) == block_size_fld &&
> + RMI_ADDR_RANGE_COUNT(entry) == 1 &&
> + RMI_ADDR_RANGE_STATE(entry) == state) {
> + addr_list_start--;
> + swap(sro->addr_list[addr_list_start],
> + sro->addr_list[i]);
> + found++;
> + /* Continue from the swapped in entry */
> + continue;
> + }
> + /* skip past the entry */
Bit random on comment capitalization. Have a quick final look through.
For instance I think this one is Skip to match Continue above.
> + i++;
> + }
...
> +
> +static int rmi_sro_reclaim(struct rmi_sro_state *sro,
> + unsigned long sro_handle,
> + struct arm_smccc_1_2_regs *out_regs)
> +{
> + unsigned long capacity;
> +
> + /*
> + * We don't do a partial free of the entries. So for
> + * now free the entire address list as we prepare
> + * to reclaim more from the RMM.
Rewrap to use all that nice space up to 80 chars! I guess a refactoring
side effect.
> + */
> + if (rmi_sro_ensure_capacity(sro, 1))
> + rmi_sro_free(sro);
> +
> + capacity = RMI_MAX_ADDR_LIST - sro->addr_count;
> +
> + rmi_op_mem_reclaim(sro_handle,
> + virt_to_phys(&sro->addr_list[sro->addr_count]),
> + capacity, out_regs);
> +
> + /*
> + * RMI_OP_MEM_RECLAIM always return RMI_INCOMPLETE, except when the
> + * input parameters were invalid.
> + */
> + if (WARN_ON_ONCE(RMI_RESULT_STATUS(out_regs->a0) != RMI_INCOMPLETE))
> + return -EINVAL;
> + if (WARN_ON_ONCE(out_regs->a1 > capacity))
> + out_regs->a1 = capacity;
> +
> + sro->addr_count += out_regs->a1;
> +
> + return 0;
> +}
> +
> +long rmi_sro_memxfer_execute(struct rmi_sro_state *sro, gfp_t gfp)
> +{
> + struct arm_smccc_1_2_regs *regs = &sro->regs;
> + bool cancelled = false;
> + unsigned long sro_handle;
> +
> + rmi_smccc_invoke(regs);
> +
> + sro_handle = regs->a1;
> + while (RMI_RESULT_STATUS(regs->a0) == RMI_INCOMPLETE) {
> + bool can_cancel = RMI_RESULT_CAN_CANCEL(regs->a0) == RMI_OP_CAN_CANCEL;
For a flag that is "can" or "cannot", do we need the RMI_OP_CAN_CANCEL (1) / RMI_OP_CANNOT_CANCEL (0)
defines? Doesn't feel like we'll ever get RMI_OP_UNKNOWN_IF_IT_CAN_CANCEL and I can't think
of any other more reasonable options that would justify needing the explicit field value
match.
To me
bool can_cancel = RMI_RESULT_CAN_CANCEL(regs->a0);
is obvious enough. I don't care that much though so up to you.
> + int ret = 0;
> +
> + switch (RMI_RESULT_MEMREQ(regs->a0)) {
> + case RMI_OP_MEM_REQ_NONE:
> + rmi_op_continue(sro_handle, RMI_CONTINUE_KEEP_GOING,
> + regs);
> + break;
> + case RMI_OP_MEM_REQ_DONATE:
> + ret = rmi_sro_donate(sro, sro_handle, regs->a2, regs,
> + gfp);
> + break;
> + case RMI_OP_MEM_REQ_RECLAIM:
> + ret = rmi_sro_reclaim(sro, sro_handle, regs);
> + break;
> + default:
> + WARN_ON_ONCE(1);
> + ret = -ENXIO;
> + break;
> + }
> +
> + if (ret) {
> + /*
> + * All memory donating SROs must be cancellable. So a
> + * failure in memory allocation shouldn't be an issue.
> + * However, if we encounter a random failure (e.g.,
> + * buggy RMM), don't loop forever, just give up.
> + */
> + if (WARN_ON_ONCE(!can_cancel))
> + return ret;
> + /*
> + * If we have already cancelled, and came back here due
> + * to an error in MEMREQ, then there is no point
> + * in going in loops.
> + */
> + if (WARN_ON_ONCE(cancelled))
> + break;
> + rmi_op_cancel(sro_handle, regs);
> + cancelled = true;
> +
> + if (WARN_ON_ONCE(RMI_RESULT_STATUS(regs->a0) != RMI_INCOMPLETE))
> + return ret;
> + }
> + }
> +
> + if (cancelled)
> + return -ECANCELED;
> +
> + return regs->a0;
> +}
> +EXPORT_SYMBOL_GPL(rmi_sro_memxfer_execute);
> +
> +/*
> + * rmi_sro_execute: Execute an RMI command that is Stateful but not memory
> + * tranfserring. Takes regs, filled with the FIDs and the arguments in place.
Spell check. Transferring. Also why does Stateful get a capital letter and
Memory Transferring does not. They seem to both be properties of the comman
so I'd expect some consistency.
> + *
> + * Returns :
> + * -ECANCELLED - If the operation had to be aborted and SRO was cancellable.
> + * Otherwise, returns the result of the RMI command.
> + */
> +long rmi_sro_execute(struct arm_smccc_1_2_regs *regs)
> +{
> + bool cancelled = false;
> + unsigned long sro_handle = regs->a1;
> +
> + rmi_smccc_invoke(regs);
> +
> + sro_handle = regs->a1;
> + while (RMI_RESULT_STATUS(regs->a0) == RMI_INCOMPLETE) {
> + bool can_cancel = RMI_RESULT_CAN_CANCEL(regs->a0) == RMI_OP_CAN_CANCEL;
> +
> + switch (RMI_RESULT_MEMREQ(regs->a0)) {
> + case RMI_OP_MEM_REQ_NONE:
> + rmi_op_continue(sro_handle, RMI_CONTINUE_KEEP_GOING,
> + regs);
> + break;
> + default:
> + WARN_ON_ONCE(1);
> + if (!can_cancel)
> + return regs->a0;
> + /*
> + * We can't get here normally, but handle this anyway
> + * for a buggy RMM implementation.
> + */
> + if (cancelled)
> + return -ECANCELED;
> + rmi_op_cancel(sro_handle, regs);
> + cancelled = true;
> + }
> + }
> +
> + if (cancelled)
> + return -ECANCELED;
> +
> + return regs->a0;
> +}
> +EXPORT_SYMBOL_GPL(rmi_sro_execute);
next prev parent reply other threads:[~2026-09-24 19:14 UTC|newest]
Thread overview: 64+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-24 13:51 [PATCH v19 0/7] firmware: arm_rmm: Add RMM v2.0 base RMI support Suzuki K Poulose
2026-09-24 13:51 ` [PATCH v19 1/7] firmware: arm_rmm: Add SMC definitions for calling the RMM Suzuki K Poulose
2026-09-24 16:57 ` Jonathan Cameron
2026-09-24 22:15 ` Suzuki K Poulose
2026-09-24 17:05 ` Ackerley Tng
2026-09-24 22:49 ` Suzuki K Poulose
2026-09-24 13:51 ` [PATCH v19 2/7] firmware: arm_rmm: Check for RMI support at init Suzuki K Poulose
2026-09-24 14:00 ` sashiko-bot
2026-09-24 16:58 ` Jonathan Cameron
2026-09-25 0:00 ` Gavin Shan
2026-09-25 8:51 ` Suzuki K Poulose
2026-09-25 5:43 ` Gavin Shan
2026-09-25 8:50 ` Suzuki K Poulose
2026-09-25 10:42 ` Catalin Marinas
2026-09-25 15:23 ` Suzuki K Poulose
2026-09-27 9:29 ` Marc Zyngier
2026-09-28 8:05 ` Suzuki K Poulose
2026-09-24 13:51 ` [PATCH v19 3/7] firmware: arm_rmm: Configure the RMM with the host's page size Suzuki K Poulose
2026-09-24 17:03 ` Jonathan Cameron
[not found] ` <d4b768e5-c942-43cf-aea2-c266a8bab353@oss.qualcomm.com>
2026-09-25 14:56 ` Suzuki K Poulose
2026-09-26 13:38 ` Venkata Rao Kakani
2026-09-25 0:03 ` Gavin Shan
2026-09-24 13:51 ` [PATCH v19 4/7] firmware: arm_rmm: Add support for SRO Suzuki K Poulose
2026-09-24 14:08 ` sashiko-bot
2026-09-24 23:18 ` Suzuki K Poulose
2026-09-24 19:13 ` Jonathan Cameron [this message]
2026-09-24 23:10 ` Suzuki K Poulose
2026-09-25 5:24 ` Gavin Shan
2026-09-29 12:52 ` Suzuki K Poulose
2026-09-25 11:50 ` Catalin Marinas
2026-09-25 15:11 ` Suzuki K Poulose
2026-09-28 9:28 ` Catalin Marinas
2026-09-28 10:13 ` Suzuki K Poulose
2026-09-28 17:28 ` Catalin Marinas
2026-09-28 20:45 ` Suzuki K Poulose
2026-09-24 13:51 ` [PATCH v19 5/7] firmware: arm_rmm: Activate the RMM Suzuki K Poulose
2026-09-25 12:17 ` Catalin Marinas
2026-09-25 15:02 ` Suzuki K Poulose
2026-09-25 15:34 ` Alper Gun
2026-09-25 16:42 ` Catalin Marinas
2026-09-25 17:50 ` Suzuki K Poulose
2026-09-28 9:08 ` Suzuki K Poulose
2026-09-28 13:55 ` Suzuki K Poulose
2026-09-28 18:01 ` Catalin Marinas
2026-09-28 18:28 ` Suzuki K Poulose
2026-09-29 11:15 ` Catalin Marinas
2026-09-24 13:52 ` [PATCH v19 6/7] firmware: arm_rmm: Ensure the RMM has GPT entries for memory Suzuki K Poulose
2026-09-24 21:38 ` Jonathan Cameron
2026-09-24 23:30 ` Suzuki K Poulose
2026-09-25 15:30 ` Jonathan Cameron
2026-09-25 0:07 ` Gavin Shan
2026-09-29 11:01 ` Catalin Marinas
2026-09-29 12:15 ` Suzuki K Poulose
2026-09-29 22:17 ` Shanker Donthineni
2026-09-29 22:25 ` Suzuki K Poulose
2026-09-29 22:29 ` Shanker Donthineni
2026-09-30 8:17 ` Suzuki K Poulose
2026-09-24 13:52 ` [PATCH v19 7/7] firmware: arm_rmm: Add wrappers for Realm related RMI commands Suzuki K Poulose
2026-09-25 11:56 ` Catalin Marinas
2026-09-29 12:15 ` Suzuki K Poulose
2026-09-25 6:29 ` [PATCH v19 0/7] firmware: arm_rmm: Add RMM v2.0 base RMI support Gavin Shan
2026-09-25 9:03 ` Suzuki K Poulose
2026-09-29 10:50 ` Catalin Marinas
2026-09-29 12:14 ` Suzuki K Poulose
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=20260924121356.00000d4d@oss.qualcomm.com \
--to=jonathan.cameron@oss.qualcomm.com \
--cc=WeiLin.Chang@arm.com \
--cc=alpergun@google.com \
--cc=aneesh.kumar@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=enju.kohei@fujitsu.com \
--cc=fj0570is@fujitsu.com \
--cc=gankulkarni@os.amperecomputing.com \
--cc=gshan@redhat.com \
--cc=joey.gouly@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=lpieralisi@kernel.org \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=sdonthineni@nvidia.com \
--cc=steven.price@arm.com \
--cc=sudeep.holla@arm.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.