Re: [PATCH v14 09/44] arm64: RMI: Provide functions to delegate/undelegate ranges of memory
From: Suzuki K Poulose
Date: Thu May 21 2026 - 12:30:02 EST
On 21/05/2026 14:59, Marc Zyngier wrote:
On Wed, 13 May 2026 14:17:17 +0100,
Steven Price <steven.price@xxxxxxx> wrote:
The RMM requires memory is 'delegated' to it so that it can be used
either for a realm guest or for various tracking purposes within the RMM
(e.g. for metadata or page tables). Memory that has been delegated
cannot be accessed by the host (it will result in a Granule Protection
Fault).
Undelegation may fail if the memory is still in use by the RMM. This
shouldn't happen (Linux should ensure it has destroyed the RMM objects
before attempting to undelegate). In the event that it does happen this
points to a programming bug and the only reasonable approach is for the
physical pages to be leaked - it is up to the caller of
rmi_undelegate_range() to handle this.
Signed-off-by: Steven Price <steven.price@xxxxxxx>
---
v14:
* Split into separate patch and moved out of KVM
---
arch/arm64/include/asm/rmi_cmds.h | 13 +++++++++++
arch/arm64/kernel/rmi.c | 36 +++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+)
diff --git a/arch/arm64/include/asm/rmi_cmds.h b/arch/arm64/include/asm/rmi_cmds.h
index 9078a2920a7c..eb213c8e6f26 100644
--- a/arch/arm64/include/asm/rmi_cmds.h
+++ b/arch/arm64/include/asm/rmi_cmds.h
@@ -33,6 +33,19 @@ struct rmi_sro_state {
} while (RMI_RETURN_STATUS(res.a0) == RMI_BUSY || \
RMI_RETURN_STATUS(res.a0) == RMI_BLOCKED)
+int rmi_delegate_range(phys_addr_t phys, unsigned long size);
+int rmi_undelegate_range(phys_addr_t phys, unsigned long size);
+
+static inline int rmi_delegate_page(phys_addr_t phys)
+{
+ return rmi_delegate_range(phys, PAGE_SIZE);
+}
+
+static inline int rmi_undelegate_page(phys_addr_t phys)
+{
+ return rmi_undelegate_range(phys, PAGE_SIZE);
+}
+
bool rmi_is_available(void);
unsigned long rmi_sro_execute(struct rmi_sro_state *sro, gfp_t gfp);
diff --git a/arch/arm64/kernel/rmi.c b/arch/arm64/kernel/rmi.c
index 52a415e99500..08cef54acadb 100644
--- a/arch/arm64/kernel/rmi.c
+++ b/arch/arm64/kernel/rmi.c
@@ -12,6 +12,42 @@ static bool arm64_rmi_is_available;
unsigned long rmm_feat_reg0;
unsigned long rmm_feat_reg1;
+int rmi_delegate_range(phys_addr_t phys, unsigned long size)
+{
+ unsigned 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)
+ phys = out_top;
+ else if (ret != RMI_BUSY && ret != RMI_BLOCKED)
+ return ret;
+ }
+
+ return ret;
+}
+
+int rmi_undelegate_range(phys_addr_t phys, unsigned long size)
+{
+ unsigned long ret = 0;
+ unsigned long top = phys + size;
+ unsigned long out_top;
+
+ WARN_ON(size == 0);
I find it odd to warn on size = 0. After all, free(NULL) is not an
error. But even then, you continue feeding this to the RMM.
You also don't seem to be bothered with that on the delegation side...
+
+ while (phys < top) {
+ ret = rmi_granule_range_undelegate(phys, top, &out_top);
+ if (ret == RMI_SUCCESS)
+ phys = out_top;
and size==0 doesn't violate any of the failure conditions listed in
B4.5.18.2 (beta2). Will you end-up looping around forever?
That is not true ? It triggers, top_bound error condition, for both.
pre: UInt(top) <= UInt(base)
post: result.status == RMI_ERROR_INPUT
Suzuki
Same questions for the delegation, obviously.
M.