[PATCH v14 09/44] arm64: RMI: Provide functions to delegate/undelegate ranges of memory
Steven Price
steven.price at arm.com
Wed May 13 06:17:17 PDT 2026
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 at arm.com>
---
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);
+
+ while (phys < top) {
+ ret = rmi_granule_range_undelegate(phys, top, &out_top);
+ if (ret == RMI_SUCCESS)
+ phys = out_top;
+ else if (ret != RMI_BUSY && ret != RMI_BLOCKED)
+ return ret;
+ }
+
+ return ret;
+}
+
static int rmi_check_version(void)
{
struct arm_smccc_res res;
--
2.43.0
More information about the linux-arm-kernel
mailing list