[PATCH v6 3/4] firmware: smccc: arm-cca-guest: Bind the TSM provider to an SMCCC device

Suzuki K Poulose suzuki.poulose at arm.com
Thu Jun 4 03:24:05 PDT 2026


On 04/06/2026 10:21, Sudeep Holla wrote:
> On Wed, May 27, 2026 at 03:32:32PM +0530, Aneesh Kumar K.V (Arm) wrote:
>> The Arm CCA guest TSM provider currently binds through the arm-cca-dev
>> platform device. Like arm-smccc-trng, this device is not an independent
>> platform resource; it is a software representation of the RSI firmware
>> service discovered through SMCCC.
>>
>> Move RSI discovery into the SMCCC firmware driver. When the SMCCC conduit
>> is SMC and the RSI ABI version check succeeds, create an arm-rsi-dev SMCCC
>> device. Convert the Arm CCA guest TSM provider to an SMCCC driver so it
>> binds to that discovered RSI service and keeps module autoloading through
>> the SMCCC device id table.
>>
>> Keep the old arm-cca-dev platform-device registration for now. Userspace
>> has used that device as a Realm-guest indicator, so removing it is left to
>> a follow-up patch that adds a replacement sysfs ABI.
>>
>> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar at kernel.org>
>> ---
>>   arch/arm64/include/asm/rsi.h                  |  2 +-
>>   arch/arm64/kernel/rsi.c                       |  2 +-
>>   drivers/firmware/smccc/Makefile               |  4 ++
>>   drivers/firmware/smccc/rmm.c                  | 25 ++++++++
>>   drivers/firmware/smccc/rmm.h                  | 17 ++++++
>>   drivers/firmware/smccc/smccc.c                |  8 +++
>>   drivers/virt/coco/arm-cca-guest/Kconfig       |  1 +
>>   drivers/virt/coco/arm-cca-guest/Makefile      |  2 +
>>   .../{arm-cca-guest.c => arm-cca.c}            | 60 +++++++++----------
>>   9 files changed, 89 insertions(+), 32 deletions(-)
>>   create mode 100644 drivers/firmware/smccc/rmm.c
>>   create mode 100644 drivers/firmware/smccc/rmm.h
>>   rename drivers/virt/coco/arm-cca-guest/{arm-cca-guest.c => arm-cca.c} (85%)
>>
>> diff --git a/arch/arm64/include/asm/rsi.h b/arch/arm64/include/asm/rsi.h
>> index 88b50d660e85..2d2d363aaaee 100644
>> --- a/arch/arm64/include/asm/rsi.h
>> +++ b/arch/arm64/include/asm/rsi.h
>> @@ -10,7 +10,7 @@
>>   #include <linux/jump_label.h>
>>   #include <asm/rsi_cmds.h>
>>   
>> -#define RSI_PDEV_NAME "arm-cca-dev"
>> +#define RSI_DEV_NAME "arm-rsi-dev"
>>   
>>   DECLARE_STATIC_KEY_FALSE(rsi_present);
>>   
>> diff --git a/arch/arm64/kernel/rsi.c b/arch/arm64/kernel/rsi.c
>> index 92160f2e57ff..da440f71bb64 100644
>> --- a/arch/arm64/kernel/rsi.c
>> +++ b/arch/arm64/kernel/rsi.c
>> @@ -161,7 +161,7 @@ void __init arm64_rsi_init(void)
>>   }
>>   
>>   static struct platform_device rsi_dev = {
>> -	.name = RSI_PDEV_NAME,
>> +	.name = "arm-cca-dev",
>>   	.id = PLATFORM_DEVID_NONE
>>   };
>>   
>> diff --git a/drivers/firmware/smccc/Makefile b/drivers/firmware/smccc/Makefile
>> index 40d19144a860..33c850aaff4d 100644
>> --- a/drivers/firmware/smccc/Makefile
>> +++ b/drivers/firmware/smccc/Makefile
>> @@ -2,3 +2,7 @@
>>   #
>>   obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY)	+= smccc.o kvm_guest.o
>>   obj-$(CONFIG_ARM_SMCCC_SOC_ID)	+= soc_id.o
>> +
>> +ifeq ($(CONFIG_HAVE_ARM_SMCCC_DISCOVERY),y)
>> +obj-$(CONFIG_ARM64) += rmm.o
>> +endif
>> diff --git a/drivers/firmware/smccc/rmm.c b/drivers/firmware/smccc/rmm.c
>> new file mode 100644
>> index 000000000000..d572f47e955c
>> --- /dev/null
>> +++ b/drivers/firmware/smccc/rmm.c
>> @@ -0,0 +1,25 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/*
>> + * Copyright (C) 2026 Arm Limited
>> + */
>> +
>> +#include <linux/arm-smccc-bus.h>
>> +#include <linux/err.h>
>> +#include <linux/printk.h>
>> +
>> +#include "rmm.h"
>> +
>> +void __init register_rsi_device(void)
>> +{
>> +	unsigned long ret;
>> +
>> +	if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_SMC)
>> +		return;
>> +
>> +	ret = rsi_request_version(RSI_ABI_VERSION, NULL, NULL);
>> +	if (ret != RSI_SUCCESS)
>> +		return;
>> +
>> +	if (IS_ERR(arm_smccc_device_register(RSI_DEV_NAME)))
>> +		pr_err("%s: could not register device\n", RSI_DEV_NAME);
>> +}
> 
> OK, I had something else in my mind when I started looking at 1/4. I didn't
> expect each device added on this bus comes up with it's own way to enumerate
> it. IMO, it defeats the purpose of building the smccc bus. We may find the
> specs for each feature deviated a bit but we can have a generic probe
> IMO, let's try that before exploring per feature probe function.

