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

Suzuki K Poulose suzuki.poulose at arm.com
Wed Sep 23 15:31:57 PDT 2026


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 at arm.com>
>>
>> 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 at arm.com>
>> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>

> [...]
> 
>> 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


> 




More information about the linux-arm-kernel mailing list