Thread (16 messages) flat view 16 messages, 2 authors, 36m ago

Re: [PATCH v10 3/7] firmware: arm_rmm: Move RSI support out of arch/arm64

From: Jason Gunthorpe <jgg@nvidia.com>
Date: 2026-09-04 19:40:11
Also in: linux-arm-kernel, lkml

quoted hunk ↗ jump to hunk
The RSI SMCCC function IDs describe a firmware ABI and are not arm64
architecture specific definitions. Follow-up changes need to use them from
non-arch code, including drivers/firmware/smccc and the Arm CCA guest
driver.

Move the complete Realm Service Interface (RSI) implementation from
arch/arm64 to drivers/firmware/arm_rmm. The RSI SMCCC definitions and
command helpers are also moved to include/linux so they can be shared by
architecture code and firmware or driver code. This also keeps the
firmware interface outside architecture code, as requested [1].

[1] https://lore.kernel.org/all/agsNO9cc7H-b0H8L@willie-the-truck (local)

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Acked-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index b5a51b0ef9440a..ff9565d3ffa596 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -38,6 +38,7 @@ config ARM64
 	select ARCH_HAS_MEMBARRIER_SYNC_CORE
 	select ARCH_HAS_MEM_ENCRYPT
 	select ARCH_SUPPORTS_MSEAL_SYSTEM_MAPPINGS
+	select ARCH_SUPPORTS_RMM
 	select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
 	select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
 	select ARCH_HAS_NONLEAF_PMD_YOUNG if ARM64_HAFT
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 49a7002661a928..1620537f0332d9 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -8,6 +8,7 @@
 #ifndef __ASM_IO_H
 #define __ASM_IO_H
 
+#include <linux/arm-rsi-cmds.h>
 #include <linux/types.h>
 #include <linux/pgtable.h>
 
@@ -17,7 +18,6 @@
 #include <asm/early_ioremap.h>
 #include <asm/alternative.h>
 #include <asm/cpufeature.h>
-#include <asm/rsi.h>
 
 /*
  * Generic IO read/write.  These perform native-endian accesses.
diff --git a/arch/arm64/include/asm/mem_encrypt.h b/arch/arm64/include/asm/mem_encrypt.h
index 636f45b4d8afc7..f03b9d7b83b438 100644
--- a/arch/arm64/include/asm/mem_encrypt.h
+++ b/arch/arm64/include/asm/mem_encrypt.h
@@ -2,8 +2,8 @@
 #ifndef __ASM_MEM_ENCRYPT_H
 #define __ASM_MEM_ENCRYPT_H
 
+#include <linux/arm-rsi-cmds.h>
 #include <asm/hypervisor.h>
-#include <asm/rsi.h>
 
 struct device;
 
diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h
index 09d7c00cf40541..58e71e592175ef 100644
--- a/arch/arm64/include/asm/pgtable-prot.h
+++ b/arch/arm64/include/asm/pgtable-prot.h
@@ -66,9 +66,9 @@
 
 #ifndef __ASSEMBLER__
 
+#include <linux/arm-rsi-cmds.h>
 #include <asm/cpufeature.h>
 #include <asm/pgtable-types.h>
-#include <asm/rsi.h>
 
 extern bool arm64_use_ng_mappings;
 extern unsigned long prot_ns_shared;
diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
deleted file mode 100644
index 88b50d660e85a0..00000000000000
--- a/arch/arm64/include/asm/rsi.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2024 ARM Ltd.
- */
-
-#ifndef __ASM_RSI_H_
-#define __ASM_RSI_H_
-
-#include <linux/errno.h>
-#include <linux/jump_label.h>
-#include <asm/rsi_cmds.h>
-
-#define RSI_PDEV_NAME "arm-cca-dev"
-
-DECLARE_STATIC_KEY_FALSE(rsi_present);
-
-void __init arm64_rsi_init(void);
-
-bool arm64_rsi_is_protected(phys_addr_t base, size_t size);
-
-static inline bool is_realm_world(void)
-{
-	return static_branch_unlikely(&rsi_present);
-}
-
-static inline int rsi_set_memory_range(phys_addr_t start, phys_addr_t end,
-				       enum ripas state, unsigned long flags)
-{
-	unsigned long ret;
-	phys_addr_t top;
-
-	while (start != end) {
-		ret = rsi_set_addr_range_state(start, end, state, flags, &top);
-		if (ret || top < start || top > end)
-			return -EINVAL;
-		start = top;
-	}
-
-	return 0;
-}
-
-/*
- * Convert the specified range to RAM. Do not use this if you rely on the
- * contents of a page that may already be in RAM state.
- */
-static inline int rsi_set_memory_range_protected(phys_addr_t start,
-						 phys_addr_t end)
-{
-	return rsi_set_memory_range(start, end, RSI_RIPAS_RAM,
-				    RSI_CHANGE_DESTROYED);
-}
-
-/*
- * Convert the specified range to RAM. Do not convert any pages that may have
- * been DESTROYED, without our permission.
- */
-static inline int rsi_set_memory_range_protected_safe(phys_addr_t start,
-						      phys_addr_t end)
-{
-	return rsi_set_memory_range(start, end, RSI_RIPAS_RAM,
-				    RSI_NO_CHANGE_DESTROYED);
-}
-
-static inline int rsi_set_memory_range_shared(phys_addr_t start,
-					      phys_addr_t end)
-{
-	return rsi_set_memory_range(start, end, RSI_RIPAS_EMPTY,
-				    RSI_CHANGE_DESTROYED);
-}
-#endif /* __ASM_RSI_H_ */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index d2690c3ec52885..21fc3a3d25c91f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -34,7 +34,7 @@ obj-y			:= debug-monitors.o entry.o irq.o fpsimd.o		\
 			   cpufeature.o alternative.o cacheinfo.o		\
 			   smp.o smp_spin_table.o topology.o smccc-call.o	\
 			   syscall.o proton-pack.o idle.o patching.o pi/	\