I guess this is ideal, but see below.

> 
> I have a brief sketch of what I think we should aim for(uncompiled/untested)
> below. Let me know if that makes sense. I just based it on your bus code.
> 
> Regards,
> Sudeep
> 
> -->8
> 
> diff --git c/drivers/firmware/smccc/smccc.c w/drivers/firmware/smccc/smccc.c
> index 695c920a8087..450605ddfab6 100644
> --- c/drivers/firmware/smccc/smccc.c
> +++ w/drivers/firmware/smccc/smccc.c
> @@ -9,21 +9,58 @@
>   #include <linux/init.h>
>   #include <linux/arm-smccc.h>
>   #include <linux/kernel.h>
> -#include <linux/platform_device.h>
>   #include <linux/arm-smccc-bus.h>
>   #include <linux/idr.h>
>   #include <linux/slab.h>
> 
> -#include <asm/archrandom.h>
> -
>   static u32 smccc_version = ARM_SMCCC_VERSION_1_0;
>   static enum arm_smccc_conduit smccc_conduit = SMCCC_CONDUIT_NONE;
>   static DEFINE_IDA(arm_smccc_bus_id);
> 
> -bool __ro_after_init smccc_trng_available = false;
> +struct smccc_device_info {
> +       u32 func_id;
> +       bool requires_smc;
> +       unsigned long min_return;

Is this viable for all ? There may be additional restrictions around
the return values and further SMC calls ? Which brings us to call backs
and we kind of have a variant of that here.

Suzuki


> +       const char *device_name;
> +};
> +
> +bool __ro_after_init smccc_trng_available;
>   s32 __ro_after_init smccc_soc_id_version = SMCCC_RET_NOT_SUPPORTED;
>   s32 __ro_after_init smccc_soc_id_revision = SMCCC_RET_NOT_SUPPORTED;
> 
> +static const struct smccc_device_info smccc_devices[] __initconst = {
> +       {
> +               .func_id        = ARM_SMCCC_TRNG_VERSION,
> +               .requires_smc   = false,
> +               .min_return     = ARM_SMCCC_TRNG_MIN_VERSION,
> +               .device_name    = "arm-smccc-trng",
> +       },
> +};
> +
> +static bool __init
> +smccc_probe_smccc_device(const struct smccc_device_info *smccc_dev)
> +{
> +       struct arm_smccc_res res;
> +       unsigned long ret;
> +
> +       if (!IS_ENABLED(CONFIG_ARM64))
> +               return false;
> +
> +       if (smccc_conduit == SMCCC_CONDUIT_NONE)
> +               return false;
> +
> +       if (smccc_dev->requires_smc && smccc_conduit != SMCCC_CONDUIT_SMC)
> +               return false;
> +
> +       arm_smccc_1_1_invoke(smccc_dev->func_id, &res);
> +       ret = res.a0;
> +
> +       if ((s32)ret < 0)
> +               return false;
> +
> +       return ret >= smccc_dev->min_return;
> +}
> +
>   void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
>   {
>          struct arm_smccc_res res;
> @@ -31,7 +68,7 @@ void __init arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit)
>          smccc_version = version;
>          smccc_conduit = conduit;
> 
> -       smccc_trng_available = smccc_probe_trng();
> +       smccc_trng_available = smccc_probe_smccc_device(&smccc_devices[0]);
> 
>          if ((smccc_version >= ARM_SMCCC_VERSION_1_2) &&
>              (smccc_conduit != SMCCC_CONDUIT_NONE)) {
> @@ -241,14 +278,20 @@ subsys_initcall(arm_smccc_bus_init);
> 
>   static int __init smccc_devices_init(void)
>   {
> -       struct platform_device *pdev;
> -
> -       if (smccc_trng_available) {
> -               pdev = platform_device_register_simple("smccc_trng", -1,
> -                                                      NULL, 0);
> -               if (IS_ERR(pdev))
> -                       pr_err("smccc_trng: could not register device: %ld\n",
> -                              PTR_ERR(pdev));
> +       const struct smccc_device_info *smccc_dev;
> +       struct arm_smccc_device *sdev;
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(smccc_devices); i++) {
> +               smccc_dev = &smccc_devices[i];
> +
> +               if (!smccc_probe_smccc_device(smccc_dev))
> +                       continue;
> +
> +               sdev = arm_smccc_device_register(smccc_dev->device_name);
> +               if (IS_ERR(sdev))
> +                       pr_err("%s: could not register device: %ld\n",
> +                              smccc_dev->device_name, PTR_ERR(sdev));
>          }
> 
>          return 0;
> 




More information about the linux-arm-kernel mailing list