[PATCH v18 4/7] firmware: arm_rmm: Add support for SRO

Suzuki K Poulose suzuki.poulose at arm.com
Mon Sep 14 07:47:57 PDT 2026


On 14/09/2026 15:02, Suzuki K Poulose wrote:
> On 14/09/2026 13:50, Sudeep Holla wrote:
>> On Sat, Sep 12, 2026 at 09:36:07AM +0100, Suzuki K Poulose wrote:
>>> 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 at arm.com>
>>> Co-Developed-by: Suzuki K Poulose <suzuki.poulose at arm.com>
>>> Signed-off-by: Suzuki K Poulose <suzuki.poulose at arm.com>
>>
>> [...]
>>
>>> +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)
>>> +{
>>> +    unsigned long block_size_fld = RMI_DONATE_BLOCK_SIZE(donatereq);
>>> +    unsigned long block_size = 
>>> rmi_addr_block_size_to_bytes(block_size_fld);
>>> +    unsigned long count = RMI_DONATE_COUNT(donatereq);
>>> +    unsigned long state = RMI_DONATE_STATE(donatereq);
>>> +    unsigned long found = 0;
>>> +    unsigned long donated_granules;
>>> +    unsigned long granules_per_block = block_size >> PAGE_SHIFT;
>>> +    unsigned long consumed_blocks;
>>> +    int addr_list_start = sro->addr_count;
>>> +
>>> +    int ret;
>>> +
>>> +    for (int i = 0; i < addr_list_start && found < count; i++) {
>>> +        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++;
>>> +            i--;
>>> +        }
>>> +    }
>>> +
>>> +    ret = rmi_sro_ensure_capacity(sro, count - found);
>>> +    if (ret)
>>> +        return ret;
>>> +
>>> +    while (found < count) {
>>> +        unsigned long addr_range;
>>> +        void *virt = alloc_pages_exact(block_size, gfp);
>>> +        phys_addr_t phys;
>>> +
>>> +        if (!virt)
>>> +            return -ENOMEM;
>>> +
>>> +        phys = virt_to_phys(virt);
>>> +
>>> +        if (state == RMI_OP_MEM_DELEGATED) {
>>
>> Based on my understanding, rmi_sro_memxfer_execute() is an exported 
>> function
>> and can be invoked by any module. The donatereq argument appears to 
>> accept one
>> of three operations:
>>
>> RMI_OP_MEM_DELEGATED
>> RMI_OP_MEM_UNDELEGATED
>> RMI_OP_MEM_CONDITIONAL
> 
> Ack
> 
>>
>> Currently, the check confirming the state is RMI_OP_MEM_DELEGATED occurs
>> relatively late in the function execution. It seems this function is
>> explicitly designed to handle only RMI_OP_MEM_DELEGATED.
> 
> No, that is not correct. The function handles both OP_MEM_DELEGATED and
> OP_MEM_UNDELEGATED. In the former case, we explicitly "delegate" the
> pages before donating. The "UNDELEGATED" case doesn't need to do that
> extra step.
> 
>>
>> Given that this is an exported interface, would it make sense to
>> fail-fast by moving this validation to the very beginning of the 
>> function?
>> Even if RMI_OP_MEM_CONDITIONAL is intended for future use, it should
> 
> Yep, agree. We can rejec the CONDITIONAL ones.

For the record, the CONDITIONAL ones are required for self-describing
cases for L1_GPT_CREATE and TRACKING_GRANULE_SET, where the RMM could
accept DELEGATED granules for the objects (if not self describing) or
UNDELEGATED granules  (if they are self-describing).

For now, we don't support such RMMs, so will reject the type for now.

Cheers
Suzuki

> 
>> probably be rejected as invalid for now. Also, it is not clear why the
>> current check is inside the loop while the state itself doesn't get
>> modified.
> 
> As above, that check is additionally preparing the memory for RMM
> consumption.
> 
> 
>>
>> If this is a valid concern, the same architectural pattern should 
>> likely be
>> applied to rmi_sro_donate_contig().
>>
> 
> Ack, we can reject the CONDITIONAL ones.
> 
> Suzuki
> 




More information about the linux-arm-kernel mailing list