-			   rsi.o jump_label.o
+			   jump_label.o
 
 obj-$(CONFIG_COMPAT)			+= sys32.o signal32.o			\
 					   sys_compat.o
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 29c6100f0c50b2..a707deba6ae701 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/acpi.h>
+#include <linux/arm-rsi-cmds.h>
 #include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
@@ -43,7 +44,6 @@
 #include <asm/cpu_ops.h>
 #include <asm/kasan.h>
 #include <asm/numa.h>
-#include <asm/rsi.h>
 #include <asm/scs.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index fbf215ecc7d061..2a8de20d2b447b 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -34,6 +34,8 @@
 #include <linux/acpi_iort.h>
 #include <linux/kmemleak.h>
 #include <linux/execmem.h>
+#include <linux/arm-rsi-cmds.h>
+
 
 #include <asm/boot.h>
 #include <asm/fixmap.h>
@@ -43,7 +45,6 @@
 #include <asm/kvm_host.h>
 #include <asm/memory.h>
 #include <asm/numa.h>
-#include <asm/rsi.h>
 #include <asm/sections.h>
 #include <asm/setup.h>
 #include <linux/sizes.h>
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index b7cc11e4fbfa65..62660bf520a8da 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -310,5 +310,6 @@ source "drivers/firmware/samsung/Kconfig"
 source "drivers/firmware/smccc/Kconfig"
 source "drivers/firmware/tegra/Kconfig"
 source "drivers/firmware/xilinx/Kconfig"
+source "drivers/firmware/arm_rmm/Kconfig"
 
 endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index be46f1e1dc77fa..196a650ccf025b 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -39,3 +39,4 @@ obj-y				+= samsung/
 obj-y				+= smccc/
 obj-y				+= tegra/
 obj-y				+= xilinx/
