Re: [PATCH v18 2/7] firmware: arm_rmm: Check for RMI support at init

From: Suzuki K Poulose

Date: Wed Sep 23 2026 - 18:32:45 EST


Hi Sudeep,

Apologies, this one took longer to address. Thanks for raising this,
response inline.

On 14/09/2026 11:27, Sudeep Holla wrote:
On Sat, Sep 12, 2026 at 09:36:05AM +0100, Suzuki K Poulose wrote:
From: Steven Price <steven.price@xxxxxxx>

Query the RMI version number and check if it is a compatible version.
The first two feature registers are read and exposed for future code to
use.

We only support this for Little Endian kernels, the Big Endian kernel
support is anyway marked BROKEN and is being removed.

Signed-off-by: Steven Price <steven.price@xxxxxxx>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>

[...]

diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h
new file mode 100644
index 0000000000000..9792bf0e00cb9
--- /dev/null
+++ b/include/linux/arm-rmi-cmds.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2026 ARM Ltd.
+ */
+
+#ifndef __LINUX_ARM_RMI_CMDS_H_
+#define __LINUX_ARM_RMI_CMDS_H_
+
+#include <linux/arm-smccc-rmi.h>
+#include <linux/bug.h>
+#include <linux/processor.h>
+#include <linux/types.h>
+
+
+/*
+ * rmi_smccc_invoke: Invoke the RMI call and return the results in @regs_out
+ * @regs_in: Registers with the arguments filled in.
+ * @regs_out: Ouptput results from the call.
+ */
+static inline void rmi_smccc_invoke(struct arm_smccc_1_2_regs *regs)
+{
+ struct arm_smccc_1_2_regs args = *regs;
+ unsigned long status;
+
+ while (1) {
+ arm_smccc_1_2_invoke(&args, regs);
+ status = RMI_RETURN_STATUS(regs->a0);
+ if (status != RMI_BUSY && status != RMI_BLOCKED)
+ break;
+ cpu_relax();
+ }
+}

I haven't done a detailed review, this is just a drive through comment.
The while(1) gained my attention.

Should RMI_BLOCKED be returned to the caller instead of retried here?

Short answer yes, to be safe.


RMM spec defines RMI_BLOCKED as persisting until the Host takes action.
It also says it is returned when another SRO on the same context is
incomplete. You may be running it on different CPUs and hence different

I agree this is poorly documented and we are working on improving the
documentation on this front.

RMI_BLOCKED is a side effect of an incomplete operation (in other
words long running) that has turned some "resource" into an
intermediate state. e.g.

The following operations could put objects into an intermediate
state until the RMM completes it, to ensure correctness.

* Unmap a large IPA range triggering SMMU TLB invalidations.
For KVM, we serialize the unmap S2 with kvm->mmu_lock with
write lock. So two operations could not race (even a map
at the same location).

* Delegate/Undelegate, which again could end up in SMMU GPC
invalidations.
The only case where we race and do parallel "delegate" is
while handling concurrent VCPU faults on two different physical
CPUs. Even there a failing thread handles this by returning
to the guest and taking the fault again (if it wasn't
resolved by the other thread). We could additionally tighten
this by using write lock for the fault (just like pKVM).

* Change the tracking region granularity. e.g, convert from FINE
granulartiy to COARSE or INTERMEDIATE, causing all granules in
the target region to be locked. This is not something we do
in Linux. We mandate the firmware maintains FINE granularity,
at least for now. Even with dynamic tracking, we don't expect
to fold the tracking granularity for regions with "mixed"
entries (which would fail anyway due to the mismatch).

* An object bound SRO handle is active, while another SRO initiating
operation is issued. This possible with a buggy host.
e.g., RMI_REALM_ACTIVATE is called while RMI_RTT_INIT_RIPAS is
in progress. In KVM we serialize this with kvm->arch.config_lock.

For all practical purposes the above operations should complete in
a single try and another command observing the RMI_BLOCKED should
be able to make progress. That said, for Linux it is better to
return the RMI_BLOCKED back to the caller after an arbitrary
tiny number of times. So I have updated the code to try for
3 times for RMI_BLOCKED and return back to the caller.

We could even drop that and just return back immediately to
the caller. Like I described above, the only case where
we expect to hit the RMI_BLOCKED in Linux is for parallel
faults, which could be handled and/or prevented in Linux.



context I assume. But this loop takes no such action and hides the status
from the caller, so a command issued against that context if that can
happen can spin indefinitely while the operation which would unblock it
cannot run. Ignore me if it taken care not to happen elsewhere. I am
just looking at this in isolation.

Could this retry only RMI_BUSY and propagate RMI_BLOCKED so that the caller
can arrange for the incomplete operation to make progress if the above
scenario is possible ?

Ack. I have made the changes in the next version.

Cheers
Suzuki