Re: [PATCH v22 02/10] firmware: arm_rmm: Check for RMI support at init
From: Suzuki K Poulose
Date: Wed Oct 14 2026 - 05:19:48 EST
On 14/10/2026 08:26, Gavin Shan wrote:
On 10/13/26 7:58 PM, Suzuki K Poulose wrote:
On 13/10/2026 04:53, Gavin Shan wrote:
Hi Suzuki,
On 10/2/26 4:14 PM, Suzuki K Poulose wrote:
From: Steven Price <steven.price@xxxxxxx>
Query the RMI version number and check if it is a compatible version.
All RMM feature registers are read and exposed for future code to
use. Also restrict the support to SMC conduit.
We only support this for Little Endian kernels, the Big Endian kernel
support is anyway marked BROKEN and is being removed.
Cc: Marc Zyngier <maz@xxxxxxxxxx>
Cc: Oliver Upton <oupton@xxxxxxxxxx>
Reviewed-by: Jonathan Cameron <jonathan.cameron@xxxxxxxxxxxxxxxx>
Reviewed-by: Gavin Shan <gshan@xxxxxxxxxx>
Reviewed-by: Catalin Marinas <catalin.marinas@xxxxxxx>
Tested-by: Gavin Shan <gshan@xxxxxxxxxx>
Signed-off-by: Steven Price <steven.price@xxxxxxx>
Co-developed-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@xxxxxxx>
---
[...]
---
MAINTAINERS | 2 +
arch/arm64/Kconfig | 1 +
arch/arm64/kernel/cpufeature.c | 1 +
arch/arm64/kvm/sys_regs.c | 2 +
drivers/firmware/Kconfig | 1 +
drivers/firmware/Makefile | 1 +
drivers/firmware/arm_rmm/Kconfig | 25 +++++++
drivers/firmware/arm_rmm/Makefile | 1 +
drivers/firmware/arm_rmm/rmi.c | 112 ++++++++++++++++++++++++++ ++++
include/linux/arm-rmi-cmds.h | 48 +++++++++++++
10 files changed, 194 insertions(+)
create mode 100644 drivers/firmware/arm_rmm/Kconfig
create mode 100644 drivers/firmware/arm_rmm/Makefile
create mode 100644 drivers/firmware/arm_rmm/rmi.c
create mode 100644 include/linux/arm-rmi-cmds.h
[...]
diff --git a/drivers/firmware/arm_rmm/rmi.c b/drivers/firmware/ arm_rmm/rmi.c
new file mode 100644
index 0000000000000..06f5392c982d2
--- /dev/null
+++ b/drivers/firmware/arm_rmm/rmi.c
@@ -0,0 +1,112 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2023-2026 ARM Ltd.
+ */
+
+#include <linux/arm-rmi-cmds.h>
+#include <linux/cpufeature.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+
+#include <asm/memory.h>
+#include <asm/pgtable-hwdef.h>
+
+/* RMM v2.0 defines RmiFeatureRegister0 to RmiFeatureRegister4. */
+static unsigned long rmi_feat_reg_cache[5] __ro_after_init;
+
+static int rmi_check_version(void)
+{
+ unsigned short version_major, version_minor;
+ unsigned long host_version = RMI_ABI_VERSION(RMI_ABI_MAJOR_VERSION,
+ RMI_ABI_MINOR_VERSION);
+ unsigned long aa64pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
+ struct arm_smccc_1_2_regs res = {
+ SMC_RMI_VERSION, host_version,
+ };
+
+ /* If RME isn't supported, then RMI can't be */
+ if (cpuid_feature_extract_unsigned_field(aa64pfr0, ID_AA64PFR0_EL1_RME_SHIFT) == 0)
+ return -ENXIO;
+
+ if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
+ return -ENXIO;
I think we need to ensure SMCCC version is v1.2 or a newer one here? arm_smccc_1_2_smc()
is immediately called by rmi_smccc_invoke() after this check.
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC ||
arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
We could. But I am wondering if that adds any value ? If the RMM
exists and responds to the RMI_ABI_VERSION, it must be so on a
platform with v1.2 or greater ? The extra check doesn't hurt.
It's required as documented in section "B1.1 overview" of RMM-spec-v2.0- bet3.
In the same section, there are more requirements regarding the SMCCC version
when SVE/SME are supported. I don't see a practical problem if the check is
missed since the combination of TF-A and TF-RMM are the only RMM-spec- v2.0-bet3
implementation (as I knew) where the SMCCC version has been set to v1.5 in the
'master' branch.
Reading the RMM spec again, DFNMZ lists how one can detect if the RMM
ABI is present. That specifies that the user checks for SMCCC
version >= 1.1, which we do by using arm_smccc_1_1_get_conduit().
Then checking the R{M,S}I_VERSION call is sufficient. So, I think
we are good here. Do you agree ?
Suzuki
Thanks,
Gavin
Suzuki
return -ENXIO;
Thanks,
Gavin
+
+ rmi_smccc_invoke(&res);
+ if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
+ return -ENXIO;
+
+ version_major = RMI_ABI_VERSION_GET_MAJOR(res.a1);
+ version_minor = RMI_ABI_VERSION_GET_MINOR(res.a1);
+
+ if (res.a0 != RMI_SUCCESS) {
+ unsigned short high_version_major, high_version_minor;
+
+ high_version_major = RMI_ABI_VERSION_GET_MAJOR(res.a2);
+ high_version_minor = RMI_ABI_VERSION_GET_MINOR(res.a2);
+
+ pr_err("Unsupported RMI ABI (v%d.%d - v%d.%d) we want v%d. %d\n",
+ version_major, version_minor,
+ high_version_major, high_version_minor,
+ RMI_ABI_MAJOR_VERSION,
+ RMI_ABI_MINOR_VERSION);
+ return -ENXIO;
+ }
+
+ pr_info("RMI ABI version %d.%d\n", version_major, version_minor);
+
+ return 0;
+}
+
[...]