+obj-y				+= arm_rmm/
diff --git a/drivers/firmware/arm_rmm/Kconfig b/drivers/firmware/arm_rmm/Kconfig
new file mode 100644
index 00000000000000..e981e12fdbe6a8
--- /dev/null
+++ b/drivers/firmware/arm_rmm/Kconfig
@@ -0,0 +1,17 @@
+
+config ARCH_SUPPORTS_RMM
+	bool
+
+config ARM_RMM_RSI
+	bool "Realm Service Interface (RSI) Support"
+	depends on ARCH_SUPPORTS_RMM
+	default y
+	help
+	  Enable support for running Linux as a Realm guest under a Realm
+	  Management Monitor (RMM), as defined by the Arm Confidential
+	  Compute Architecture.
+
+	  The RMM exposes the Realm Service Interface (RSI) to Realm guests.
+	  Linux uses RSI to negotiate the interface version, obtain the Realm
+	  configuration, and manage the protected or shared state of guest
+	  memory.
diff --git a/drivers/firmware/arm_rmm/Makefile b/drivers/firmware/arm_rmm/Makefile
new file mode 100644
index 00000000000000..3708b37a9aafc6
--- /dev/null
+++ b/drivers/firmware/arm_rmm/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_ARM_RMM_RSI)	= rsi.o
diff --git a/arch/arm64/kernel/rsi.c b/drivers/firmware/arm_rmm/rsi.c
similarity index 99%
rename from arch/arm64/kernel/rsi.c
rename to drivers/firmware/arm_rmm/rsi.c
index 25ca75ce1a4dff..8e716f1c1e319d 100644
--- a/arch/arm64/kernel/rsi.c
+++ b/drivers/firmware/arm_rmm/rsi.c
@@ -8,11 +8,11 @@
 #include <linux/psci.h>
 #include <linux/swiotlb.h>
 #include <linux/platform_device.h>
+#include <linux/arm-rsi-cmds.h>
 
 #include <asm/io.h>
 #include <asm/mem_encrypt.h>
 #include <asm/pgtable.h>
-#include <asm/rsi.h>
 
 static struct realm_config config;
 
diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/arm-cca-guest/Kconfig
index 3f0f013f03f159..2582ebb36922ea 100644
--- a/drivers/virt/coco/arm-cca-guest/Kconfig
+++ b/drivers/virt/coco/arm-cca-guest/Kconfig
@@ -1,6 +1,6 @@
 config ARM_CCA_GUEST
 	tristate "Arm CCA Guest driver"
-	depends on ARM64
+	depends on ARM_RMM_RSI
 	select TSM_REPORTS
 	help
 	  The driver provides userspace interface to request and
diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
index 0eeddd1ff05b51..b741643d136476 100644
--- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
+++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
@@ -3,7 +3,8 @@
  * Copyright (C) 2023 ARM Ltd.
  */
 
-#include <linux/arm-smccc.h>
+#include <linux/arm-rsi-cmds.h>
+#include <linux/arm-smccc-rsi.h>
 #include <linux/cc_platform.h>
 #include <linux/kernel.h>
 #include <linux/device-id/platform.h>
@@ -12,8 +13,6 @@
 #include <linux/tsm.h>
 #include <linux/types.h>
 
-#include <asm/rsi.h>
-
  [Severity: High]
  This is a pre-existing issue, but is there a missing bounds check on the
  firmware-supplied length in this file?

  In arm_cca_attestation_continue(), the len value returned from the firmware
  (via rsi_attestation_token_continue) is added to info->offset without verifying
  that len <= size:

	  ret = rsi_attestation_token_continue(info->granule, info->offset, size,
					       &len);
	  info->offset += len;

  If the firmware returns a maliciously large len, info->offset will exceed
  RSI_GRANULE_SIZE (which is 4096 bytes). 

  Later in arm_cca_report_new(), this unvalidated info.offset is used as the
  memcpy() length:

	  if (WARN_ON(token_size + info.offset > max_size))
		  break;
	  memcpy(&token[token_size], buf, info.offset);

  The WARN_ON check only ensures it doesn't exceed max_size, but buf was
  allocated as exactly RSI_GRANULE_SIZE bytes. Can this lead to memcpy()
  reading past the end of buf and copying adjacent kernel memory into the
  attestation token returned to userspace?

Pre-existing, but seems worth fixing for robustness and avoiding
future LLM bot noise.

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>

-- 
Jason
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help