All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support
@ 2025-07-22 11:41 Oleksii Moisieiev
  2025-07-22 11:41 ` [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem Oleksii Moisieiev
                   ` (10 more replies)
  0 siblings, 11 replies; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

Inroducing V4 RFC patch series  on top of the Xen version 4.20-rc2
which includes implementation of the SCI SCMI SMC multi-agent support.

Patch 1 "xen/arm: add generic SCI subsystem"
- rebased and refactored
- introduced DEVICE_ARM_SCI DT device class and used for SCI drivers probing
instead of custom,
  linker sections based implementation.
- added SCI API for Dom0 DT handling, instead of manipulating with ARM arch
dom0 code directly.
- RFC changes in XEN_DOMCTL_assign_device OP processing
- Introduce arch_handle_passthrough_prop call to handle arm specific
nodes

Patch 2 "xen/arm: scmi-smc: update to be used under sci subsystem"
- update driver introduced by commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI
over SMC calls
handling layer") be used under sci subsystem.
- no functional changes in general

Patch 3 "xen/arm: scmi-smc: passthrough SCMI SMC to guest domain
This is new change which allows passthrough SCMI SMC, single agent interface to
guest domain
cover use case "thin Dom0 with guest domain, which serves as Driver domain".
See patch commit message for full description.

Patch 4 - docs: arm: add docs for SCMI over SMC calls forwarding
driver
- add documentation section for Simple Arm SCMI over SMC/HVC calls
forwarding driver.

Patch 6 - xen/domctl: extend XEN_DOMCTL_assign_device to handle not
only iommu
- add chainged handling of assigned DT devices to support
access-controller functionality through SCI framework.
Change was done in two parts:
 - update iommu_do_dt_domctl() to check for dt_device_is_protected()
 and not fail if DT device is not protected by IOMMU
 -add chained call to sci_do_domctl() to do_domctl()

Patch 9 - xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
- added "scmi-secondary-agents" and "#scmi-secondary-agent-cells"
  property to "xen,config" node in "chosen" to inform SCI SCMI
  multi-agent driver about available agents and their
  configuration. It defines <agent_id> to <smc-id,scmi_shm> map.
  This option is Xen specific as Xen is the only one entry in the
  system which need to know about SCMI multi-agent support and configuration.
- each guest using SCMI should be configured with SCMI agent_id, so SCMI
  FW can implement Agent-specific permission policy.
  -- dom0: dom0_scmi_agent_id=<agent_id> in Xen command line option
  -- toolstack: arm_sci = "type=scmi_smc_multiagent,agent_id=<agent_id>"
  -- dom0less: "xen,sci_type", "xen,sci_agent_id" properties in
"xen,domain" nodes.
- factored out SCMI generic definitions (re-usable)
- factored out SCMI shmem code (re-usable)
- the SCMI passthrough configuration for guest domains is similar to any other
HW passthrough cfg.

Patch 10 - docs: arm: add SCI SCMI SMC multi-agent driver docs
- add SCI SCMI SMC multi-agent driver documentation.

Add separate SCMI DT node for Xen management agent under "xen,config"
node under chosen.

All Xen-specific configuration provided under "/chosen" node. This
approach allows to isolate modifications to Host DT only under
"/chosen" node.

This approach provides the following device tree (DT)
parameters (placed under xen,config node):

- "scmi-secondary-agents": A Xen-specific parameter under the
  "/chosen" node, which describes the SCMI agent configuration for
  the domains.
- the SCMI configuration for Xen (privileged agent) and the shared
  memory configuration for all agents are provided under the "/chosen"
  node and are used strictly by Xen for its initial configuration.
- the scmi_shm and SCMI configuration for Dom0 are placed in the
  "/firmware/scmi" node so that they can be moved to Dom0 without
  any changes.

This configuration allows the use of Xen-specific nodes to provide
information strictly needed by Xen while using the default SCMI
configuration for Dom0 and other domains. As a result, no additional
bindings need to be introduced to the device tree.
This simplifies the Xen SCMI multi-agent configuration and utilizes
generic device tree bindings for the domains.

NOTE: Haven't added RB tags for patch 1 and 2 because rebase and some
minor changes were done.

Code can be found at:
https://github.com/oleksiimoisieiev/xen/tree/scmi_upstrv5

[1] RFC v2:
http://patchwork.kernel.org/project/xen-devel/cover/cover.1644341635.git.oleksii_moisieiev@epam.com/
[2] RFC v3:
https://patchwork.kernel.org/project/xen-devel/patch/20250311111618.1850927-1-grygorii_strashko@epam.com
SCMI spec:
https://developer.arm.com/documentation/den0056/e/?lang=en

SCMI bindings:
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml

Reference EL3 FW:
RPI5: https://github.com/xen-troops/arm-trusted-firmware/commits/rpi5_dev/
Renesas v4h:
https://github.com/GrygiriiS/arm-trusted-firmware/commits/rcar_gen4_v2.7_v4x-scmi_upd/

base-commit: dbe60f244c (Update Xen to 4.21, 2025-02-21)

Changes in v5:
- update Maintainers file. Set role as a Reviewer
- rebased on the latest master branch
- Introduce arch_handle_passthrough_prop call to handle arm specific nodes
- rename dom0_scmi_smc_passthrough to scmi_smc_passthrough
- rename dom0_scmi_smc_passthrough in documentation
- set error code to -ENXIO when iommu is disabled
- return -EINVAL if mediator without assign_dt_device was provided
- invert return code check for iommu_do_domctl in
XEN_DOMCTL_assign_device domctl processing to make cleaner code
- change -ENOTSUPP error code to -ENXIO in sci_do_domctl
- handle -ENXIO return comde of iommu_do_domctl
- leave !dt_device_is_protected check in iommu_do_dt_domctl to make
code work the same way it's done in "handle_device" call while
creating hwdom(dom0) and "handle_passthrough_prop" call for dom0less
creation
- drop return check from sci_assign_dt_device call as not needed
- do not return EINVAL when addign_dt_device is not set. That is
because this callback is optional and not implemented in single-agent driver
- move memcpy_toio/fromio to the generic place
- fix device-tree example format in booting.txt, added ";" after "}".
- update define in scmi-proto.h
- update define in scmi-shmem.h file
- scmi_assign_device - do not ignore -EOPNOTSUPP return
code of the do_smc_xfer
- remove overwriting agent_channel->agent_id after
SCMI_BASE_DISCOVER_AGENT call
- add multi-agent files to the MAINTAINERS
- add SCMI multi-agent description to the SUPPORT.md
- handle ARM_SMCCC_INVALID_PARAMETER return code and return -EINVAL
for smc call
- updated collect_agents function. Set agent_id parameter as optional
in scmi-secondary-agents device-tree property
- introduce "#scmi-secondary-agents-cells" parameter to set if
agent_id was provided
- reanme xen,scmi-secondary-agents property to scmi-secondary-agents
- move memcpu_toio/fromio for the generic place
- update Xen to get management channel from /chosen/xen,config node
- get hypervisor channnel from node instead of using hardcoded
- update handling scmi and shmem nodes for the domain
- Set multi-agent driver to support only Arm64
- rework multi-agent driver to leave Host Device-tree unmodified

Changes in v4:
- fix SPDX-License
- rename DEVICE_ARM_SCI DT device class to FIRMWARE_DEVICE
- move XEN_DOMCTL_assign_device code in separate patch
- Add documentation for SCI SCMI drivers
- xl.cfg doc
- fix comments from Stefano Stabellini
- fix toolstack code as sugested by Anthony PERARD
  - use MATCH_OPTION()
  - move arm_sci struct and cfg params in "arch_arm"
- add SCMI passthrough for dom0less case
- toolstack comments from Anthony PERARD
- added dom0less support
- added doc for "xen,scmi-secondary-agents"

Grygorii Strashko (5):
  xen/arm: scmi-smc: update to be used under sci subsystem
  xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
  docs: arm: add docs for SCMI over SMC calls forwarding driver
  xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
  docs: arm: add SCI SCMI SMC multi-agent driver docs

Oleksii Moisieiev (5):
  xen/arm: add generic SCI subsystem
  drivers: iommu: change error code when iommu is disabled
  xen: arm: smccc: add INVALID_PARAMETER error code
  lib/arm: Add I/O memory copy helpers
  xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver

 MAINTAINERS                                   |  10 +
 SUPPORT.md                                    |  11 +
 .../arm/firmware/arm-scmi.rst                 | 516 +++++++++++
 docs/hypervisor-guide/arm/index.rst           |   9 +
 docs/hypervisor-guide/index.rst               |   1 +
 docs/man/xl.cfg.5.pod.in                      |  47 +
 docs/misc/arm/device-tree/booting.txt         | 103 +++
 docs/misc/xen-command-line.pandoc             |  18 +
 tools/include/libxl.h                         |   5 +
 tools/libs/light/libxl_arm.c                  |  18 +
 tools/libs/light/libxl_types.idl              |  12 +
 tools/xl/xl_parse.c                           |  48 ++
 xen/arch/arm/device.c                         |   5 +
 xen/arch/arm/dom0less-build.c                 |  51 ++
 xen/arch/arm/domain.c                         |  12 +-
 xen/arch/arm/domain_build.c                   |  11 +-
 xen/arch/arm/firmware/Kconfig                 |  37 +-
 xen/arch/arm/firmware/Makefile                |   2 +
 xen/arch/arm/firmware/sci.c                   | 189 +++++
 xen/arch/arm/firmware/scmi-proto.h            | 164 ++++
 xen/arch/arm/firmware/scmi-shmem.c            | 112 +++
 xen/arch/arm/firmware/scmi-shmem.h            |  45 +
 xen/arch/arm/firmware/scmi-smc-multiagent.c   | 803 ++++++++++++++++++
 xen/arch/arm/firmware/scmi-smc.c              | 191 ++++-
 xen/arch/arm/include/asm/domain.h             |   5 +
 xen/arch/arm/include/asm/firmware/sci.h       | 214 +++++
 xen/arch/arm/include/asm/firmware/scmi-smc.h  |  41 -
 xen/arch/arm/include/asm/smccc.h              |   1 +
 xen/arch/arm/vsmc.c                           |   4 +-
 xen/common/device-tree/dom0less-build.c       |   4 +
 xen/common/domctl.c                           |  19 +
 xen/drivers/passthrough/device_tree.c         |   6 +
 xen/drivers/passthrough/iommu.c               |   2 +-
 xen/include/asm-generic/device.h              |   1 +
 xen/include/asm-generic/dom0less-build.h      |   9 +
 xen/include/public/arch-arm.h                 |   8 +
 xen/include/xen/lib/arm/io.h                  |  15 +
 xen/lib/Makefile                              |   1 +
 xen/lib/arm/Makefile                          |   1 +
 xen/lib/arm/io.c                              |  80 ++
 40 files changed, 2744 insertions(+), 87 deletions(-)
 create mode 100644 docs/hypervisor-guide/arm/firmware/arm-scmi.rst
 create mode 100644 docs/hypervisor-guide/arm/index.rst
 create mode 100644 xen/arch/arm/firmware/sci.c
 create mode 100644 xen/arch/arm/firmware/scmi-proto.h
 create mode 100644 xen/arch/arm/firmware/scmi-shmem.c
 create mode 100644 xen/arch/arm/firmware/scmi-shmem.h
 create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c
 create mode 100644 xen/arch/arm/include/asm/firmware/sci.h
 delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
 create mode 100644 xen/include/xen/lib/arm/io.h
 create mode 100644 xen/lib/arm/Makefile
 create mode 100644 xen/lib/arm/io.c

-- 
2.34.1


^ permalink raw reply	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-08-23  0:26   ` Stefano Stabellini
  2025-07-22 11:41 ` [RFC PATCH v5 01/10] xen/arm: add generic SCI subsystem Oleksii Moisieiev
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

From: Grygorii Strashko <grygorii_strashko@epam.com>

The introduced SCI (System Control Interface) subsystem provides unified
interface to integrate in Xen SCI drivers which adds support for ARM
firmware (EL3, SCP) based software interfaces (like SCMI) that are used in
system management. The SCI subsystem allows to add drivers for different FW
interfaces or have different drivers for the same FW interface (for example,
SCMI with different transports).

This patch updates SCMI over SMC calls handling layer, introduced by
commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls handling
layer"), to be SCI driver:
- convert to DT device;
- convert to SCI Xen interface.

There are no functional changes in general, the driver is just adopted
to the SCI interface.

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---



 xen/arch/arm/firmware/Kconfig                | 13 ++-
 xen/arch/arm/firmware/scmi-smc.c             | 93 +++++++++++---------
 xen/arch/arm/include/asm/firmware/scmi-smc.h | 41 ---------
 xen/arch/arm/vsmc.c                          |  5 +-
 xen/include/public/arch-arm.h                |  1 +
 5 files changed, 64 insertions(+), 89 deletions(-)
 delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h

diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
index fc7918c7fc..bbf88fbb9a 100644
--- a/xen/arch/arm/firmware/Kconfig
+++ b/xen/arch/arm/firmware/Kconfig
@@ -8,9 +8,18 @@ config ARM_SCI
 
 menu "Firmware Drivers"
 
+choice
+	prompt "ARM SCI driver type"
+	default SCMI_SMC
+	help
+	Choose which ARM SCI driver to enable.
+
+config ARM_SCI_NONE
+	bool "none"
+
 config SCMI_SMC
 	bool "Forward SCMI over SMC calls from hwdom to EL3 firmware"
-	default y
+	select ARM_SCI
 	help
 	  This option enables basic awareness for SCMI calls using SMC as
 	  doorbell mechanism and Shared Memory for transport ("arm,scmi-smc"
@@ -18,4 +27,6 @@ config SCMI_SMC
 	  firmware node is used to trap and forward corresponding SCMI SMCs
 	  to firmware running at EL3, for calls coming from the hardware domain.
 
+endchoice
+
 endmenu
diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c
index 33473c04b1..13d1137592 100644
--- a/xen/arch/arm/firmware/scmi-smc.c
+++ b/xen/arch/arm/firmware/scmi-smc.c
@@ -9,6 +9,7 @@
  * Copyright 2024 NXP
  */
 
+#include <asm/device.h>
 #include <xen/acpi.h>
 #include <xen/device_tree.h>
 #include <xen/errno.h>
@@ -16,12 +17,11 @@
 #include <xen/sched.h>
 #include <xen/types.h>
 
+#include <asm/firmware/sci.h>
 #include <asm/smccc.h>
-#include <asm/firmware/scmi-smc.h>
 
 #define SCMI_SMC_ID_PROP   "arm,smc-id"
 
-static bool __ro_after_init scmi_enabled;
 static uint32_t __ro_after_init scmi_smc_id;
 
 /*
@@ -41,14 +41,11 @@ static bool scmi_is_valid_smc_id(uint32_t fid)
  *
  * Returns true if SMC was handled (regardless of response), false otherwise.
  */
-bool scmi_handle_smc(struct cpu_user_regs *regs)
+static bool scmi_handle_smc(struct cpu_user_regs *regs)
 {
     uint32_t fid = (uint32_t)get_user_reg(regs, 0);
     struct arm_smccc_res res;
 
-    if ( !scmi_enabled )
-        return false;
-
     if ( !scmi_is_valid_smc_id(fid) )
         return false;
 
@@ -78,49 +75,45 @@ bool scmi_handle_smc(struct cpu_user_regs *regs)
     return true;
 }
 
-static int __init scmi_check_smccc_ver(void)
+static int scmi_smc_domain_init(struct domain *d,
+                                struct xen_domctl_createdomain *config)
 {
-    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
-    {
-        printk(XENLOG_WARNING
-               "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
-        return -ENOSYS;
-    }
+    if ( !is_hardware_domain(d) )
+        return 0;
 
+    d->arch.sci_enabled = true;
+    printk(XENLOG_DEBUG "SCMI: %pd init\n", d);
     return 0;
 }
 
-static int __init scmi_dt_init_smccc(void)
+static void scmi_smc_domain_destroy(struct domain *d)
 {
-    static const struct dt_device_match scmi_ids[] __initconst =
-    {
-        /* We only support "arm,scmi-smc" binding for now */
-        DT_MATCH_COMPATIBLE("arm,scmi-smc"),
-        { /* sentinel */ },
-    };
-    const struct dt_device_node *scmi_node;
-    int ret;
+    if ( !is_hardware_domain(d) )
+        return;
 
-    /* If no SCMI firmware node found, fail silently as it's not mandatory */
-    scmi_node = dt_find_matching_node(NULL, scmi_ids);
-    if ( !scmi_node )
-        return -EOPNOTSUPP;
+    printk(XENLOG_DEBUG "SCMI: %pd destroy\n", d);
+}
 
-    ret = dt_property_read_u32(scmi_node, SCMI_SMC_ID_PROP, &scmi_smc_id);
-    if ( !ret )
+static int __init scmi_check_smccc_ver(void)
+{
+    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
     {
-        printk(XENLOG_ERR "SCMI: No valid \"%s\" property in \"%s\" DT node\n",
-               SCMI_SMC_ID_PROP, scmi_node->full_name);
-        return -ENOENT;
+        printk(XENLOG_WARNING
+               "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
+        return -ENOSYS;
     }
 
-    scmi_enabled = true;
-
     return 0;
 }
 
+static const struct sci_mediator_ops scmi_smc_ops = {
+    .handle_call = scmi_handle_smc,
+    .domain_init = scmi_smc_domain_init,
+    .domain_destroy = scmi_smc_domain_destroy,
+};
+
 /* Initialize the SCMI layer based on SMCs and Device-tree */
-static int __init scmi_init(void)
+static int __init scmi_dom0_init(struct dt_device_node *dev, const void *data)
 {
     int ret;
 
@@ -134,22 +127,36 @@ static int __init scmi_init(void)
     if ( ret )
         return ret;
 
-    ret = scmi_dt_init_smccc();
-    if ( ret == -EOPNOTSUPP )
-        return ret;
+    ret = dt_property_read_u32(dev, SCMI_SMC_ID_PROP, &scmi_smc_id);
+    if ( !ret )
+    {
+        printk(XENLOG_ERR "SCMI: No valid \"%s\" property in \"%s\" DT node\n",
+               SCMI_SMC_ID_PROP, dt_node_full_name(dev));
+        return -ENOENT;
+    }
+
+    ret = sci_register(&scmi_smc_ops);
     if ( ret )
-        goto err;
+    {
+        printk(XENLOG_ERR "SCMI: mediator already registered (ret = %d)\n",
+               ret);
+        return ret;
+    }
 
     printk(XENLOG_INFO "Using SCMI with SMC ID: 0x%x\n", scmi_smc_id);
 
     return 0;
-
- err:
-    printk(XENLOG_ERR "SCMI: Initialization failed (ret = %d)\n", ret);
-    return ret;
 }
 
-__initcall(scmi_init);
+static const struct dt_device_match scmi_smc_match[] __initconst = {
+    DT_MATCH_COMPATIBLE("arm,scmi-smc"),
+    { /* sentinel */ },
+};
+
+DT_DEVICE_START(scmi_smc, "SCMI SMC DOM0", DEVICE_FIRMWARE)
+    .dt_match = scmi_smc_match,
+    .init = scmi_dom0_init,
+DT_DEVICE_END
 
 /*
  * Local variables:
diff --git a/xen/arch/arm/include/asm/firmware/scmi-smc.h b/xen/arch/arm/include/asm/firmware/scmi-smc.h
deleted file mode 100644
index 6b1a164a40..0000000000
--- a/xen/arch/arm/include/asm/firmware/scmi-smc.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * xen/arch/arm/include/asm/firmware/scmi-smc.h
- *
- * ARM System Control and Management Interface (SCMI) over SMC
- * Generic handling layer
- *
- * Andrei Cherechesu <andrei.cherechesu@nxp.com>
- * Copyright 2024 NXP
- */
-
-#ifndef __ASM_SCMI_SMC_H__
-#define __ASM_SCMI_SMC_H__
-
-#include <xen/types.h>
-
-struct cpu_user_regs;
-
-#ifdef CONFIG_SCMI_SMC
-
-bool scmi_handle_smc(struct cpu_user_regs *regs);
-
-#else
-
-static inline bool scmi_handle_smc(struct cpu_user_regs *regs)
-{
-    return false;
-}
-
-#endif /* CONFIG_SCMI_SMC */
-
-#endif /* __ASM_SCMI_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c
index 2469738fcc..78d5bdf56f 100644
--- a/xen/arch/arm/vsmc.c
+++ b/xen/arch/arm/vsmc.c
@@ -21,7 +21,6 @@
 #include <asm/traps.h>
 #include <asm/vpsci.h>
 #include <asm/platform.h>
-#include <asm/firmware/scmi-smc.h>
 
 /* Number of functions currently supported by Hypervisor Service. */
 #define XEN_SMCCC_FUNCTION_COUNT 3
@@ -233,7 +232,7 @@ static bool handle_sip(struct cpu_user_regs *regs)
     if ( platform_smc(regs) )
         return true;
 
-    return scmi_handle_smc(regs);
+    return sci_handle_call(regs);
 }
 
 /*
@@ -301,8 +300,6 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs)
             break;
         case ARM_SMCCC_OWNER_SIP:
             handled = handle_sip(regs);
-            if ( !handled )
-                handled = sci_handle_call(regs);
             break;
         case ARM_SMCCC_OWNER_TRUSTED_APP ... ARM_SMCCC_OWNER_TRUSTED_APP_END:
         case ARM_SMCCC_OWNER_TRUSTED_OS ... ARM_SMCCC_OWNER_TRUSTED_OS_END:
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index 55eed9992c..095b1a23e3 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -328,6 +328,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 #define XEN_DOMCTL_CONFIG_TEE_FFA       2
 
 #define XEN_DOMCTL_CONFIG_ARM_SCI_NONE      0
+#define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC  1
 
 struct xen_arch_domainconfig {
     /* IN/OUT */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 01/10] xen/arm: add generic SCI subsystem
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
  2025-07-22 11:41 ` [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-08-23  0:26   ` Stefano Stabellini
  2025-07-22 11:41 ` [RFC PATCH v5 04/10] docs: arm: add docs for SCMI over SMC calls forwarding driver Oleksii Moisieiev
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

This patch adds the basic framework for ARM SCI mediator. SCI is System
Control Interface, which is designed to redirect requests from the Domains
to ARM specific Firmware (for example SCMI). This will allow the devices,
passed-through to the different Domains, to access to the System resources
(such as clocks/resets etc) by sending requests to the firmware.

ARM SCI subsystem allows to implement different SCI drivers to handle
specific ARM firmware interfaces (like ARM SCMI) and mediate requests
-between the Domains and the Firmware. Also it allows SCI drivers to perform
proper action during Domain creation/destruction which is vital for
handling use cases like Domain reboot.

This patch introduces new DEVICE_FIRMWARE device subclass for probing SCI
drivers basing on device tree, SCI drivers register itself with
DT_DEVICE_START/END macro. On init - the SCI drivers should register its
SCI ops with sci_register(). Only one SCI driver can be supported.

At run-time, the following SCI API calls are introduced:

- sci_domain_sanitise_config() called from arch_sanitise_domain_config()
- sci_domain_init() called from arch_domain_create()
- sci_relinquish_resources() called from domain_relinquish_resources()
- sci_domain_destroy() called from arch_domain_destroy()
- sci_handle_call() called from vsmccc_handle_call()
- sci_dt_handle_node()
- sci_dt_finalize() called from handle_node() (Dom0 DT)

Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
---

Changes in v5:
- update Maintainers file. Set role as a Reviewer
- rebased on the latest master branch
- Introduce arch_handle_passthrough_prop call to handle arm specific nodes

Changes in v4:
- fix SPDX-License
- rename DEVICE_ARM_SCI DT device class to FIRMWARE_DEVICE
- move XEN_DOMCTL_assign_device code in separate patch
- Add documentation for SCI SCMI drivers

 MAINTAINERS                              |   6 +
 xen/arch/arm/device.c                    |   5 +
 xen/arch/arm/dom0less-build.c            |   8 +
 xen/arch/arm/domain.c                    |  12 +-
 xen/arch/arm/domain_build.c              |   8 +
 xen/arch/arm/firmware/Kconfig            |   8 +
 xen/arch/arm/firmware/Makefile           |   1 +
 xen/arch/arm/firmware/sci.c              | 154 +++++++++++++++++
 xen/arch/arm/include/asm/domain.h        |   5 +
 xen/arch/arm/include/asm/firmware/sci.h  | 200 +++++++++++++++++++++++
 xen/arch/arm/vsmc.c                      |   3 +
 xen/common/device-tree/dom0less-build.c  |   4 +
 xen/include/asm-generic/device.h         |   1 +
 xen/include/asm-generic/dom0less-build.h |   9 +
 xen/include/public/arch-arm.h            |   4 +
 15 files changed, 427 insertions(+), 1 deletion(-)
 create mode 100644 xen/arch/arm/firmware/sci.c
 create mode 100644 xen/arch/arm/include/asm/firmware/sci.h

diff --git a/MAINTAINERS b/MAINTAINERS
index c4886c1159..31dbba54bb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -509,6 +509,12 @@ R:	George Dunlap <gwd@xenproject.org>
 S:	Supported
 F:	xen/common/sched/
 
+SCI MEDIATORS
+R:	Oleksii Moisieiev <oleksii_moisieiev@epam.com>
+S:	Supported
+F:	xen/arch/arm/firmware/sci.c
+F:	xen/arch/arm/include/asm/firmware/sci.h
+
 SEABIOS UPSTREAM
 M:	Wei Liu <wl@xen.org>
 S:	Supported
diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
index 11523750ae..74b54cad34 100644
--- a/xen/arch/arm/device.c
+++ b/xen/arch/arm/device.c
@@ -13,6 +13,7 @@
 #include <xen/iocap.h>
 #include <xen/lib.h>
 
+#include <asm/firmware/sci.h>
 #include <asm/setup.h>
 
 int map_irq_to_domain(struct domain *d, unsigned int irq,
@@ -303,6 +304,10 @@ int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt,
                 return res;
             }
         }
+
+        res = sci_assign_dt_device(d, dev);
+        if ( res )
+            return res;
     }
 
     res = map_device_irqs_to_domain(d, dev, own_device, irq_ranges);
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index 4b285cff5e..2a0bf817ba 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -22,6 +22,7 @@
 #include <asm/arm64/sve.h>
 #include <asm/dom0less-build.h>
 #include <asm/domain_build.h>
+#include <asm/firmware/sci.h>
 #include <asm/grant_table.h>
 #include <asm/setup.h>
 
@@ -272,6 +273,12 @@ int __init init_vuart(struct domain *d, struct kernel_info *kinfo,
     return rc;
 }
 
+int __init arch_handle_passthrough_prop(struct kernel_info *kinfo,
+                                        struct dt_device_node *node)
+{
+    return sci_assign_dt_device(kinfo->d, node);
+}
+
 void __init arch_create_domUs(struct dt_device_node *node,
                        struct xen_domctl_createdomain *d_cfg,
                        unsigned int flags)
@@ -280,6 +287,7 @@ void __init arch_create_domUs(struct dt_device_node *node,
 
     d_cfg->arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
     d_cfg->flags |= XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap;
+    d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
 
     if ( !dt_property_read_u32(node, "nr_spis", &d_cfg->arch.nr_spis) )
     {
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 79a144e61b..d0146da5da 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -24,6 +24,7 @@
 #include <asm/platform.h>
 #include <asm/procinfo.h>
 #include <asm/regs.h>
+#include <asm/firmware/sci.h>
 #include <asm/tee/tee.h>
 #include <asm/vfp.h>
 #include <asm/vgic.h>
@@ -699,7 +700,7 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
-    return 0;
+    return sci_domain_sanitise_config(config);
 }
 
 int arch_domain_create(struct domain *d,
@@ -791,6 +792,9 @@ int arch_domain_create(struct domain *d,
     d->arch.sve_vl = config->arch.sve_vl;
 #endif
 
+    if ( (rc = sci_domain_init(d, config)) != 0 )
+        goto fail;
+
     return 0;
 
 fail:
@@ -851,6 +855,7 @@ void arch_domain_destroy(struct domain *d)
     domain_vgic_free(d);
     domain_vuart_free(d);
     free_xenheap_page(d->shared_info);
+    sci_domain_destroy(d);
 #ifdef CONFIG_ACPI
     free_xenheap_pages(d->arch.efi_acpi_table,
                        get_order_from_bytes(d->arch.efi_acpi_len));
@@ -1044,6 +1049,7 @@ enum {
     PROG_p2m_root,
     PROG_p2m,
     PROG_p2m_pool,
+    PROG_sci,
     PROG_done,
 };
 
@@ -1103,6 +1109,10 @@ int domain_relinquish_resources(struct domain *d)
         ret = relinquish_p2m_mapping(d);
         if ( ret )
             return ret;
+    PROGRESS(sci):
+        ret = sci_relinquish_resources(d);
+        if ( ret )
+            return ret;
 
     PROGRESS(p2m_root):
         /*
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index ed668bd61c..92039cf213 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -26,6 +26,7 @@
 #include <asm/setup.h>
 #include <asm/tee/tee.h>
 #include <asm/pci.h>
+#include <asm/firmware/sci.h>
 #include <asm/platform.h>
 #include <asm/psci.h>
 #include <asm/setup.h>
@@ -1639,6 +1640,9 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
         return 0;
     }
 
+    if ( sci_dt_handle_node(d, node) )
+        return 0;
+
     /*
      * The vGIC does not support routing hardware PPIs to guest. So
      * we need to skip any node using PPIs.
@@ -1739,6 +1743,10 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
         if ( res )
             return res;
 
+        res = sci_dt_finalize(d, kinfo->fdt);
+        if ( res )
+            return res;
+
         /*
          * Create a second memory node to store the ranges covering
          * reserved-memory regions.
diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
index 817da745fd..fc7918c7fc 100644
--- a/xen/arch/arm/firmware/Kconfig
+++ b/xen/arch/arm/firmware/Kconfig
@@ -1,3 +1,11 @@
+config ARM_SCI
+	bool
+	depends on ARM
+	help
+	  This option enables generic Arm SCI (System Control Interface) mediators
+	  support. It allows domains to control system resources via one of
+	  Arm SCI mediators drivers implemented in XEN, like SCMI.
+
 menu "Firmware Drivers"
 
 config SCMI_SMC
diff --git a/xen/arch/arm/firmware/Makefile b/xen/arch/arm/firmware/Makefile
index a5e4542666..71bdefc24a 100644
--- a/xen/arch/arm/firmware/Makefile
+++ b/xen/arch/arm/firmware/Makefile
@@ -1 +1,2 @@
+obj-$(CONFIG_ARM_SCI) += sci.o
 obj-$(CONFIG_SCMI_SMC) += scmi-smc.o
diff --git a/xen/arch/arm/firmware/sci.c b/xen/arch/arm/firmware/sci.c
new file mode 100644
index 0000000000..e1522e10e2
--- /dev/null
+++ b/xen/arch/arm/firmware/sci.c
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Generic part of the SCI (System Control Interface) subsystem.
+ *
+ * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
+ * Copyright (c) 2025 EPAM Systems
+ */
+
+#include <xen/acpi.h>
+#include <xen/errno.h>
+#include <xen/init.h>
+#include <xen/sched.h>
+#include <xen/types.h>
+
+#include <asm/firmware/sci.h>
+
+static const struct sci_mediator_ops __read_mostly *cur_mediator;
+
+int sci_register(const struct sci_mediator_ops *ops)
+{
+    if ( cur_mediator )
+        return -EEXIST;
+
+    if ( !ops->domain_init || !ops->domain_destroy || !ops->handle_call )
+        return -EINVAL;
+
+    cur_mediator = ops;
+
+    return 0;
+};
+
+bool sci_handle_call(struct cpu_user_regs *args)
+{
+    if ( unlikely(!cur_mediator) )
+        return false;
+
+    return cur_mediator->handle_call(args);
+}
+
+int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config)
+{
+    if ( !cur_mediator )
+        return 0;
+
+    return cur_mediator->domain_init(d, config);
+}
+
+int sci_domain_sanitise_config(struct xen_domctl_createdomain *config)
+{
+    if ( !cur_mediator )
+        return 0;
+
+    if ( !cur_mediator->domain_sanitise_config )
+        return 0;
+
+    return cur_mediator->domain_sanitise_config(config);
+}
+
+void sci_domain_destroy(struct domain *d)
+{
+    if ( !cur_mediator )
+        return;
+
+    cur_mediator->domain_destroy(d);
+}
+
+int sci_relinquish_resources(struct domain *d)
+{
+    if ( !cur_mediator )
+        return 0;
+
+    if ( !cur_mediator->relinquish_resources )
+        return 0;
+
+    return cur_mediator->relinquish_resources(d);
+}
+
+bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node)
+{
+    if ( !cur_mediator )
+        return 0;
+
+    if ( !cur_mediator->dom0_dt_handle_node )
+        return 0;
+
+    return cur_mediator->dom0_dt_handle_node(d, node);
+}
+
+int sci_dt_finalize(struct domain *d, void *fdt)
+{
+    if ( !cur_mediator )
+        return 0;
+
+    if ( !cur_mediator->dom0_dt_finalize )
+        return 0;
+
+    return cur_mediator->dom0_dt_finalize(d, fdt);
+}
+
+int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev)
+{
+    struct dt_phandle_args ac_spec;
+    int index = 0;
+    int ret;
+
+    if ( !cur_mediator )
+        return 0;
+
+    if ( !cur_mediator->assign_dt_device )
+        return 0;
+
+    while ( !dt_parse_phandle_with_args(dev, "access-controllers",
+                                        "#access-controller-cells", index,
+                                        &ac_spec) )
+    {
+        printk(XENLOG_DEBUG "sci: assign device %s to %pd\n",
+               dt_node_full_name(dev), d);
+
+        ret = cur_mediator->assign_dt_device(d, &ac_spec);
+        if ( ret )
+            return ret;
+
+        index++;
+    }
+
+    return 0;
+}
+
+static int __init sci_init(void)
+{
+    struct dt_device_node *np;
+    unsigned int num_sci = 0;
+    int rc;
+
+    dt_for_each_device_node(dt_host, np)
+    {
+        rc = device_init(np, DEVICE_FIRMWARE, NULL);
+        if ( !rc && num_sci )
+        {
+            printk(XENLOG_ERR
+                   "SCMI: Only one SCI controller is supported. found second %s\n",
+                   np->name);
+            return -EOPNOTSUPP;
+        }
+        else if ( !rc )
+            num_sci++;
+        else if ( rc != -EBADF && rc != -ENODEV )
+            return rc;
+    }
+
+    return 0;
+}
+
+__initcall(sci_init);
diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
index a3487ca713..af3e168374 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -120,6 +120,11 @@ struct arch_domain
 #ifdef CONFIG_TEE
     void *tee;
 #endif
+#ifdef CONFIG_ARM_SCI
+    bool sci_enabled;
+    /* ARM SCI driver's specific data */
+    void *sci_data;
+#endif
 
 }  __cacheline_aligned;
 
diff --git a/xen/arch/arm/include/asm/firmware/sci.h b/xen/arch/arm/include/asm/firmware/sci.h
new file mode 100644
index 0000000000..71fb54852e
--- /dev/null
+++ b/xen/arch/arm/include/asm/firmware/sci.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Generic ARM SCI (System Control Interface) subsystem.
+ *
+ * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
+ * Copyright (c) 2025 EPAM Systems
+ */
+
+#ifndef __ASM_ARM_SCI_H
+#define __ASM_ARM_SCI_H
+
+#include <xen/lib.h>
+#include <xen/types.h>
+#include <xen/device_tree.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+
+#ifdef CONFIG_ARM_SCI
+
+struct sci_mediator_ops {
+    /*
+     * Called during domain construction. If it is requested to enable
+     * SCI support, so SCI driver can create own structures for the new domain
+     * and inform firmware about new domain (if required).
+     * Mandatory.
+     */
+    int (*domain_init)(struct domain *d,
+                       struct xen_domctl_createdomain *config);
+
+    /*
+     * Called during domain construction. The SCI driver uses
+     * it to sanitize domain SCI configuration parameters.
+     * Optional.
+     */
+    int (*domain_sanitise_config)(struct xen_domctl_createdomain *config);
+
+    /*
+     * Called during domain destruction, releases all resources, that
+     * were allocated for domain.
+     * Mandatory.
+     */
+    void (*domain_destroy)(struct domain *d);
+
+    /*
+     * Called during domain destruction to relinquish resources used
+     * by SCI driver itself and request resources releasing from firmware.
+     * Optional.
+     */
+    int (*relinquish_resources)(struct domain *d);
+
+    /* SMC/HVC Handle callback */
+    bool (*handle_call)(struct cpu_user_regs *regs);
+
+    /*
+     * Dom0 DT nodes handling callback so SCI driver can detect DT nodes it
+     * need to handle and decide if those nodes need to be provided to Dom0.
+     * Optional.
+     */
+    bool (*dom0_dt_handle_node)(struct domain *d, struct dt_device_node *node);
+
+    /*
+     * SCI driver callback called at the end of Dom0 DT generation, so
+     * it can perform steps to modify DT to enable/disable SCI
+     * functionality for Dom0.
+     */
+    int (*dom0_dt_finalize)(struct domain *d, void *fdt);
+
+    /*
+     * SCI driver callback called when DT device is passed through to guest,
+     * so SCI driver can enable device access to the domain if SCI FW provides
+     * Device specific access control functionality.
+     * Optional.
+     */
+    int (*assign_dt_device)(struct domain *d, struct dt_phandle_args *ac_spec);
+};
+
+
+static inline bool sci_domain_is_enabled(struct domain *d)
+{
+    return d->arch.sci_enabled;
+}
+
+/*
+ * Register SCI subsystem ops.
+ *
+ * Register SCI drivers operation and so enable SCI functionality.
+ * Only one SCI driver is supported.
+ */
+int sci_register(const struct sci_mediator_ops *ops);
+
+/*
+ * Initialize SCI functionality for domain if configured.
+ *
+ * Initialization routine to enable SCI functionality for the domain.
+ * The SCI configuration data and decision about enabling SCI functionality
+ * for the domain is SCI driver specific.
+ */
+int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config);
+
+/*
+ * Sanitise domain configuration parameters.
+ *
+ */
+int sci_domain_sanitise_config(struct xen_domctl_createdomain *config);
+
+/*
+ * Destroy SCI domain instance.
+ */
+void sci_domain_destroy(struct domain *d);
+
+/*
+ * Free resources assigned to the certain domain.
+ */
+int sci_relinquish_resources(struct domain *d);
+
+/*
+ * SMC/HVC Handle callback.
+ *
+ * SCI driver acts as SMC/HVC server for the registered domains and
+ * does redirection of the domain calls to the SCI firmware,
+ * such as ARM TF-A or similar.
+ */
+bool sci_handle_call(struct cpu_user_regs *regs);
+
+/*
+ * Dom0 DT nodes handling function.
+ *
+ * Allows SCI driver to detect DT nodes it need to handle and decide if
+ * those nodes need to be provided to Dom0.
+ */
+bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node);
+
+/*
+ * Dom0 DT generation finalize.
+ *
+ * Called at the end of Dom0 DT generation, so SCI driver can perform steps
+ * to modify DT to enable/disable SCI functionality for Dom0.
+ */
+int sci_dt_finalize(struct domain *d, void *fdt);
+
+/*
+ * Assign DT device to domain.
+ *
+ * Called when DT device is passed through to guest, so SCI driver can enable
+ * device access to the domain if SCI FW provides "Device specific access
+ * control" functionality.
+ */
+int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev);
+#else
+
+static inline bool sci_domain_is_enabled(struct domain *d)
+{
+    return false;
+}
+
+static inline int sci_domain_init(struct domain *d,
+                                  struct xen_domctl_createdomain *config)
+{
+    return 0;
+}
+
+static inline int
+sci_domain_sanitise_config(struct xen_domctl_createdomain *config)
+{
+    return 0;
+}
+
+static inline void sci_domain_destroy(struct domain *d)
+{}
+
+static inline int sci_relinquish_resources(struct domain *d)
+{
+    return 0;
+}
+
+static inline bool sci_handle_call(struct cpu_user_regs *args)
+{
+    return false;
+}
+
+static inline bool sci_dt_handle_node(struct domain *d,
+                                      struct dt_device_node *node)
+{
+    return false;
+}
+
+static inline int sci_dt_finalize(struct domain *d, void *fdt)
+{
+    return false;
+}
+
+static inline int sci_assign_dt_device(struct domain *d,
+                                       struct dt_device_node *dev)
+{
+    return 0;
+}
+
+#endif /* CONFIG_ARM_SCI */
+
+#endif /* __ASM_ARM_SCI_H */
diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c
index 6081f14ed0..2469738fcc 100644
--- a/xen/arch/arm/vsmc.c
+++ b/xen/arch/arm/vsmc.c
@@ -12,6 +12,7 @@
 #include <public/arch-arm/smccc.h>
 #include <asm/cpuerrata.h>
 #include <asm/cpufeature.h>
+#include <asm/firmware/sci.h>
 #include <asm/monitor.h>
 #include <asm/regs.h>
 #include <asm/smccc.h>
@@ -300,6 +301,8 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs)
             break;
         case ARM_SMCCC_OWNER_SIP:
             handled = handle_sip(regs);
+            if ( !handled )
+                handled = sci_handle_call(regs);
             break;
         case ARM_SMCCC_OWNER_TRUSTED_APP ... ARM_SMCCC_OWNER_TRUSTED_APP_END:
         case ARM_SMCCC_OWNER_TRUSTED_OS ... ARM_SMCCC_OWNER_TRUSTED_OS_END:
diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c
index 0012046574..f29656a27e 100644
--- a/xen/common/device-tree/dom0less-build.c
+++ b/xen/common/device-tree/dom0less-build.c
@@ -228,6 +228,10 @@ static int __init handle_passthrough_prop(struct kernel_info *kinfo,
     if ( res < 0 )
         return res;
 
+    res = arch_handle_passthrough_prop(kinfo, node);
+    if ( res )
+        return res;
+
     /* If xen_force, we allow assignment of devices without IOMMU protection. */
     if ( xen_force && !dt_device_is_protected(node) )
         return 0;
diff --git a/xen/include/asm-generic/device.h b/xen/include/asm-generic/device.h
index 1acd1ba1d8..e96c5558c2 100644
--- a/xen/include/asm-generic/device.h
+++ b/xen/include/asm-generic/device.h
@@ -18,6 +18,7 @@ enum device_class
     DEVICE_IOMMU,
     DEVICE_INTERRUPT_CONTROLLER,
     DEVICE_PCI_HOSTBRIDGE,
+    DEVICE_FIRMWARE,
     /* Use for error */
     DEVICE_UNKNOWN,
 };
diff --git a/xen/include/asm-generic/dom0less-build.h b/xen/include/asm-generic/dom0less-build.h
index e0ad0429ec..1c56441c33 100644
--- a/xen/include/asm-generic/dom0less-build.h
+++ b/xen/include/asm-generic/dom0less-build.h
@@ -61,6 +61,9 @@ void set_domain_type(struct domain *d, struct kernel_info *kinfo);
 int init_intc_phandle(struct kernel_info *kinfo, const char *name,
                       const int node_next, const void *pfdt);
 
+int arch_handle_passthrough_prop(struct kernel_info *kinfo,
+                                 struct dt_device_node *node);
+
 #else /* !CONFIG_DOM0LESS_BOOT */
 
 static inline void create_domUs(void) {}
@@ -70,6 +73,12 @@ static inline bool is_dom0less_mode(void)
 }
 static inline void set_xs_domain(struct domain *d) {}
 
+static inline int arch_handle_passthrough_prop(struct kernel_info *kinfo,
+                                               struct dt_device_node *node)
+{
+    return 0;
+}
+
 #endif /* CONFIG_DOM0LESS_BOOT */
 
 #endif /* __ASM_GENERIC_DOM0LESS_BUILD_H__ */
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index 24840eeaa6..55eed9992c 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -327,6 +327,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
 #define XEN_DOMCTL_CONFIG_TEE_FFA       2
 
+#define XEN_DOMCTL_CONFIG_ARM_SCI_NONE      0
+
 struct xen_arch_domainconfig {
     /* IN/OUT */
     uint8_t gic_version;
@@ -350,6 +352,8 @@ struct xen_arch_domainconfig {
      *
      */
     uint32_t clock_frequency;
+    /* IN */
+    uint8_t arm_sci_type;
 };
 #endif /* __XEN__ || __XEN_TOOLS__ */
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (2 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 04/10] docs: arm: add docs for SCMI over SMC calls forwarding driver Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-07-22 12:21   ` Jan Beulich
                     ` (2 more replies)
  2025-07-22 11:41 ` [RFC PATCH v5 05/10] drivers: iommu: change error code when iommu is disabled Oleksii Moisieiev
                   ` (6 subsequent siblings)
  10 siblings, 3 replies; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

From: Grygorii Strashko <grygorii_strashko@epam.com>

The commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls
handling layer") introduces simple driver which forwards SCMI over SMC
calls from hwdom/dom0 to EL3 firmware (TF-A) with a single SCMI OSPM agent
support. While it is working gracefully for hwdom/dom0 use case it doesn't
cover "thin Dom0 with guest domain, which serves as Driver domain"
use-case. In this case HW need to be enable in Driver domain and dom0 is
performing only control functions.

The EL3 SCMI firmware (TF-A) with a single SCMI OSPM agent support is
pretty generic case for the default vendors SDK and new platforms.

This patch enables passthrough of SCMI SMC single agent interface to the
one guest domain serving as Driver domain.

Configure Dom0 to enable SCMI passthrough:

 - dom0: add scmi_smc_passthrough to the Xen Command Line

Enabled SCMI passthrough for guest using toolstack in the following way:

 - domD: xl.cfg add "arm_sci" option as below

   arm_sci = "type=scmi_smc"

 - domD: xl.cfg enable access to the "arm,scmi-shmem"

iomem = [
    "47ff0,1@22001",
]

 - domD: add SCMI nodes to the Driver domain partial device tree as in the
 below example:

passthrough {
   scmi_shm_0: sram@22001000 {
       compatible = "arm,scmi-shmem";
       reg = <0x0 0x22001000 0x0 0x1000>;
   };

   firmware {
        compatible = "simple-bus";
            scmi: scmi {
                compatible = "arm,scmi-smc";
                shmem = <&scmi_shm_0>;
                ...
            }
    }
}

dom0less case configuration:

- add "xen,sci_type" property for required DomU ("xen,domain") node

   xen,sci_type="scmi_smc"

- add scmi nodes to the Driver domain partial device tree the same way
as above and enable access to the "arm,scmi-shmem" according to
dom0less documentation. For example:

  scmi_shm_0: sram@22001000 {
        compatible = "arm,scmi-shmem";
        reg = <0x00 0x22001000 0x00 0x1000>;
->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
->        xen,force-assign-without-iommu;
  };

The SCMI SMC single agent interface can be enabled for one and only one
domain. In general, the configuration is similar to any other HW
passthrough, except explicitly enabling SCMI with "arm_sci" xl.cfg option.

Note that "arm,scmi-smc" and "arm,scmi-shmem" nodes will be removed from
dom0/hwdom DT in case of

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---

Changes in v5:
- rename dom0_scmi_smc_passthrough to scmi_smc_passthrough

Changes in v4:
- xl.cfg doc
- fix comments from Stefano Stabellini
- fix toolstack code as sugested by Anthony PERARD
  - use MATCH_OPTION()
  - move arm_sci struct and cfg params in "arch_arm"
- add SCMI passthrough for dom0less case

 docs/man/xl.cfg.5.pod.in              |  34 ++++++++
 docs/misc/arm/device-tree/booting.txt |  15 ++++
 docs/misc/xen-command-line.pandoc     |   9 +++
 tools/include/libxl.h                 |   5 ++
 tools/libs/light/libxl_arm.c          |  14 ++++
 tools/libs/light/libxl_types.idl      |  10 +++
 tools/xl/xl_parse.c                   |  36 +++++++++
 xen/arch/arm/dom0less-build.c         |  34 +++++++-
 xen/arch/arm/firmware/Kconfig         |   4 +-
 xen/arch/arm/firmware/scmi-smc.c      | 112 +++++++++++++++++++++++++-
 10 files changed, 268 insertions(+), 5 deletions(-)

diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 1d122982c6..8f1a203e21 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -3073,6 +3073,40 @@ writes will be ignored.
 
 This option is only implemented for Arm where the default is enabled.
 
+=item B<arm_sci="ARM_SCI_STRING">
+
+Set ARM_SCI specific options for the guest. ARM SCI is System
+Control Protocol allows domain to manage various functions that are provided
+by HW platform firmware.
+
+B<ARM_SCI_STRING> is a comma separated list of C<KEY=VALUE> settings,
+from the following list:
+
+=over 4
+
+=item B<type=STRING>
+
+Specifies an ARM SCI type for the guest.
+
+=over 4
+
+=item B<none>
+
+Don't allow guest to use ARM SCI if present on the platform. This is the
+default value.
+
+=item B<scmi_smc>
+
+Enables ARM SCMI SMC support for the guest by enabling SCMI over SMC calls
+forwarding from domain to the EL3 firmware (like Trusted Firmware-A) with a
+single SCMI OSPM agent support.
+Should be used together with B<scmi_smc_passthrough> Xen command line
+option.
+
+=back
+
+=back
+
 =back
 
 =head3 x86
diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index 07acc7ba64..8ea11c1551 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -307,6 +307,21 @@ with the following properties:
     passed through. This option is the default if this property is missing
     and the user does not provide the device partial device tree for the domain.
 
+- xen,sci_type
+
+    A string property specifying an ARM SCI type for the guest.
+
+    - "none"
+    Don't allow guest to use ARM SCI if present on the platform. This is the
+    default value.
+
+    - "scmi_smc"
+    Enables ARM SCMI SMC support for the guest by enabling SCMI over SMC calls
+    forwarding from domain to the EL3 firmware (like Trusted Firmware-A) with a
+    single SCMI OSPM agent support.
+    Should be used together with scmi_smc_passthrough Xen command line
+    option.
+
 Under the "xen,domain" compatible node, one or more sub-nodes are present
 for the DomU kernel and ramdisk.
 
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 6865a61220..7a1f723e63 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -1096,6 +1096,15 @@ affinities to prefer but be not limited to the specified node(s).
 
 Pin dom0 vcpus to their respective pcpus
 
+### scmi_smc_passthrough (ARM)
+> `= <boolean>`
+
+The option is available when `CONFIG_SCMI_SMC` is compiled in, and allows to
+enable SCMI SMC single agent interface for any, but only one guest domain,
+which serves as Driver domain. The SCMI will be disabled for Dom0/hwdom and
+SCMI nodes removed from Dom0/hwdom device tree.
+(for example, thin Dom0 with Driver domain use-case).
+
 ### dtuart (ARM)
 > `= path [:options]`
 
diff --git a/tools/include/libxl.h b/tools/include/libxl.h
index a8704e0268..64ca80e4cc 100644
--- a/tools/include/libxl.h
+++ b/tools/include/libxl.h
@@ -313,6 +313,11 @@
  */
 #define LIBXL_HAVE_BUILDINFO_ARCH_NR_SPIS 1
 
+/*
+ * libxl_domain_build_info has the arch_arm.sci* fields.
+ */
+#define LIBXL_HAVE_BUILDINFO_ARCH_ARM_SCI 1
+
 /*
  * LIBXL_HAVE_SOFT_RESET indicates that libxl supports performing
  * 'soft reset' for domains and there is 'soft_reset' shutdown reason
diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
index ec258bdc16..e4407d6e3f 100644
--- a/tools/libs/light/libxl_arm.c
+++ b/tools/libs/light/libxl_arm.c
@@ -233,6 +233,20 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
         config->arch.sve_vl = d_config->b_info.arch_arm.sve_vl / 128U;
     }
 
+    switch (d_config->b_info.arch_arm.arm_sci.type) {
+    case LIBXL_ARM_SCI_TYPE_NONE:
+        config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
+        break;
+    case LIBXL_ARM_SCI_TYPE_SCMI_SMC:
+        config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
+        break;
+    default:
+        LOG(ERROR, "Unknown ARM_SCI type %d",
+            d_config->b_info.arch_arm.arm_sci.type);
+        return ERROR_FAIL;
+    }
+    LOG(DEBUG, " - SCI type=%u", config->arch.arm_sci_type);
+
     return 0;
 }
 
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index 26999b77e3..c8bc0f8521 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -551,6 +551,15 @@ libxl_sve_type = Enumeration("sve_type", [
     (2048, "2048")
     ], init_val = "LIBXL_SVE_TYPE_DISABLED")
 
+libxl_arm_sci_type = Enumeration("arm_sci_type", [
+    (0, "none"),
+    (1, "scmi_smc")
+    ], init_val = "LIBXL_ARM_SCI_TYPE_NONE")
+
+libxl_arm_sci = Struct("arm_sci", [
+    ("type", libxl_arm_sci_type),
+    ])
+
 libxl_rdm_reserve = Struct("rdm_reserve", [
     ("strategy",    libxl_rdm_reserve_strategy),
     ("policy",      libxl_rdm_reserve_policy),
@@ -726,6 +735,7 @@ libxl_domain_build_info = Struct("domain_build_info",[
                                ("vuart", libxl_vuart_type),
                                ("sve_vl", libxl_sve_type),
                                ("nr_spis", uint32, {'init_val': 'LIBXL_NR_SPIS_DEFAULT'}),
+                               ("arm_sci", libxl_arm_sci),
                               ])),
     ("arch_x86", Struct(None, [("msr_relaxed", libxl_defbool),
                               ])),
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 4ffcbf624b..68d2ebeb9f 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -1284,6 +1284,36 @@ out:
     if (rc) exit(EXIT_FAILURE);
 }
 
+static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci,
+                                const char *str)
+{
+    int ret = 0;
+    char *buf2, *ptr;
+    char *oparg;
+
+    if (NULL == (buf2 = ptr = strdup(str)))
+        return ERROR_NOMEM;
+
+    ptr = strtok(buf2, ",");
+    while (ptr != NULL)
+    {
+        if (MATCH_OPTION("type", ptr, oparg)) {
+            ret = libxl_arm_sci_type_from_string(oparg, &arm_sci->type);
+            if (ret) {
+                fprintf(stderr, "Unknown ARM_SCI type: %s\n", oparg);
+                ret = ERROR_INVAL;
+                goto parse_error;
+            }
+        }
+
+        ptr = strtok(NULL, ",");
+    }
+
+parse_error:
+    free(buf2);
+    return ret;
+}
+
 void parse_config_data(const char *config_source,
                        const char *config_data,
                        int config_len,
@@ -2984,6 +3014,12 @@ skip_usbdev:
     xlu_cfg_get_defbool(config, "trap_unmapped_accesses",
                         &b_info->trap_unmapped_accesses, 0);
 
+    if (!xlu_cfg_get_string(config, "arm_sci", &buf, 1)) {
+        if (parse_arm_sci_config(config, &b_info->arch_arm.arm_sci, buf)) {
+            exit(EXIT_FAILURE);
+        }
+    }
+
     parse_vkb_list(config, d_config);
 
     d_config->virtios = NULL;
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index 2a0bf817ba..d28143f98b 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -279,6 +279,36 @@ int __init arch_handle_passthrough_prop(struct kernel_info *kinfo,
     return sci_assign_dt_device(kinfo->d, node);
 }
 
+int __init domu_dt_sci_parse(struct dt_device_node *node,
+                             struct xen_domctl_createdomain *d_cfg)
+{
+    const char *sci_type = NULL;
+    int ret;
+
+    d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
+
+    if ( !IS_ENABLED(CONFIG_ARM_SCI) ||
+         !dt_property_read_bool(node, "xen,sci_type") )
+        return 0;
+
+    ret = dt_property_read_string(node, "xen,sci_type", &sci_type);
+    if ( ret )
+        return ret;
+
+    if ( !strcmp(sci_type, "none") )
+        d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
+    else if ( !strcmp(sci_type, "scmi_smc") )
+        d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
+    else
+    {
+        printk(XENLOG_ERR "xen,sci_type in not valid (%s) for domain %s\n",
+               sci_type, dt_node_name(node));
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
 void __init arch_create_domUs(struct dt_device_node *node,
                        struct xen_domctl_createdomain *d_cfg,
                        unsigned int flags)
@@ -287,7 +317,9 @@ void __init arch_create_domUs(struct dt_device_node *node,
 
     d_cfg->arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
     d_cfg->flags |= XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap;
-    d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
+
+    if ( domu_dt_sci_parse(node, d_cfg) )
+        panic("Error getting SCI configuration\n");
 
     if ( !dt_property_read_u32(node, "nr_spis", &d_cfg->arch.nr_spis) )
     {
diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
index bbf88fbb9a..5c5f0880c4 100644
--- a/xen/arch/arm/firmware/Kconfig
+++ b/xen/arch/arm/firmware/Kconfig
@@ -25,7 +25,9 @@ config SCMI_SMC
 	  doorbell mechanism and Shared Memory for transport ("arm,scmi-smc"
 	  compatible only). The value of "arm,smc-id" DT property from SCMI
 	  firmware node is used to trap and forward corresponding SCMI SMCs
-	  to firmware running at EL3, for calls coming from the hardware domain.
+	  to firmware running at EL3, for calls coming from the hardware domain or
+	  driver domain.
+	  Use with EL3 firmware which supports only single SCMI OSPM agent.
 
 endchoice
 
diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c
index 13d1137592..ae759f1616 100644
--- a/xen/arch/arm/firmware/scmi-smc.c
+++ b/xen/arch/arm/firmware/scmi-smc.c
@@ -14,6 +14,8 @@
 #include <xen/device_tree.h>
 #include <xen/errno.h>
 #include <xen/init.h>
+#include <xen/iocap.h>
+#include <xen/param.h>
 #include <xen/sched.h>
 #include <xen/types.h>
 
@@ -22,7 +24,11 @@
 
 #define SCMI_SMC_ID_PROP   "arm,smc-id"
 
+static bool __ro_after_init opt_scmi_smc_passthrough = false;
+boolean_param("scmi_smc_passthrough", opt_scmi_smc_passthrough);
+
 static uint32_t __ro_after_init scmi_smc_id;
+static struct domain __read_mostly *scmi_dom;
 
 /*
  * Check if provided SMC Function Identifier matches the one known by the SCMI
@@ -50,7 +56,7 @@ static bool scmi_handle_smc(struct cpu_user_regs *regs)
         return false;
 
     /* Only the hardware domain should use SCMI calls */
-    if ( !is_hardware_domain(current->domain) )
+    if ( scmi_dom != current->domain )
     {
         gdprintk(XENLOG_WARNING, "SCMI: Unprivileged access attempt\n");
         return false;
@@ -75,12 +81,45 @@ static bool scmi_handle_smc(struct cpu_user_regs *regs)
     return true;
 }
 
+static int
+scmi_smc_domain_sanitise_config(struct xen_domctl_createdomain *config)
+{
+    if ( config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_NONE &&
+         config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC )
+        return -EINVAL;
+
+    return 0;
+}
+
 static int scmi_smc_domain_init(struct domain *d,
                                 struct xen_domctl_createdomain *config)
 {
-    if ( !is_hardware_domain(d) )
+    /*
+     * scmi_passthrough is not enabled:
+     * - proceed only for hw_domain
+     * - fail if guest domain has SCMI enabled.
+     */
+    if ( !opt_scmi_smc_passthrough && !is_hardware_domain(d) )
+    {
+        if ( config->arch.arm_sci_type == XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC )
+            return -EINVAL;
+        else
+            return 0;
+    }
+    /*
+     * scmi_passthrough is enabled:
+     * - ignore hw_domain
+     * - proceed only for domain with SCMI enabled.
+     */
+    if ( opt_scmi_smc_passthrough &&
+         (config->arch.arm_sci_type == XEN_DOMCTL_CONFIG_ARM_SCI_NONE ||
+          is_hardware_domain(d)) )
         return 0;
 
+    if ( scmi_dom )
+        return -EEXIST;
+
+    scmi_dom = d;
     d->arch.sci_enabled = true;
     printk(XENLOG_DEBUG "SCMI: %pd init\n", d);
     return 0;
@@ -88,12 +127,77 @@ static int scmi_smc_domain_init(struct domain *d,
 
 static void scmi_smc_domain_destroy(struct domain *d)
 {
-    if ( !is_hardware_domain(d) )
+    if ( scmi_dom && scmi_dom != d )
         return;
 
+    scmi_dom = NULL;
+    d->arch.sci_enabled = false;
     printk(XENLOG_DEBUG "SCMI: %pd destroy\n", d);
 }
 
+/*
+ * Handle Dom0 SCMI SMC specific DT nodes
+ *
+ * if scmi_smc_passthrough=false:
+ * - Copy SCMI nodes into Dom0 device tree.
+ * if scmi_smc_passthrough=true:
+ * - skip SCMI nodes from Dom0 DT
+ * - give dom0 control access to SCMI shmem MMIO, so SCMI can be passed
+ *   through to guest.
+ */
+static bool scmi_smc_dt_handle_node(struct domain *d,
+                                    struct dt_device_node *node)
+{
+    static const struct dt_device_match shmem_matches[] __initconst = {
+        DT_MATCH_COMPATIBLE("arm,scmi-shmem"),
+        { /* sentinel */ },
+    };
+    static const struct dt_device_match scmi_matches[] __initconst = {
+        DT_MATCH_PATH("/firmware/scmi"),
+        { /* sentinel */ },
+    };
+
+    /* skip scmi shmem node for dom0 if scmi not enabled */
+    if ( dt_match_node(shmem_matches, node) && !sci_domain_is_enabled(d) )
+    {
+        dt_dprintk("Skip scmi shmem node\n");
+        return true;
+    }
+
+    /*
+     * skip scmi node for dom0 if scmi not enabled, but give dom0 control
+     * access to SCMI shmem
+     */
+    if ( dt_match_node(scmi_matches, node) && !sci_domain_is_enabled(d) )
+    {
+        struct dt_device_node *shmem_node;
+        const __be32 *prop;
+        u64 paddr, size;
+        int ret;
+
+        /* give dom0 control access to SCMI shmem */
+        prop = dt_get_property(node, "shmem", NULL);
+        if ( !prop )
+            return true;
+
+        shmem_node = dt_find_node_by_phandle(be32_to_cpu(*prop));
+        if ( !shmem_node )
+            return true;
+
+        ret = dt_device_get_address(shmem_node, 0, &paddr, &size);
+        if ( ret )
+            return true;
+
+        ret = iomem_permit_access(d, paddr_to_pfn(paddr),
+                                  paddr_to_pfn(paddr + size - 1));
+
+        dt_dprintk("Skip scmi node\n");
+        return true;
+    }
+
+    return false;
+}
+
 static int __init scmi_check_smccc_ver(void)
 {
     if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
@@ -108,8 +212,10 @@ static int __init scmi_check_smccc_ver(void)
 
 static const struct sci_mediator_ops scmi_smc_ops = {
     .handle_call = scmi_handle_smc,
+    .domain_sanitise_config = scmi_smc_domain_sanitise_config,
     .domain_init = scmi_smc_domain_init,
     .domain_destroy = scmi_smc_domain_destroy,
+    .dom0_dt_handle_node = scmi_smc_dt_handle_node,
 };
 
 /* Initialize the SCMI layer based on SMCs and Device-tree */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 04/10] docs: arm: add docs for SCMI over SMC calls forwarding driver
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
  2025-07-22 11:41 ` [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem Oleksii Moisieiev
  2025-07-22 11:41 ` [RFC PATCH v5 01/10] xen/arm: add generic SCI subsystem Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-08-23  0:30   ` Stefano Stabellini
  2025-07-22 11:41 ` [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent Oleksii Moisieiev
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

From: Grygorii Strashko <grygorii_strashko@epam.com>

Add documentation section for Simple Arm SCMI over SMC/HVC calls forwarding
driver (EL3).

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---

Changes in v5:
- rename dom0_scmi_smc_passthrough in documentation

 .../arm/firmware/arm-scmi.rst                 | 177 ++++++++++++++++++
 docs/hypervisor-guide/arm/index.rst           |   9 +
 docs/hypervisor-guide/index.rst               |   1 +
 3 files changed, 187 insertions(+)
 create mode 100644 docs/hypervisor-guide/arm/firmware/arm-scmi.rst
 create mode 100644 docs/hypervisor-guide/arm/index.rst

diff --git a/docs/hypervisor-guide/arm/firmware/arm-scmi.rst b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
new file mode 100644
index 0000000000..a084c0caa3
--- /dev/null
+++ b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
@@ -0,0 +1,177 @@
+.. SPDX-License-Identifier: CC-BY-4.0
+
+ARM System Control and Management Interface (SCMI)
+==================================================
+
+The System Control and Management Interface (SCMI) [1], which is a set of operating
+system-independent software interfaces that are used in system management. SCMI currently
+provides interfaces for:
+
+- Discovery and self-description of the interfaces it supports
+- Power domain management
+- Clock management
+- Reset domain management
+- Voltage domain management
+- Sensor management
+- Performance management
+- Power capping and monitoring
+- Pin control protocol.
+
+The SCMI compliant firmware could run:
+
+- as part of EL3 secure world software (like Trusted Firmware-A) with
+  ARM SMC/HVC shared-memory transport;
+- on dedicated System Control Processor (SCP) with HW mailbox shared-memory transport
+
+The major purpose of enabling SCMI support in Xen is to enable guest domains access to the SCMI
+interfaces for performing management actions on passed-through devices (such as clocks/resets etc)
+without accessing directly to the System control HW (like clock controllers) which in most cases
+can't shared/split between domains. Or, at minimum, allow SCMI access for dom0/hwdom (or guest
+domain serving as Driver domain).
+
+The below sections describe SCMI support options available for Xen.
+
+[1] `Arm SCMI <https://developer.arm.com/documentation/den0056/latest/>`_
+
+Simple SCMI over SMC/HVC calls forwarding driver (EL3)
+------------------------------------------------------
+
+The EL3 SCMI firmware (TF-A) with a single SCMI OSPM agent support is pretty generic case for
+the default vendors SDK and new platforms with SCMI support. Such EL3 SCMI firmware supports only
+single SCMI OSPM transport (agent) with Shared memory based transport and SMC/HVC calls as doorbell.
+
+The SCMI over SMC/HVC calls forwarding driver solves major problem for this case by allowing
+SMC/HVC calls to be forwarded form guest to the EL3 SCMI firmware.
+
+By default, the SCMI over SMC/HVC calls forwarding is enabled for Dom0/hwdom.
+
+::
+
+    +--------------------------+
+    |                          |
+    | EL3 SCMI FW (TF-A)       |
+    ++-------+--^--------------+
+     |shmem  |  | smc-id
+     +----^--+  |
+          |     |
+     +----|-+---+---+----------+
+     |    | |  FWD  |      Xen |
+     |    | +---^---+          |
+     +----|-----|--------------+
+          |     | smc-id
+     +----v-----+--+ +---------+
+     |             | |         |
+     | Dom0/hwdom  | | DomU    |
+     |             | |         |
+     |             | |         |
+     +-------------+ +---------+
+
+
+The SCMI messages are passed directly through SCMI shared-memory (zero-copy) and driver only
+forwards SMC/HVC calls.
+
+Compiling
+^^^^^^^^^
+
+To build with the SCMI over SMC/HVC calls forwarding enabled support, enable Kconfig option
+
+::
+
+    CONFIG_SCMI_SMC
+
+The ``CONFIG_SCMI_SMC`` is enabled by default.
+
+Pass-through SCMI SMC to domain which serves as Driver domain
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This section describes how to configure the SCMI over SMC/HVC calls forwarding driver to handle use
+case "thin Dom0 with guest domain, which serves as Driver domain". In this case HW need to be
+enabled in Driver domain and dom0 is performing only control functions (without accessing FW) and so,
+the SCMI need to be enabled in Driver domain.
+
+::
+
+     +--------------------------+
+     |EL3 SCMI FW (TF-A)        |
+     |                          |
+     +-------------^--+-------+-+
+             smc-id|  |shmem0 |
+                   |  +----^--+
+    +-------------++------+|----+
+    |Xen          |  FWD  ||    |
+    |             +--^----+|    |
+    +----------------|-----|----+
+              smc-id |     |
+    +-----------+ +--+-----v-----+
+    |           | |              |
+    | Dom0      | |    Driver    |
+    | Control   | |    domain    |
+    |           | |              |
+    +-----------+ +--------------+
+
+The SCMI can be enabled for one and only one guest domain.
+
+First. configure Dom0 to enable SCMI pass-through using Xen Command Line
+**"scmi_smc_passthrough"** option. This will disable SCMI for Dom0/hwdom and SCMI nodes will
+be removed from Dom0/hwdom device tree.
+
+**Configure SCMI pass-through for guest domain with toolstack**
+
+* In domain's xl.cfg file add **"arm_sci"** option as below
+
+::
+
+    arm_sci = "type=scmi_smc"
+
+* In domain's xl.cfg file enable access to the "arm,scmi-shmem"
+
+::
+
+    iomem = [
+        "47ff0,1@22001",
+    ]
+
+.. note:: It's up to the user to select guest IPA for mapping SCMI shared-memory.
+
+* Add SCMI nodes to the Driver domain partial device tree as in the below example:
+
+.. code::
+
+    passthrough {
+       scmi_shm_0: sram@22001000 {
+           compatible = "arm,scmi-shmem";
+           reg = <0x0 0x22001000 0x0 0x1000>;
+       };
+
+       firmware {
+            compatible = "simple-bus";
+                scmi: scmi {
+                    compatible = "arm,scmi-smc";
+                    shmem = <&scmi_shm_0>;
+                    ...
+                }
+        }
+    }
+
+In general, the configuration is similar to any other HW pass-through, except explicitly
+enabling SCMI with "arm_sci" xl.cfg option.
+
+**Configure SCMI pass-through for predefined domain (dom0less)**
+
+* add "xen,sci_type" property for required DomU ("xen,domain") node
+
+::
+
+       xen,sci_type="scmi_smc"
+
+* add scmi nodes to the Driver domain partial device tree the same way as above and enable access
+  to the "arm,scmi-shmem" according to  dom0less documentation. For example:
+
+.. code::
+
+      scmi_shm_0: sram@22001000 {
+            compatible = "arm,scmi-shmem";
+            reg = <0x00 0x22001000 0x00 0x1000>;
+    ->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
+    ->        xen,force-assign-without-iommu;
+      };
diff --git a/docs/hypervisor-guide/arm/index.rst b/docs/hypervisor-guide/arm/index.rst
new file mode 100644
index 0000000000..7aae4a0a03
--- /dev/null
+++ b/docs/hypervisor-guide/arm/index.rst
@@ -0,0 +1,9 @@
+.. SPDX-License-Identifier: CC-BY-4.0
+
+ARM
+===
+
+.. toctree::
+   :maxdepth: 2
+
+   firmware/arm-scmi
diff --git a/docs/hypervisor-guide/index.rst b/docs/hypervisor-guide/index.rst
index e4393b0697..520fe01554 100644
--- a/docs/hypervisor-guide/index.rst
+++ b/docs/hypervisor-guide/index.rst
@@ -9,3 +9,4 @@ Hypervisor documentation
    code-coverage
 
    x86/index
+   arm/index
\ No newline at end of file
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 07/10] xen: arm: smccc: add INVALID_PARAMETER error code
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (4 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 05/10] drivers: iommu: change error code when iommu is disabled Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-08-23  0:33   ` Stefano Stabellini
  2025-07-22 11:41 ` [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu Oleksii Moisieiev
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

According to the "7.1 Return Codes" section of DEN0028 [1]
INVALID_PARAMETER code (-3) is returned when one of the call
parameters has a non-supported value.
Adding this error code to the common smccc header file.

[1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6

Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---



 xen/arch/arm/include/asm/smccc.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/xen/arch/arm/include/asm/smccc.h b/xen/arch/arm/include/asm/smccc.h
index a289c48b7f..dc6af94db1 100644
--- a/xen/arch/arm/include/asm/smccc.h
+++ b/xen/arch/arm/include/asm/smccc.h
@@ -381,6 +381,7 @@ void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
                        0x3FFF)
 
 /* SMCCC error codes */
+#define ARM_SMCCC_INVALID_PARAMETER     (-3)
 #define ARM_SMCCC_NOT_REQUIRED          (-2)
 #define ARM_SMCCC_ERR_UNKNOWN_FUNCTION  (-1)
 #define ARM_SMCCC_NOT_SUPPORTED         (-1)
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 05/10] drivers: iommu: change error code when iommu is disabled
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (3 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-07-22 12:29   ` Jan Beulich
  2025-07-22 11:41 ` [RFC PATCH v5 07/10] xen: arm: smccc: add INVALID_PARAMETER error code Oleksii Moisieiev
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

Change -ENOPNOTSUPP error code to -ENXIO when iommu is disabled during
iommu_do_domctl call. As was discussed in [1]

[0]: https://lore.kernel.org/xen-devel/alpine.DEB.2.22.394.2506171701190.1780597@ubuntu-linux-20-04-desktop/

Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---

Changes in v5:
- set error code to -ENXIO when iommu is disabled

 xen/drivers/passthrough/iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 16aad86973..075bbd1718 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -632,7 +632,7 @@ int iommu_do_domctl(
     int ret = -ENODEV;
 
     if ( !(d ? is_iommu_enabled(d) : iommu_enabled) )
-        return -EOPNOTSUPP;
+        return -ENXIO;
 
 #ifdef CONFIG_HAS_PCI
     ret = iommu_do_pci_domctl(domctl, d, u_domctl);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (5 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 07/10] xen: arm: smccc: add INVALID_PARAMETER error code Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-07-22 12:34   ` Jan Beulich
  2025-07-22 11:41 ` [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Oleksii Moisieiev
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

From: Grygorii Strashko <grygorii_strashko@epam.com>

Add chained handling of assigned DT devices to support access-controller
functionality through SCI framework, so DT device assign request can be
passed to FW for processing and enabling VM access to requested device
(for example, device power management through FW interface like SCMI).

The SCI access-controller DT device processing is chained after IOMMU
processing and expected to be executed for any DT device regardless of its
protection by IOMMU (or if IOMMU is disabled).

This allows to pass not only IOMMU protected DT device through
xl.cfg:"dtdev" property for processing:

dtdev = [
    "/soc/video@e6ef0000", <- IOMMU protected device
    "/soc/i2c@e6508000", <- not IOMMU protected device
]

The change is done in two parts:
1) update iommu_do_dt_domctl() to check for dt_device_is_protected() and
not fail if DT device is not protected by IOMMU
2) add chained call to sci_do_domctl() in do_domctl()

Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---

Changes in v5:
- return -EINVAL if mediator without assign_dt_device was provided
- invert return code check for iommu_do_domctl in
XEN_DOMCTL_assign_device domctl processing to make cleaner code
- change -ENOTSUPP error code to -ENXIO in sci_do_domctl
- handle -ENXIO return comde of iommu_do_domctl
- leave !dt_device_is_protected check in iommu_do_dt_domctl to make
code work the same way it's done in "handle_device" call while
creating hwdom(dom0) and "handle_passthrough_prop" call for dom0less
creation
- drop return check from sci_assign_dt_device call as not needed
- do not return EINVAL when addign_dt_device is not set. That is
because this callback is optional and not implemented in single-agent driver

 xen/arch/arm/firmware/sci.c             | 35 +++++++++++++++++++++++++
 xen/arch/arm/include/asm/firmware/sci.h | 14 ++++++++++
 xen/common/domctl.c                     | 19 ++++++++++++++
 xen/drivers/passthrough/device_tree.c   |  6 +++++
 4 files changed, 74 insertions(+)

diff --git a/xen/arch/arm/firmware/sci.c b/xen/arch/arm/firmware/sci.c
index e1522e10e2..db75fc5cb3 100644
--- a/xen/arch/arm/firmware/sci.c
+++ b/xen/arch/arm/firmware/sci.c
@@ -126,6 +126,41 @@ int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev)
     return 0;
 }
 
+int sci_do_domctl(struct xen_domctl *domctl, struct domain *d,
+                  XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
+{
+    struct dt_device_node *dev;
+    int ret = 0;
+
+    switch ( domctl->cmd )
+    {
+    case XEN_DOMCTL_assign_device:
+        ret = -ENXIO;
+        if ( domctl->u.assign_device.dev != XEN_DOMCTL_DEV_DT )
+            break;
+
+        if ( !cur_mediator )
+            break;
+
+        if ( !cur_mediator->assign_dt_device )
+            break;
+
+        ret = dt_find_node_by_gpath(domctl->u.assign_device.u.dt.path,
+                                    domctl->u.assign_device.u.dt.size, &dev);
+        if ( ret )
+            return ret;
+
+        ret = sci_assign_dt_device(d, dev);
+
+        break;
+    default:
+        /* do not fail here as call is chained with iommu handling */
+        break;
+    }
+
+    return ret;
+}
+
 static int __init sci_init(void)
 {
     struct dt_device_node *np;
diff --git a/xen/arch/arm/include/asm/firmware/sci.h b/xen/arch/arm/include/asm/firmware/sci.h
index 71fb54852e..b8d1bc8a62 100644
--- a/xen/arch/arm/include/asm/firmware/sci.h
+++ b/xen/arch/arm/include/asm/firmware/sci.h
@@ -146,6 +146,14 @@ int sci_dt_finalize(struct domain *d, void *fdt);
  * control" functionality.
  */
 int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev);
+
+/*
+ * SCI domctl handler
+ *
+ * Only XEN_DOMCTL_assign_device is handled for now.
+ */
+int sci_do_domctl(struct xen_domctl *domctl, struct domain *d,
+                  XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl);
 #else
 
 static inline bool sci_domain_is_enabled(struct domain *d)
@@ -195,6 +203,12 @@ static inline int sci_assign_dt_device(struct domain *d,
     return 0;
 }
 
+static inline int sci_do_domctl(struct xen_domctl *domctl, struct domain *d,
+                                XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
+{
+    return 0;
+}
+
 #endif /* CONFIG_ARM_SCI */
 
 #endif /* __ASM_ARM_SCI_H */
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index f2a7caaf85..35398a0c42 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -29,6 +29,7 @@
 #include <xen/xvmalloc.h>
 
 #include <asm/current.h>
+#include <asm/firmware/sci.h>
 #include <asm/irq.h>
 #include <asm/page.h>
 #include <asm/p2m.h>
@@ -859,7 +860,25 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
     case XEN_DOMCTL_test_assign_device:
     case XEN_DOMCTL_deassign_device:
     case XEN_DOMCTL_get_device_group:
+        int ret1;
+        
         ret = iommu_do_domctl(op, d, u_domctl);
+        if ( ret < 0 && ret != -ENXIO )
+            return ret;
+
+        /*
+         * Add chained handling of assigned DT devices to support
+         * access-controller functionality through SCI framework, so
+         * DT device assign request can be passed to FW for processing and
+         * enabling VM access to requested device.
+         * The access-controller DT device processing is chained after IOMMU
+         * processing and expected to be executed for any DT device
+         * regardless if DT device is protected by IOMMU or not (or IOMMU
+         * is disabled).
+         */
+        ret1 = sci_do_domctl(op, d, u_domctl);
+        if ( ret1 != -ENXIO )
+            ret = ret1;
         break;
 
     case XEN_DOMCTL_get_paging_mempool_size:
diff --git a/xen/drivers/passthrough/device_tree.c b/xen/drivers/passthrough/device_tree.c
index f5850a2607..29a44dc773 100644
--- a/xen/drivers/passthrough/device_tree.c
+++ b/xen/drivers/passthrough/device_tree.c
@@ -379,6 +379,12 @@ int iommu_do_dt_domctl(struct xen_domctl *domctl, struct domain *d,
             break;
         }
 
+        if ( !dt_device_is_protected(dev) )
+        {
+            ret = 0;
+            break;
+        }
+
         ret = iommu_assign_dt_device(d, dev);
 
         if ( ret )
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (7 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-07-22 12:43   ` Jan Beulich
  2025-08-23  0:40   ` Stefano Stabellini
  2025-07-22 11:41 ` [RFC PATCH v5 10/10] docs: arm: add SCI SCMI SMC multi-agent driver docs Oleksii Moisieiev
  2025-08-23  0:34 ` [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Stefano Stabellini
  10 siblings, 2 replies; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

This commit introduces two helper functions, `__memcpy_fromio` and
`__memcpy_toio`, to provide a robust mechanism for copying data between
standard memory and memory-mapped I/O (MMIO) space for the ARM
architecture.

These functions are designed to handle memory transfers safely,
accounting for potential address alignment issues to ensure correctness
and improve performance where possible. The implementation is specific
to ARM and uses relaxed I/O accessors.

__memcpy_fromio:
Copies a block of data from an I/O memory source to a destination in
standard ("real") memory. The implementation first handles any unaligned
bytes at the beginning of the source buffer individually using byte-wise
reads. It then copies the bulk of the data using 32-bit reads for
efficiency, and finally processes any remaining bytes at the end of the
buffer.

__memcpy_toio:
Copies a block of data from standard memory to a destination in I/O
memory space. It follows a similar strategy, handling any initial
unaligned portion of the destination buffer byte-by-byte before using
more efficient 32-bit writes for the main, aligned part of the transfer.
Any trailing bytes are also handled individually.
xen/include/xen/lib/arm/io.h

Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---

Changes in v5:
- move memcpy_toio/fromio to the generic place

 xen/include/xen/lib/arm/io.h | 15 +++++++
 xen/lib/Makefile             |  1 +
 xen/lib/arm/Makefile         |  1 +
 xen/lib/arm/io.c             | 80 ++++++++++++++++++++++++++++++++++++
 4 files changed, 97 insertions(+)
 create mode 100644 xen/include/xen/lib/arm/io.h
 create mode 100644 xen/lib/arm/Makefile
 create mode 100644 xen/lib/arm/io.c

diff --git a/xen/include/xen/lib/arm/io.h b/xen/include/xen/lib/arm/io.h
new file mode 100644
index 0000000000..86973660ba
--- /dev/null
+++ b/xen/include/xen/lib/arm/io.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _XEN_LIB_ARM_IO_H
+#define _XEN_LIB_ARM_IO_H
+
+#include <xen/types.h>
+
+/*
+ * Prototypes for I/O memory access functions.
+ */
+extern void __memcpy_fromio(void *to, const volatile void __iomem *from,
+                     size_t count);
+extern void __memcpy_toio(volatile void __iomem *to, const void *from,
+                   size_t count);
+
+#endif /* _XEN_LIB_ARM_IO_H */
diff --git a/xen/lib/Makefile b/xen/lib/Makefile
index 5ccb1e5241..efa8157a72 100644
--- a/xen/lib/Makefile
+++ b/xen/lib/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_X86) += x86/
+obj-$(CONFIG_ARM) += arm/
 
 lib-y += bsearch.o
 lib-y += ctors.o
diff --git a/xen/lib/arm/Makefile b/xen/lib/arm/Makefile
new file mode 100644
index 0000000000..87250b3822
--- /dev/null
+++ b/xen/lib/arm/Makefile
@@ -0,0 +1 @@
+obj-y += io.o
\ No newline at end of file
diff --git a/xen/lib/arm/io.c b/xen/lib/arm/io.c
new file mode 100644
index 0000000000..d267bd28e4
--- /dev/null
+++ b/xen/lib/arm/io.c
@@ -0,0 +1,80 @@
+#include <asm/io.h>
+#include <xen/lib/arm/io.h>
+
+/*
+ * memcpy_fromio - Copy data from IO memory space to "real" memory space.
+ * @to: Where to copy to
+ * @from: Where to copy from
+ * @count: The size of the area.
+ */
+void __memcpy_fromio(void *to, const volatile void __iomem *from,
+                     size_t count)
+{
+    while ( count && !IS_ALIGNED((unsigned long)from, 4) )
+    {
+        *(u8 *)to = readb_relaxed(from);
+        from++;
+        to++;
+        count--;
+    }
+
+    while ( count >= 4 )
+    {
+        *(u32 *)to = readl_relaxed(from);
+        from += 4;
+        to += 4;
+        count -= 4;
+    }
+
+    while ( count )
+    {
+        *(u8 *)to = readb_relaxed(from);
+        from++;
+        to++;
+        count--;
+    }
+}
+
+/*
+ * memcpy_toio - Copy data from "real" memory space to IO memory space.
+ * @to: Where to copy to
+ * @from: Where to copy from
+ * @count: The size of the area.
+ */
+void __memcpy_toio(volatile void __iomem *to, const void *from,
+                   size_t count)
+{
+    while ( count && !IS_ALIGNED((unsigned long)to, 4) )
+    {
+        writeb_relaxed(*(u8 *)from, to);
+        from++;
+        to++;
+        count--;
+    }
+
+    while ( count >= 4 )
+    {
+        writel_relaxed(*(u32 *)from, to);
+        from += 4;
+        to += 4;
+        count -= 4;
+    }
+
+    while ( count )
+    {
+        writeb_relaxed(*(u8 *)from, to);
+        from++;
+        to++;
+        count--;
+    }
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 8
+ * tab-width: 8
+ * indent-tabs-mode: t
+ * End:
+ */
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (6 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-07-22 12:46   ` Jan Beulich
                     ` (3 more replies)
  2025-07-22 11:41 ` [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers Oleksii Moisieiev
                   ` (2 subsequent siblings)
  10 siblings, 4 replies; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

This patch introduces SCI driver to support for ARM EL3 Trusted Firmware-A
(TF-A) which provides SCMI interface with multi-agnet support, as shown
below.

  +-----------------------------------------+
  |                                         |
  | EL3 TF-A SCMI                           |
  +-------+--+-------+--+-------+--+-------++
  |shmem1 |  |shmem0 |  |shmem2 |  |shmemX |
  +-----+-+  +---+---+  +--+----+  +---+---+
smc-id1 |        |         |           |
agent1  |        |         |           |
  +-----v--------+---------+-----------+----+
  |              |         |           |    |
  |              |         |           |    |
  +--------------+---------+-----------+----+
         smc-id0 |  smc-id2|    smc-idX|
         agent0  |  agent2 |    agentX |
                 |         |           |
            +----v---+  +--v-----+  +--v-----+
            |        |  |        |  |        |
            | Dom0   |  | Dom1   |  | DomX   |
            |        |  |        |  |        |
            |        |  |        |  |        |
            +--------+  +--------+  +--------+

The EL3 SCMI multi-agent firmware expected to provide SCMI SMC/HVC shared
memory transport for every Agent in the system.

The SCMI Agent transport channel defined by pair:
 - smc-id: SMC/HVC id used for Doorbell
 - shmem: shared memory for messages transfer, Xen page
 aligned. Shared memort is mapped with the following flags:
 MT_DEVICE_nGnRE.

The follwoing SCMI Agents expected to be defined by SCMI FW to enable SCMI
multi-agent functionality under Xen:
- Xen manegement agent: trusted agents that accesses to the Base Protocol
commands to configure agent specific permissions
- OSPM VM agents: non-trusted agent, one for each Guest domain which is
  allowed direct HW access. At least one OSPM VM agent has to be provided
  by FW if HW is handled only by Dom0 or Driver Domain.

The EL3 SCMI FW expected to implement following Base protocol messages:
- BASE_DISCOVER_AGENT (optional if agent_id was provided)
- BASE_RESET_AGENT_CONFIGURATION (optional)
- BASE_SET_DEVICE_PERMISSIONS (optional)

The SCI SCMI SMC multi-agent driver implements following
functionality:
- The driver is initialized based on the ``xen,config`` node under ``chosen``
  (only one SCMI interface is supported), which describes the Xen management
  agent SCMI interface.

scmi_shm_1: sram@47ff1000 {
          compatible = "arm,scmi-shmem";
          reg = <0x0 0x47ff1000 0x0 0x1000>;
};
scmi_xen: scmi {
        compatible = "arm,scmi-smc";
        arm,smc-id = <0x82000003>; <--- Xen manegement agent smc-id
        #address-cells = < 1>;
        #size-cells = < 0>;
        #access-controller-cells = < 1>;
        shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
};

- The driver obtains Xen specific SCMI Agent's configuration from the Host DT, probes Agents and
  builds SCMI Agents list. The Agents configuration is taken from "scmi-secondary-agents"
  property where first item is "arm,smc-id", second - "arm,scmi-shmem" phandle and third is
  optional "agent_id":

chosen {
  ranges;
  xen,config {
    ranges;
    scmi-secondary-agents = <
                  0x82000003 &scmi_shm_0 0
                  0x82000004 &scmi_shm_2 2
                  0x82000005 &scmi_shm_3 3
                  0x82000006 &scmi_shm_4 4>;
    #scmi-secondary-agents-cells = <3>; <--- optional, default 3

    scmi_shm_0 : sram@47ff0000 {
        compatible = "arm,scmi-shmem";
        reg = <0x0 0x47ff0000 0x0 0x1000>;
    };

    scmi_shm_2: sram@47ff2000 {
            compatible = "arm,scmi-shmem";
            reg = <0x0 0x47ff2000 0x0 0x1000>;
    };
    scmi_shm_3: sram@47ff3000 {
            compatible = "arm,scmi-shmem";
            reg = <0x0 0x47ff3000 0x0 0x1000>;
    };
    scmi_shm_4: sram@47ff4000 {
            compatible = "arm,scmi-shmem";
            reg = <0x0 0x47ff4000 0x0 0x1000>;
    };

    // Xen SCMI management channel
    scmi_shm_1: sram@47ff1000 {
            compatible = "arm,scmi-shmem";
            reg = <0x0 0x47ff1000 0x0 0x1000>;
    };

    scmi_xen: scmi {
        compatible = "arm,scmi-smc";
        arm,smc-id = <0x82000002>; <--- Xen manegement agent smc-id
        #address-cells = < 1>;
        #size-cells = < 0>;
        #access-controller-cells = < 1>;
        shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
    };
  };
};

/{
    // Host SCMI OSPM channel - provided to the Dom0 as is if SCMI enabled for it
    scmi_shm: sram@47ff0000 {
            compatible = "arm,scmi-shmem";
            reg = <0x0 0x47ff0000 0x0 0x1000>;
    };

    firmware {
        scmi: scmi {
            compatible = "arm,scmi-smc";
            arm,smc-id = <0x82000002>; <--- Host OSPM agent smc-id
            #address-cells = < 1>;
            #size-cells = < 0>;
            shmem = <&scmi_shm>; <--- Host OSPM agent shmem

            protocol@X{
            };
        };
    };
};

This approach allows defining multiple SCMI Agents by adding Xen-specific properties under
the ``/chosen`` node to the Host Device Tree, leaving the main part unchanged. The Host DT
SCMI channel will be passed to Dom0.

The Xen management agent is described as a ``scmi_xen`` node under the ``/chosen`` node, which
is used by Xen to control other SCMI Agents in the system.

All secondary agents' configurations are provided in the ``scmi-secondary-agents`` property with
an optional ``agent_id`` field.

The ``agent_id`` from the ``scmi-secondary-agents`` property is used to identify the agent in the
system and can be omitted by setting ``#scmi-secondary-agents-cells = <2>``, so the Secondary
Agents configuration will look like this:

chosen {
  xen,config {
    scmi-secondary-agents = <
                  0x82000003 &scmi_shm_0
                  0x82000004 &scmi_shm_2
                  0x82000005 &scmi_shm_3
                  0x82000006 &scmi_shm_4>;
    #scmi-secondary-agents-cells = <2>;
  };
}

In this case, Xen will use the ``SCMI_BASE_DISCOVER_AGENT`` call to discover the ``agent_id``
for each secondary agent. Providing the ``agent_id`` in the ``scmi-secondary-agents`` property
allows skipping the discovery call, which is useful when the secondary agent's shared memory is
not accessible by Xen or when boot time is important because it allows skipping the agent
discovery procedure.

  Note that Xen is the only one entry in the system which need to know
  about SCMI multi-agent support.

- It implements the SCI subsystem interface required for configuring and
enabling SCMI functionality for Dom0/hwdom and Guest domains. To enable
SCMI functionality for domain it has to be configured with unique supported
SCMI Agent_id and use corresponding SCMI SMC/HVC shared memory transport
[smc-id, shmem] defined for this SCMI Agent_id.
- Once Xen domain is configured it can communicate with EL3 SCMI FW:
  -- zero-copy, the guest domain puts SCMI message in shmem;
  -- the guest triggers SMC/HVC exception with smc-id (doorbell);
  -- the Xen driver catches exception, do checks and synchronously forwards
  it to EL3 FW.
- the Xen driver sends BASE_RESET_AGENT_CONFIGURATION message to Xen
  management agent channel on domain destroy event. This allows to reset
  resources used by domain and so implement use-case like domain reboot.

Dom0 Enable SCMI SMC:
 - pass dom0_scmi_agent_id=<agent_id> in Xen command line. if not provided
   SCMI will be disabled for Dom0 and all SCMI nodes removed from Dom0 DT.
   The driver updates Dom0 DT SCMI node "arm,smc-id" value and fix up shmem
   node according to assigned agent_id.

Guest domains enable SCMI SMC:
 - xl.cfg: add configuration option as below

   arm_sci = "type=scmi_smc_multiagent,agent_id=2"

 - xl.cfg: enable access to the "arm,scmi-shmem" which should correspond assigned agent_id for
   the domain, for example:

iomem = [
    "47ff2,1@22001",
]

 - DT: add SCMI nodes to the Driver domain partial device tree as in the
 below example. The "arm,smc-id" should correspond assigned agent_id for the domain:

passthrough {
   scmi_shm_0: sram@22001000 {
       compatible = "arm,scmi-shmem";
       reg = <0x0 0x22001000 0x0 0x1000>;
   };

   firmware {
        compatible = "simple-bus";
            scmi: scmi {
                compatible = "arm,scmi-smc";
                arm,smc-id = <0x82000004>;
                shmem = <&scmi_shm_0>;
                ...
            }
    }
}

SCMI "4.2.1.1 Device specific access control"

The XEN SCI SCMI SMC multi-agent driver performs "access-controller" provider function
in case EL3 SCMI FW implements SCMI "4.2.1.1 Device specific access control" and provides the
BASE_SET_DEVICE_PERMISSIONS command to configure the devices that an agents have access to.
The DT SCMI node should "#access-controller-cells=<1>" property and DT devices should be bound
to the Xen SCMI.

&i2c1 {
	access-controllers = <&scmi 0>;
};

The Dom0 and dom0less domains DT devices will be processed automatically through
sci_assign_dt_device() call, but to assign SCMI devices from toolstack the xl.cfg:"dtdev" property
shell be used:

dtdev = [
    "/soc/i2c@e6508000",
]

xl.cfg:dtdev will contain all nodes which are under SCMI management (not only those which are behind IOMMU).

[1] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
[2] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml

Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
---

Changes in v5:
- fix device-tree example format in booting.txt, added ";" after "}".
- update define in scmi-proto.h
- update define in scmi-shmem.h file
- scmi_assign_device - do not ignore -EOPNOTSUPP return
code of the do_smc_xfer
- remove overwriting agent_channel->agent_id after
SCMI_BASE_DISCOVER_AGENT call
- add multi-agent files to the MAINTAINERS
- add SCMI multi-agent description to the SUPPORT.md
- handle ARM_SMCCC_INVALID_PARAMETER return code and return -EINVAL
for smc call
- updated collect_agents function. Set agent_id parameter as optional
in scmi-secondary-agents device-tree property
- introduce "#scmi-secondary-agents-cells" parameter to set if
agent_id was provided
- reanme xen,scmi-secondary-agents property to scmi-secondary-agents
- move memcpu_toio/fromio for the generic place
- update Xen to get management channel from /chosen/xen,config node
- get hypervisor channnel from node instead of using hardcoded
- update handling scmi and shmem nodes for the domain
- Set multi-agent driver to support only Arm64

Changes in v4:
- toolstack comments from Anthony PERARD
- added dom0less support
- added doc for "xen,scmi-secondary-agents"

 MAINTAINERS                                 |   4 +
 SUPPORT.md                                  |  11 +
 docs/man/xl.cfg.5.pod.in                    |  13 +
 docs/misc/arm/device-tree/booting.txt       |  88 +++
 docs/misc/xen-command-line.pandoc           |   9 +
 tools/libs/light/libxl_arm.c                |   4 +
 tools/libs/light/libxl_types.idl            |   4 +-
 tools/xl/xl_parse.c                         |  12 +
 xen/arch/arm/dom0less-build.c               |  11 +
 xen/arch/arm/domain_build.c                 |   3 +-
 xen/arch/arm/firmware/Kconfig               |  12 +
 xen/arch/arm/firmware/Makefile              |   1 +
 xen/arch/arm/firmware/scmi-proto.h          | 164 ++++
 xen/arch/arm/firmware/scmi-shmem.c          | 112 +++
 xen/arch/arm/firmware/scmi-shmem.h          |  45 ++
 xen/arch/arm/firmware/scmi-smc-multiagent.c | 803 ++++++++++++++++++++
 xen/include/public/arch-arm.h               |   3 +
 17 files changed, 1297 insertions(+), 2 deletions(-)
 create mode 100644 xen/arch/arm/firmware/scmi-proto.h
 create mode 100644 xen/arch/arm/firmware/scmi-shmem.c
 create mode 100644 xen/arch/arm/firmware/scmi-shmem.h
 create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 31dbba54bb..1b6b58cbb7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -514,6 +514,10 @@ R:	Oleksii Moisieiev <oleksii_moisieiev@epam.com>
 S:	Supported
 F:	xen/arch/arm/firmware/sci.c
 F:	xen/arch/arm/include/asm/firmware/sci.h
+F:	xen/arch/arm/firmware/scmi-smc-multiagent.c
+F:	xen/arch/arm/firmware/scmi-shmem.c
+F:	xen/arch/arm/firmware/scmi-shmem.h
+F:	xen/arch/arm/firmware/scmi-proto.h
 
 SEABIOS UPSTREAM
 M:	Wei Liu <wl@xen.org>
diff --git a/SUPPORT.md b/SUPPORT.md
index 6a82a92189..9d7857d953 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -956,6 +956,17 @@ by hwdom. Some platforms use SCMI for access to system-level resources.
 
     Status: Supported
 
+### Arm: SCMI SMC multi-agent support
+
+Enable support for the multi-agent configuration of the EL3 Firmware, which
+allows Xen to provide an SCMI interface to the Domains.
+Xen manages access permissions to the HW resources and provides an SCMI interface
+to the Domains. Each Domain is represented as a separate Agent, which can
+communicate with EL3 Firmware using a dedicated shared memory region, and
+notifications are passed through by Xen.
+
+    Status, ARM64: Tech Preview
+
 ### ARM: Guest PSCI support
 
 Emulated PSCI interface exposed to guests. We support all mandatory
diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
index 8f1a203e21..f6cf2d4567 100644
--- a/docs/man/xl.cfg.5.pod.in
+++ b/docs/man/xl.cfg.5.pod.in
@@ -3103,8 +3103,21 @@ single SCMI OSPM agent support.
 Should be used together with B<scmi_smc_passthrough> Xen command line
 option.
 
+=item B<scmi_smc_multiagent>
+
+Enables ARM SCMI SMC multi-agent support for the guest by enabling SCMI over
+SMC calls forwarding from domain to the EL3 firmware (like Trusted Firmware-A)
+with a multi SCMI OSPM agent support. The SCMI B<agent_id> should be
+specified for the guest.
+
 =back
 
+=item B<agent_id=NUMBER>
+
+Specifies a non-zero ARM SCI agent id for the guest. This option is mandatory
+if the SCMI SMC support is enabled for the guest. The agent ids of domains
+existing on a single host must be unique and in the range [1..255].
+
 =back
 
 =back
diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index 8ea11c1551..10a99cfd15 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -322,6 +322,20 @@ with the following properties:
     Should be used together with scmi_smc_passthrough Xen command line
     option.
 
+    - "scmi_smc_multiagent"
+
+    Enables ARM SCMI SMC multi-agent support for the guest by enabling SCMI over
+    SMC calls forwarding from domain to the EL3 firmware (like ARM
+    Trusted Firmware-A) with a multi SCMI OSPM agent support.
+    The SCMI agent_id should be specified for the guest with "xen,sci_agent_id"
+    property.
+
+- "xen,sci_agent_id"
+
+    Specifies a non-zero ARM SCI agent id for the guest. This option is
+    mandatory if the SCMI SMC "scmi_smc_multiagent" support is enabled for
+    the guest. The agent ids of guest must be unique and in the range [1..255].
+
 Under the "xen,domain" compatible node, one or more sub-nodes are present
 for the DomU kernel and ramdisk.
 
@@ -824,3 +838,77 @@ The automatically allocated static shared memory will get mapped at
 0x80000000 in DomU1 guest physical address space, and at 0x90000000 in DomU2
 guest physical address space. DomU1 is explicitly defined as the owner domain,
 and DomU2 is the borrower domain.
+
+SCMI SMC multi-agent support
+============================
+
+For enabling the ARM SCMI SMC multi-agent support (enabled by CONFIG_SCMI_SMC_MA)
+the Xen specific SCMI Agent's configuration shell be provided in the Host DT
+according to the SCMI compliant EL3 Firmware specification with
+ARM SMC/HVC transport using property "scmi-secondary-agents" placed in "xen,config"
+node under "chosen" node:
+
+- scmi-secondary-agents
+
+    Defines a set of SCMI agents configuration supported by SCMI EL3 FW and
+    available for Xen. Each Agent defined as triple consisting of:
+    SMC/HVC function_id assigned for the agent transport ("arm,smc-id"),
+    phandle to SCMI SHM assigned for the agent transport ("arm,scmi-shmem"),
+    SCMI agent_id (optional) if not set - Xen will determine Agent ID for
+    each provided channel using BASE_DISCOVER_AGENT message.
+
+As an example:
+
+/{
+chosen {
+    xen,config {
+        scmi_shm_1: sram@47ff1000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff1000 0x0 0x1000>;
+        };
+        scmi_shm_2: sram@47ff2000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff2000 0x0 0x1000>;
+        };
+        scmi_shm_3: sram@47ff3000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff3000 0x0 0x1000>;
+        };
+        scmi_shm_3: sram@47ff4000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff4000 0x0 0x1000>;
+        };
+        scmi-secondary-agents = <
+            0x82000003 &scmi_shm_1 1
+            0x82000004 &scmi_shm_2 2
+            0x82000005 &scmi_shm_3 3
+            0x82000006 &scmi_shm_4 4>;
+            #scmi-secondary-agents-cells = <3>;
+        };
+    };
+};
+
+- #scmi-secondary-agents-cells
+
+    Defines whether Agent_id is set in the "scmi-secondary-agents" property.
+    Possible values are: 2, 3.
+    When set to 3 (the default), expect agent_id to be present in the secondary
+    agents list.
+    When set to 2, agent_id will be discovered for each channel using
+    BASE_DISCOVER_AGENT message.
+
+
+Example:
+
+/{
+chosen {
+    xen,config {
+        scmi-secondary-agents = <
+            0x82000003 &scmi_shm_1
+            0x82000004 &scmi_shm_2
+            0x82000005 &scmi_shm_3
+            0x82000006 &scmi_shm_4>;
+            #scmi-secondary-agents-cells = <2>;
+        };
+    };
+};
diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
index 7a1f723e63..5a1c1e072c 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -1105,6 +1105,15 @@ which serves as Driver domain. The SCMI will be disabled for Dom0/hwdom and
 SCMI nodes removed from Dom0/hwdom device tree.
 (for example, thin Dom0 with Driver domain use-case).
 
+### dom0_scmi_agent_id (ARM)
+> `= <integer>`
+
+The option is available when `CONFIG_SCMI_SMC_MA` is compiled in, and allows to
+enable SCMI functionality for Dom0 by specifying a non-zero ARM SCMI agent id.
+The SCMI will be disabled for Dom0 if this option is not specified
+(for example, thin Dom0 or dom0less use-cases).
+The agent ids of domains existing on a single host must be unique.
+
 ### dtuart (ARM)
 > `= path [:options]`
 
diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
index e4407d6e3f..be0e6263ae 100644
--- a/tools/libs/light/libxl_arm.c
+++ b/tools/libs/light/libxl_arm.c
@@ -240,6 +240,10 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
     case LIBXL_ARM_SCI_TYPE_SCMI_SMC:
         config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
         break;
+    case LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT:
+        config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
+        config->arch.arm_sci_agent_id = d_config->b_info.arch_arm.arm_sci.agent_id;
+        break;
     default:
         LOG(ERROR, "Unknown ARM_SCI type %d",
             d_config->b_info.arch_arm.arm_sci.type);
diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
index c8bc0f8521..da7f87cd0c 100644
--- a/tools/libs/light/libxl_types.idl
+++ b/tools/libs/light/libxl_types.idl
@@ -553,11 +553,13 @@ libxl_sve_type = Enumeration("sve_type", [
 
 libxl_arm_sci_type = Enumeration("arm_sci_type", [
     (0, "none"),
-    (1, "scmi_smc")
+    (1, "scmi_smc"),
+    (2, "scmi_smc_multiagent")
     ], init_val = "LIBXL_ARM_SCI_TYPE_NONE")
 
 libxl_arm_sci = Struct("arm_sci", [
     ("type", libxl_arm_sci_type),
+    ("agent_id", uint8)
     ])
 
 libxl_rdm_reserve = Struct("rdm_reserve", [
diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
index 68d2ebeb9f..4c05b20c06 100644
--- a/tools/xl/xl_parse.c
+++ b/tools/xl/xl_parse.c
@@ -1306,6 +1306,18 @@ static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci,
             }
         }
 
+        if (MATCH_OPTION("agent_id", ptr, oparg)) {
+            unsigned long val = parse_ulong(oparg);
+
+            if (!val || val > 255) {
+                fprintf(stderr, "An invalid ARM_SCI agent_id specified (%lu). Valid range [1..255]\n",
+                        val);
+                ret = ERROR_INVAL;
+                goto parse_error;
+            }
+            arm_sci->agent_id = val;
+        }
+
         ptr = strtok(NULL, ",");
     }
 
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index d28143f98b..6ca17b0ce6 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -299,6 +299,17 @@ int __init domu_dt_sci_parse(struct dt_device_node *node,
         d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
     else if ( !strcmp(sci_type, "scmi_smc") )
         d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
+    else if ( !strcmp(sci_type, "scmi_smc_multiagent") )
+    {
+        uint32_t agent_id = 0;
+
+        if ( !dt_property_read_u32(node, "xen,sci_agent_id", &agent_id) ||
+             !agent_id )
+            return -EINVAL;
+
+        d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
+        d_cfg->arch.arm_sci_agent_id = agent_id;
+    }
     else
     {
         printk(XENLOG_ERR "xen,sci_type in not valid (%s) for domain %s\n",
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 92039cf213..ea13e374a0 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -508,7 +508,8 @@ static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
                  dt_property_name_is_equal(prop, "linux,uefi-mmap-start") ||
                  dt_property_name_is_equal(prop, "linux,uefi-mmap-size") ||
                  dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-size") ||
-                 dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-ver"))
+                 dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-ver") ||
+                 dt_property_name_is_equal(prop, "xen,config") )
                 continue;
 
             if ( dt_property_name_is_equal(prop, "xen,dom0-bootargs") )
diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
index 5c5f0880c4..972cd9b173 100644
--- a/xen/arch/arm/firmware/Kconfig
+++ b/xen/arch/arm/firmware/Kconfig
@@ -29,6 +29,18 @@ config SCMI_SMC
 	  driver domain.
 	  Use with EL3 firmware which supports only single SCMI OSPM agent.
 
+config SCMI_SMC_MA
+	bool "Enable ARM SCMI SMC multi-agent driver"
+	depends on ARM_64
+	select ARM_SCI
+	help
+	  Enables SCMI SMC/HVC multi-agent in XEN to pass SCMI requests from Domains
+	  to EL3 firmware (TF-A) which supports multi-agent feature.
+	  This feature allows to enable SCMI per Domain using unique SCMI agent_id,
+	  so Domain is identified by EL3 firmware as an SCMI Agent and can access
+	  allowed platform resources through dedicated SMC/HVC Shared memory based
+	  transport.
+
 endchoice
 
 endmenu
diff --git a/xen/arch/arm/firmware/Makefile b/xen/arch/arm/firmware/Makefile
index 71bdefc24a..37927e690e 100644
--- a/xen/arch/arm/firmware/Makefile
+++ b/xen/arch/arm/firmware/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_ARM_SCI) += sci.o
 obj-$(CONFIG_SCMI_SMC) += scmi-smc.o
+obj-$(CONFIG_SCMI_SMC_MA) += scmi-shmem.o scmi-smc-multiagent.o
diff --git a/xen/arch/arm/firmware/scmi-proto.h b/xen/arch/arm/firmware/scmi-proto.h
new file mode 100644
index 0000000000..e290d6630d
--- /dev/null
+++ b/xen/arch/arm/firmware/scmi-proto.h
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Arm System Control and Management Interface definitions
+ * Version 3.0 (DEN0056C)
+ *
+ * Copyright (c) 2024 EPAM Systems
+ */
+
+#ifndef ARM_FIRMWARE_SCMI_PROTO_H_
+#define ARM_FIRMWARE_SCMI_PROTO_H_
+
+#include <xen/stdint.h>
+
+#define SCMI_SHORT_NAME_MAX_SIZE 16
+
+/* SCMI status codes. See section 4.1.4 */
+#define SCMI_SUCCESS              0
+#define SCMI_NOT_SUPPORTED      (-1)
+#define SCMI_INVALID_PARAMETERS (-2)
+#define SCMI_DENIED             (-3)
+#define SCMI_NOT_FOUND          (-4)
+#define SCMI_OUT_OF_RANGE       (-5)
+#define SCMI_BUSY               (-6)
+#define SCMI_COMMS_ERROR        (-7)
+#define SCMI_GENERIC_ERROR      (-8)
+#define SCMI_HARDWARE_ERROR     (-9)
+#define SCMI_PROTOCOL_ERROR     (-10)
+
+/* Protocol IDs */
+#define SCMI_BASE_PROTOCOL 0x10
+
+/* Base protocol message IDs */
+#define SCMI_BASE_PROTOCOL_VERSION            0x0
+#define SCMI_BASE_PROTOCOL_ATTIBUTES          0x1
+#define SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES 0x2
+#define SCMI_BASE_DISCOVER_AGENT              0x7
+#define SCMI_BASE_SET_DEVICE_PERMISSIONS      0x9
+#define SCMI_BASE_RESET_AGENT_CONFIGURATION   0xB
+
+typedef struct scmi_msg_header {
+    uint8_t id;
+    uint8_t type;
+    uint8_t protocol;
+    uint32_t status;
+} scmi_msg_header_t;
+
+/* Table 2 Message header format */
+#define SCMI_HDR_ID    GENMASK(7, 0)
+#define SCMI_HDR_TYPE  GENMASK(9, 8)
+#define SCMI_HDR_PROTO GENMASK(17, 10)
+
+#define SCMI_FIELD_GET(_mask, _reg)                                            \
+    ((typeof(_mask))(((_reg) & (_mask)) >> (ffs64(_mask) - 1)))
+#define SCMI_FIELD_PREP(_mask, _val)                                           \
+    (((typeof(_mask))(_val) << (ffs64(_mask) - 1)) & (_mask))
+
+static inline uint32_t pack_scmi_header(scmi_msg_header_t *hdr)
+{
+    return SCMI_FIELD_PREP(SCMI_HDR_ID, hdr->id) |
+           SCMI_FIELD_PREP(SCMI_HDR_TYPE, hdr->type) |
+           SCMI_FIELD_PREP(SCMI_HDR_PROTO, hdr->protocol);
+}
+
+static inline void unpack_scmi_header(uint32_t msg_hdr, scmi_msg_header_t *hdr)
+{
+    hdr->id = SCMI_FIELD_GET(SCMI_HDR_ID, msg_hdr);
+    hdr->type = SCMI_FIELD_GET(SCMI_HDR_TYPE, msg_hdr);
+    hdr->protocol = SCMI_FIELD_GET(SCMI_HDR_PROTO, msg_hdr);
+}
+
+static inline int scmi_to_xen_errno(int scmi_status)
+{
+    if ( scmi_status == SCMI_SUCCESS )
+        return 0;
+
+    switch ( scmi_status )
+    {
+    case SCMI_NOT_SUPPORTED:
+        return -EOPNOTSUPP;
+    case SCMI_INVALID_PARAMETERS:
+        return -EINVAL;
+    case SCMI_DENIED:
+        return -EACCES;
+    case SCMI_NOT_FOUND:
+        return -ENOENT;
+    case SCMI_OUT_OF_RANGE:
+        return -ERANGE;
+    case SCMI_BUSY:
+        return -EBUSY;
+    case SCMI_COMMS_ERROR:
+        return -ENOTCONN;
+    case SCMI_GENERIC_ERROR:
+        return -EIO;
+    case SCMI_HARDWARE_ERROR:
+        return -ENXIO;
+    case SCMI_PROTOCOL_ERROR:
+        return -EBADMSG;
+    default:
+        return -EINVAL;
+    }
+}
+
+/* PROTOCOL_VERSION */
+#define SCMI_VERSION_MINOR GENMASK(15, 0)
+#define SCMI_VERSION_MAJOR GENMASK(31, 16)
+
+struct scmi_msg_prot_version_p2a {
+    uint32_t version;
+} __packed;
+
+/* BASE PROTOCOL_ATTRIBUTES */
+#define SCMI_BASE_ATTR_NUM_PROTO GENMASK(7, 0)
+#define SCMI_BASE_ATTR_NUM_AGENT GENMASK(15, 8)
+
+struct scmi_msg_base_attributes_p2a {
+    uint32_t attributes;
+} __packed;
+
+/*
+ * BASE_DISCOVER_AGENT
+ */
+#define SCMI_BASE_AGENT_ID_OWN 0xFFFFFFFF
+
+struct scmi_msg_base_discover_agent_a2p {
+    uint32_t agent_id;
+} __packed;
+
+struct scmi_msg_base_discover_agent_p2a {
+    uint32_t agent_id;
+    char name[SCMI_SHORT_NAME_MAX_SIZE];
+} __packed;
+
+/*
+ * BASE_SET_DEVICE_PERMISSIONS
+ */
+#define SCMI_BASE_DEVICE_ACCESS_ALLOW           BIT(0, UL)
+
+struct scmi_msg_base_set_device_permissions_a2p {
+    uint32_t agent_id;
+    uint32_t device_id;
+    uint32_t flags;
+} __packed;
+
+/*
+ * BASE_RESET_AGENT_CONFIGURATION
+ */
+#define SCMI_BASE_AGENT_PERMISSIONS_RESET       BIT(0, UL)
+
+struct scmi_msg_base_reset_agent_cfg_a2p {
+    uint32_t agent_id;
+    uint32_t flags;
+} __packed;
+
+#endif /* ARM_FIRMWARE_SCMI_PROTO_H_ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/firmware/scmi-shmem.c b/xen/arch/arm/firmware/scmi-shmem.c
new file mode 100644
index 0000000000..8fc8ca356b
--- /dev/null
+++ b/xen/arch/arm/firmware/scmi-shmem.c
@@ -0,0 +1,112 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * SCI SCMI multi-agent driver, using SMC/HVC shmem as transport.
+ *
+ * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
+ * Copyright (c) 2025 EPAM Systems
+ */
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <asm/io.h>
+#include <xen/err.h>
+#include <xen/lib/arm/io.h>
+
+#include "scmi-proto.h"
+#include "scmi-shmem.h"
+
+static inline int
+shmem_channel_is_free(const volatile struct scmi_shared_mem __iomem *shmem)
+{
+    return (readl(&shmem->channel_status) &
+            SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE) ? 0 : -EBUSY;
+}
+
+int shmem_put_message(volatile struct scmi_shared_mem __iomem *shmem,
+                      scmi_msg_header_t *hdr, void *data, int len)
+{
+    int ret;
+
+    if ( (len + sizeof(shmem->msg_header)) > SCMI_SHMEM_MAPPED_SIZE )
+    {
+        printk(XENLOG_ERR "scmi: Wrong size of smc message. Data is invalid\n");
+        return -EINVAL;
+    }
+
+    ret = shmem_channel_is_free(shmem);
+    if ( ret )
+        return ret;
+
+    writel_relaxed(0x0, &shmem->channel_status);
+    /* Writing 0x0 right now, but "shmem"_FLAG_INTR_ENABLED can be set */
+    writel_relaxed(0x0, &shmem->flags);
+    writel_relaxed(sizeof(shmem->msg_header) + len, &shmem->length);
+    writel(pack_scmi_header(hdr), &shmem->msg_header);
+
+    if ( len > 0 && data )
+        __memcpy_toio(shmem->msg_payload, data, len);
+
+    return 0;
+}
+
+int shmem_get_response(const volatile struct scmi_shared_mem __iomem *shmem,
+                       scmi_msg_header_t *hdr, void *data, int len)
+{
+    int recv_len;
+    int ret;
+    int pad = sizeof(hdr->status);
+
+    if ( len >= SCMI_SHMEM_MAPPED_SIZE - sizeof(shmem) )
+    {
+        printk(XENLOG_ERR
+               "scmi: Wrong size of input smc message. Data may be invalid\n");
+        return -EINVAL;
+    }
+
+    ret = shmem_channel_is_free(shmem);
+    if ( ret )
+        return ret;
+
+    recv_len = readl(&shmem->length) - sizeof(shmem->msg_header);
+
+    if ( recv_len < 0 )
+    {
+        printk(XENLOG_ERR
+               "scmi: Wrong size of smc message. Data may be invalid\n");
+        return -EINVAL;
+    }
+
+    unpack_scmi_header(readl(&shmem->msg_header), hdr);
+
+    hdr->status = readl(&shmem->msg_payload);
+    recv_len = recv_len > pad ? recv_len - pad : 0;
+
+    ret = scmi_to_xen_errno(hdr->status);
+    if ( ret )
+    {
+        printk(XENLOG_DEBUG "scmi: Error received: %d\n", ret);
+        return ret;
+    }
+
+    if ( recv_len > len )
+    {
+        printk(XENLOG_ERR
+               "scmi: Not enough buffer for message %d, expecting %d\n",
+               recv_len, len);
+        return -EINVAL;
+    }
+
+    if ( recv_len > 0 )
+        __memcpy_fromio(data, shmem->msg_payload + pad, recv_len);
+
+    return 0;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/firmware/scmi-shmem.h b/xen/arch/arm/firmware/scmi-shmem.h
new file mode 100644
index 0000000000..7313cb6b26
--- /dev/null
+++ b/xen/arch/arm/firmware/scmi-shmem.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Arm System Control and Management Interface definitions
+ * Version 3.0 (DEN0056C)
+ * Shared Memory based Transport
+ *
+ * Copyright (c) 2024 EPAM Systems
+ */
+
+#ifndef ARM_FIRMWARE_SCMI_SHMEM_H_
+#define ARM_FIRMWARE_SCMI_SHMEM_H_
+
+#include <xen/stdint.h>
+
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE  BIT(0, UL)
+#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1, UL)
+
+struct scmi_shared_mem {
+    uint32_t reserved;
+    uint32_t channel_status;
+    uint32_t reserved1[2];
+    uint32_t flags;
+    uint32_t length;
+    uint32_t msg_header;
+    uint8_t msg_payload[];
+};
+
+#define SCMI_SHMEM_MAPPED_SIZE PAGE_SIZE
+
+int shmem_put_message(volatile struct scmi_shared_mem __iomem *shmem,
+                      scmi_msg_header_t *hdr, void *data, int len);
+
+int shmem_get_response(const volatile struct scmi_shared_mem __iomem *shmem,
+                       scmi_msg_header_t *hdr, void *data, int len);
+#endif /* ARM_FIRMWARE_SCMI_SHMEM_H_ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/firmware/scmi-smc-multiagent.c b/xen/arch/arm/firmware/scmi-smc-multiagent.c
new file mode 100644
index 0000000000..9f839147d4
--- /dev/null
+++ b/xen/arch/arm/firmware/scmi-smc-multiagent.c
@@ -0,0 +1,803 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * SCI SCMI multi-agent driver, using SMC/HVC shmem as transport.
+ *
+ * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
+ * Copyright (c) 2025 EPAM Systems
+ */
+
+#include <xen/acpi.h>
+
+#include <xen/device_tree.h>
+#include <xen/init.h>
+#include <xen/iocap.h>
+#include <xen/err.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/param.h>
+#include <xen/sched.h>
+#include <xen/vmap.h>
+
+#include <asm/firmware/sci.h>
+#include <asm/smccc.h>
+
+#include "scmi-proto.h"
+#include "scmi-shmem.h"
+
+#define SCMI_AGENT_ID_INVALID 0xFF
+
+static uint8_t __initdata opt_dom0_scmi_agent_id = SCMI_AGENT_ID_INVALID;
+integer_param("dom0_scmi_agent_id", opt_dom0_scmi_agent_id);
+
+#define SCMI_SECONDARY_AGENTS "scmi-secondary-agents"
+
+struct scmi_channel {
+    uint32_t agent_id;
+    uint32_t func_id;
+    domid_t domain_id;
+    uint64_t paddr;
+    uint64_t len;
+    struct scmi_shared_mem __iomem *shmem;
+    spinlock_t lock;
+    struct list_head list;
+};
+
+struct scmi_data {
+    struct list_head channel_list;
+    spinlock_t channel_list_lock;
+    uint32_t func_id;
+    bool initialized;
+    uint32_t shmem_phandle;
+    uint32_t hyp_channel_agent_id;
+    struct dt_device_node *dt_dev;
+};
+
+static struct scmi_data scmi_data;
+
+static int send_smc_message(struct scmi_channel *chan_info,
+                            scmi_msg_header_t *hdr, void *data, int len)
+{
+    struct arm_smccc_res resp;
+    int ret;
+
+    ret = shmem_put_message(chan_info->shmem, hdr, data, len);
+    if ( ret )
+        return ret;
+
+    arm_smccc_1_1_smc(chan_info->func_id, 0, 0, 0, 0, 0, 0, 0, &resp);
+
+    if ( resp.a0 == ARM_SMCCC_INVALID_PARAMETER )
+        return -EINVAL;
+
+    if ( resp.a0 )
+        return -EOPNOTSUPP;
+
+    return 0;
+}
+
+static int do_smc_xfer(struct scmi_channel *chan_info, scmi_msg_header_t *hdr,
+                       void *tx_data, int tx_size, void *rx_data, int rx_size)
+{
+    int ret = 0;
+
+    ASSERT(chan_info && chan_info->shmem);
+
+    if ( !hdr )
+        return -EINVAL;
+
+    spin_lock(&chan_info->lock);
+
+    printk(XENLOG_DEBUG
+           "scmi: agent_id = %d msg_id = %x type = %d, proto = %x\n",
+           chan_info->agent_id, hdr->id, hdr->type, hdr->protocol);
+
+    ret = send_smc_message(chan_info, hdr, tx_data, tx_size);
+    if ( ret )
+        goto clean;
+
+    ret = shmem_get_response(chan_info->shmem, hdr, rx_data, rx_size);
+
+clean:
+    printk(XENLOG_DEBUG
+           "scmi: get smc response agent_id = %d msg_id = %x proto = %x res=%d\n",
+           chan_info->agent_id, hdr->id, hdr->protocol, ret);
+
+    spin_unlock(&chan_info->lock);
+
+    return ret;
+}
+
+static struct scmi_channel *get_channel_by_id(uint32_t agent_id)
+{
+    struct scmi_channel *curr;
+    bool found = false;
+
+    spin_lock(&scmi_data.channel_list_lock);
+    list_for_each_entry(curr, &scmi_data.channel_list, list)
+    {
+        if ( curr->agent_id == agent_id )
+        {
+            found = true;
+            break;
+        }
+    }
+
+    spin_unlock(&scmi_data.channel_list_lock);
+    if ( found )
+        return curr;
+
+    return NULL;
+}
+
+static struct scmi_channel *acquire_scmi_channel(struct domain *d,
+                                                 uint32_t agent_id)
+{
+    struct scmi_channel *curr;
+    struct scmi_channel *ret = ERR_PTR(-ENOENT);
+
+    spin_lock(&scmi_data.channel_list_lock);
+    list_for_each_entry(curr, &scmi_data.channel_list, list)
+    {
+        if ( curr->agent_id == agent_id )
+        {
+            if ( curr->domain_id != DOMID_INVALID )
+            {
+                ret = ERR_PTR(-EEXIST);
+                break;
+            }
+
+            curr->domain_id = d->domain_id;
+            ret = curr;
+            break;
+        }
+    }
+
+    spin_unlock(&scmi_data.channel_list_lock);
+
+    return ret;
+}
+
+static void relinquish_scmi_channel(struct scmi_channel *channel)
+{
+    ASSERT(channel != NULL);
+
+    spin_lock(&scmi_data.channel_list_lock);
+    channel->domain_id = DOMID_INVALID;
+    spin_unlock(&scmi_data.channel_list_lock);
+}
+
+static int map_channel_memory(struct scmi_channel *channel)
+{
+    ASSERT(channel && channel->paddr);
+    channel->shmem = ioremap_nocache(channel->paddr, SCMI_SHMEM_MAPPED_SIZE);
+    if ( !channel->shmem )
+        return -ENOMEM;
+
+    channel->shmem->channel_status = SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE;
+    printk(XENLOG_DEBUG "scmi: Got shmem %lx after vmap %p\n", channel->paddr,
+           channel->shmem);
+
+    return 0;
+}
+
+static void unmap_channel_memory(struct scmi_channel *channel)
+{
+    ASSERT(channel && channel->shmem);
+    iounmap(channel->shmem);
+    channel->shmem = NULL;
+}
+
+static struct scmi_channel *smc_create_channel(uint32_t agent_id,
+                                               uint32_t func_id, uint64_t addr)
+{
+    struct scmi_channel *channel;
+
+    channel = get_channel_by_id(agent_id);
+    if ( channel )
+        return ERR_PTR(EEXIST);
+
+    channel = xmalloc(struct scmi_channel);
+    if ( !channel )
+        return ERR_PTR(ENOMEM);
+
+    spin_lock_init(&channel->lock);
+    channel->agent_id = agent_id;
+    channel->func_id = func_id;
+    channel->domain_id = DOMID_INVALID;
+    channel->shmem = NULL;
+    channel->paddr = addr;
+    list_add_tail(&channel->list, &scmi_data.channel_list);
+    return channel;
+}
+
+static void free_channel_list(void)
+{
+    struct scmi_channel *curr, *_curr;
+
+    list_for_each_entry_safe(curr, _curr, &scmi_data.channel_list, list)
+    {
+        list_del(&curr->list);
+        xfree(curr);
+    }
+}
+
+static int __init
+scmi_dt_read_hyp_channel_addr(struct dt_device_node *scmi_node, u64 *addr,
+                              u64 *size)
+{
+    struct dt_device_node *shmem_node;
+    const __be32 *prop;
+
+    prop = dt_get_property(scmi_node, "shmem", NULL);
+    if ( !prop )
+        return -EINVAL;
+
+    shmem_node = dt_find_node_by_phandle(be32_to_cpu(*prop));
+    if ( IS_ERR_OR_NULL(shmem_node) )
+    {
+        printk(XENLOG_ERR
+               "scmi: Device tree error, can't parse reserved memory %ld\n",
+               PTR_ERR(shmem_node));
+        return PTR_ERR(shmem_node);
+    }
+
+    return dt_device_get_address(shmem_node, 0, addr, size);
+}
+
+/*
+ * Handle Dom0 SCMI specific DT nodes
+ *
+ * Make a decision on copying SCMI specific nodes into Dom0 device tree.
+ * For SCMI multi-agent case:
+ * - shmem nodes will not be copied and generated instead if SCMI
+ *   is enabled for Dom0
+ * - scmi node will be copied if SCMI is enabled for Dom0
+ */
+static bool scmi_dt_handle_node(struct domain *d, struct dt_device_node *node)
+{
+    static const struct dt_device_match shmem_matches[] __initconst = {
+        DT_MATCH_COMPATIBLE("arm,scmi-shmem"),
+        { /* sentinel */ },
+    };
+    static const struct dt_device_match scmi_matches[] __initconst = {
+        DT_MATCH_PATH("/firmware/scmi"),
+        { /* sentinel */ },
+    };
+
+    if ( !scmi_data.initialized )
+        return false;
+
+    /* skip scmi shmem node for dom0 if scmi not enabled */
+    if ( dt_match_node(shmem_matches, node) && !sci_domain_is_enabled(d) )
+    {
+        dt_dprintk("  Skip scmi shmem node\n");
+        return true;
+    }
+
+    /* drop scmi if not enabled */
+    if ( dt_match_node(scmi_matches, node) && !sci_domain_is_enabled(d) )
+    {
+        dt_dprintk("  Skip scmi node\n");
+        return true;
+    }
+
+    return false;
+}
+
+static int scmi_assign_device(uint32_t agent_id, uint32_t device_id,
+                              uint32_t flags)
+{
+    struct scmi_msg_base_set_device_permissions_a2p tx;
+    struct scmi_channel *channel;
+    scmi_msg_header_t hdr;
+
+    channel = get_channel_by_id(scmi_data.hyp_channel_agent_id);
+    if ( !channel )
+        return -EINVAL;
+
+    hdr.id = SCMI_BASE_SET_DEVICE_PERMISSIONS;
+    hdr.type = 0;
+    hdr.protocol = SCMI_BASE_PROTOCOL;
+
+    tx.agent_id = agent_id;
+    tx.device_id = device_id;
+    tx.flags = flags;
+
+    return do_smc_xfer(channel, &hdr, &tx, sizeof(tx), NULL, 0);
+}
+
+static int scmi_dt_assign_device(struct domain *d,
+                                 struct dt_phandle_args *ac_spec)
+{
+    struct scmi_channel *agent_channel;
+    uint32_t scmi_device_id = ac_spec->args[0];
+    int ret;
+
+    if ( !d->arch.sci_data )
+        return 0;
+
+    /* The access-controllers is specified for DT dev, but it's not a SCMI */
+    if ( ac_spec->np != scmi_data.dt_dev )
+        return 0;
+
+    agent_channel = d->arch.sci_data;
+
+    spin_lock(&agent_channel->lock);
+
+    ret = scmi_assign_device(agent_channel->agent_id, scmi_device_id,
+                             SCMI_BASE_DEVICE_ACCESS_ALLOW);
+    if ( ret )
+    {
+        printk(XENLOG_ERR
+               "scmi: could not assign dev for %pd agent:%d dev_id:%u (%d)",
+               d, agent_channel->agent_id, scmi_device_id, ret);
+    }
+
+    spin_unlock(&agent_channel->lock);
+    return ret;
+}
+
+static int collect_agent_id(struct scmi_channel *agent_channel)
+{
+    int ret;
+    scmi_msg_header_t hdr;
+    struct scmi_msg_base_discover_agent_p2a da_rx;
+    struct scmi_msg_base_discover_agent_a2p da_tx;
+
+    ret = map_channel_memory(agent_channel);
+    if ( ret )
+        return ret;
+
+    hdr.id = SCMI_BASE_DISCOVER_AGENT;
+    hdr.type = 0;
+    hdr.protocol = SCMI_BASE_PROTOCOL;
+
+    da_tx.agent_id = agent_channel->agent_id;
+
+    ret = do_smc_xfer(agent_channel, &hdr, &da_tx, sizeof(da_tx), &da_rx,
+                        sizeof(da_rx));
+    if ( agent_channel->domain_id != DOMID_XEN )
+        unmap_channel_memory(agent_channel);
+    if ( ret )
+        return ret;
+
+    printk(XENLOG_DEBUG "id=0x%x name=%s\n", da_rx.agent_id, da_rx.name);
+    agent_channel->agent_id = da_rx.agent_id;
+    return 0;
+}
+
+static __init int collect_agents(struct dt_device_node *scmi_node)
+{
+    const struct dt_device_node *config_node;
+    const __be32 *prop;
+    uint32_t len;
+    const __be32 *end;
+    uint32_t cells_per_entry = 3; /* Default to 3 cells if property is absent. */
+
+    config_node = dt_find_node_by_path("/chosen/xen,config");
+    if ( !config_node )
+    {
+        printk(XENLOG_WARNING "scmi: /chosen/xen,config node not found, no agents to collect.\n");
+        return -ENOENT;
+    }
+
+    /* Check for the optional '#scmi-secondary-agents-cells' property. */
+    if ( dt_property_read_u32(config_node, "#scmi-secondary-agents-cells",
+                              &cells_per_entry) )
+    {
+        if ( cells_per_entry != 2 && cells_per_entry != 3 )
+        {
+            printk(XENLOG_ERR "scmi: Invalid #scmi-secondary-agents-cells value: %u\n",
+                   cells_per_entry);
+            return -EINVAL;
+        }
+    }
+
+    prop = dt_get_property(config_node, SCMI_SECONDARY_AGENTS, &len);
+    if ( !prop )
+    {
+        /* This is not an error, as there may be no secondary agents. */
+        printk(XENLOG_WARNING "scmi: No %s property found, no agents to collect.\n",
+               SCMI_SECONDARY_AGENTS);
+        return -EINVAL;
+    }
+
+    /* Validate that the property length is a multiple of the cell size. */
+    if ( len == 0 || len % (cells_per_entry * sizeof(uint32_t)) != 0 )
+    {
+        printk(XENLOG_ERR "scmi: Invalid length of %s property: %u for %u cells per entry\n",
+               SCMI_SECONDARY_AGENTS, len, cells_per_entry);
+        return -EINVAL;
+    }
+
+    end = (const __be32 *)((const u8 *)prop + len);
+
+    for ( ; prop < end; )
+    {
+        uint32_t agent_id;
+        uint32_t smc_id;
+        uint32_t shmem_phandle;
+        struct dt_device_node *node;
+        u64 addr, size;
+        int ret;
+        struct scmi_channel *agent_channel;
+
+        smc_id = be32_to_cpu(*prop++);
+        shmem_phandle = be32_to_cpu(*prop++);
+
+        if ( cells_per_entry == 3 )
+            agent_id = be32_to_cpu(*prop++);
+        else
+            agent_id = SCMI_BASE_AGENT_ID_OWN;
+
+        node = dt_find_node_by_phandle(shmem_phandle);
+        if ( !node )
+        {
+            printk(XENLOG_ERR "scmi: Could not find shmem node for agent %u\n",
+                   agent_id);
+            return -EINVAL;
+        }
+
+        ret = dt_device_get_address(node, 0, &addr, &size);
+        if ( ret )
+        {
+            printk(XENLOG_ERR
+                   "scmi: Could not read shmem address for agent %u: %d\n",
+                   agent_id, ret);
+            return ret;
+        }
+
+        if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) )
+        {
+            printk(XENLOG_ERR "scmi: shmem memory is not aligned\n");
+            return -EINVAL;
+        }
+
+        agent_channel = smc_create_channel(agent_id, smc_id, addr);
+        if ( IS_ERR(agent_channel) )
+        {
+            printk(XENLOG_ERR "scmi: Could not create channel for agent %u: %ld\n",
+                   agent_id, PTR_ERR(agent_channel));
+            return PTR_ERR(agent_channel);
+        }
+
+        if ( cells_per_entry == 2 )
+        {
+            ret = collect_agent_id(agent_channel);
+            if ( ret )
+                return ret;
+        }
+
+        printk(XENLOG_DEBUG "scmi: Agent %u SMC %X addr %lx\n", agent_channel->agent_id,
+               smc_id, (unsigned long)addr);
+    }
+
+    return 0;
+}
+
+static int scmi_domain_init(struct domain *d,
+                            struct xen_domctl_createdomain *config)
+{
+    struct scmi_channel *channel;
+    int ret;
+
+    if ( !scmi_data.initialized )
+        return 0;
+
+    /*
+     * Special case for Dom0 - the SCMI support is enabled basing on
+     * "dom0_sci_agent_id" Xen command line parameter
+     */
+    if ( is_hardware_domain(d) )
+    {
+        if ( opt_dom0_scmi_agent_id != SCMI_AGENT_ID_INVALID )
+        {
+            config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
+            config->arch.arm_sci_agent_id = opt_dom0_scmi_agent_id;
+        }
+        else
+            config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
+    }
+
+    if ( config->arch.arm_sci_type == XEN_DOMCTL_CONFIG_ARM_SCI_NONE )
+        return 0;
+
+    channel = acquire_scmi_channel(d, config->arch.arm_sci_agent_id);
+    if ( IS_ERR(channel) )
+    {
+        printk(XENLOG_ERR
+               "scmi: Failed to acquire SCMI channel for agent_id %u: %ld\n",
+               config->arch.arm_sci_agent_id, PTR_ERR(channel));
+        return PTR_ERR(channel);
+    }
+
+    printk(XENLOG_INFO
+           "scmi: Acquire channel id = 0x%x, domain_id = %d paddr = 0x%lx\n",
+           channel->agent_id, channel->domain_id, channel->paddr);
+
+    /*
+     * Dom0 (if present) needs to have an access to the guest memory range
+     * to satisfy iomem_access_permitted() check in XEN_DOMCTL_iomem_permission
+     * domctl.
+     */
+    if ( hardware_domain && !is_hardware_domain(d) )
+    {
+        ret = iomem_permit_access(hardware_domain, paddr_to_pfn(channel->paddr),
+                                  paddr_to_pfn(channel->paddr + PAGE_SIZE - 1));
+        if ( ret )
+            goto error;
+    }
+
+    d->arch.sci_data = channel;
+    d->arch.sci_enabled = true;
+
+    return 0;
+
+error:
+    relinquish_scmi_channel(channel);
+    return ret;
+}
+
+int scmi_domain_sanitise_config(struct xen_domctl_createdomain *config)
+{
+    if ( config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_NONE &&
+         config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA )
+    {
+        dprintk(XENLOG_INFO, "scmi: Unsupported ARM_SCI type\n");
+        return -EINVAL;
+    }
+    else if ( config->arch.arm_sci_type ==
+              XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA &&
+              config->arch.arm_sci_agent_id == 0 )
+    {
+        dprintk(XENLOG_INFO,
+                "scmi: A zero ARM SCMI agent_id is not supported\n");
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static int scmi_relinquish_resources(struct domain *d)
+{
+    int ret;
+    struct scmi_channel *channel, *agent_channel;
+    scmi_msg_header_t hdr;
+    struct scmi_msg_base_reset_agent_cfg_a2p tx;
+
+    if ( !d->arch.sci_data )
+        return 0;
+
+    agent_channel = d->arch.sci_data;
+
+    spin_lock(&agent_channel->lock);
+    tx.agent_id = agent_channel->agent_id;
+    spin_unlock(&agent_channel->lock);
+
+    channel = get_channel_by_id(scmi_data.hyp_channel_agent_id);
+    if ( !channel )
+    {
+        printk(XENLOG_ERR
+               "scmi: Unable to get Hypervisor scmi channel for domain %d\n",
+               d->domain_id);
+        return -EINVAL;
+    }
+
+    hdr.id = SCMI_BASE_RESET_AGENT_CONFIGURATION;
+    hdr.type = 0;
+    hdr.protocol = SCMI_BASE_PROTOCOL;
+
+    tx.flags = 0;
+
+    ret = do_smc_xfer(channel, &hdr, &tx, sizeof(tx), NULL, 0);
+    if ( ret == -EOPNOTSUPP )
+        return 0;
+
+    return ret;
+}
+
+static void scmi_domain_destroy(struct domain *d)
+{
+    struct scmi_channel *channel;
+
+    if ( !d->arch.sci_data )
+        return;
+
+    channel = d->arch.sci_data;
+    spin_lock(&channel->lock);
+
+    relinquish_scmi_channel(channel);
+    printk(XENLOG_DEBUG "scmi: Free domain %d\n", d->domain_id);
+
+    d->arch.sci_data = NULL;
+    d->arch.sci_enabled = true;
+
+    spin_unlock(&channel->lock);
+}
+
+static bool scmi_handle_call(struct cpu_user_regs *regs)
+{
+    uint32_t fid = (uint32_t)get_user_reg(regs, 0);
+    struct scmi_channel *agent_channel;
+    struct domain *d = current->domain;
+    struct arm_smccc_res resp;
+    bool res = false;
+
+    if ( !sci_domain_is_enabled(d) )
+        return false;
+
+    agent_channel = d->arch.sci_data;
+    spin_lock(&agent_channel->lock);
+
+    if ( agent_channel->func_id != fid )
+    {
+        res = false;
+        goto unlock;
+    }
+
+    arm_smccc_1_1_smc(fid,
+                      get_user_reg(regs, 1),
+                      get_user_reg(regs, 2),
+                      get_user_reg(regs, 3),
+                      get_user_reg(regs, 4),
+                      get_user_reg(regs, 5),
+                      get_user_reg(regs, 6),
+                      get_user_reg(regs, 7),
+                      &resp);
+
+    set_user_reg(regs, 0, resp.a0);
+    set_user_reg(regs, 1, resp.a1);
+    set_user_reg(regs, 2, resp.a2);
+    set_user_reg(regs, 3, resp.a3);
+    res = true;
+unlock:
+    spin_unlock(&agent_channel->lock);
+
+    return res;
+}
+
+static const struct sci_mediator_ops scmi_ops = {
+    .domain_init = scmi_domain_init,
+    .domain_destroy = scmi_domain_destroy,
+    .relinquish_resources = scmi_relinquish_resources,
+    .handle_call = scmi_handle_call,
+    .dom0_dt_handle_node = scmi_dt_handle_node,
+    .domain_sanitise_config = scmi_domain_sanitise_config,
+    .assign_dt_device = scmi_dt_assign_device,
+};
+
+static int __init scmi_check_smccc_ver(void)
+{
+    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
+    {
+        printk(XENLOG_WARNING
+               "scmi: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
+        return -ENOSYS;
+    }
+
+    return 0;
+}
+
+static int scmi_dt_hyp_channel_read(struct dt_device_node *scmi_node, struct scmi_data *scmi_data,
+                                    u64 *addr)
+{
+    int ret;
+    u64 size;
+
+    if ( !dt_property_read_u32(scmi_node, "arm,smc-id", &scmi_data->func_id) )
+    {
+        printk(XENLOG_ERR "scmi: unable to read smc-id from DT\n");
+        return -ENOENT;
+    }
+
+    ret = scmi_dt_read_hyp_channel_addr(scmi_node, addr, &size);
+    if ( IS_ERR_VALUE(ret) )
+        return -ENOENT;
+
+    if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) )
+    {
+        printk(XENLOG_ERR "scmi: shmem memory is not aligned\n");
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+static __init int scmi_probe(struct dt_device_node *scmi_node, const void *data)
+{
+    u64 addr;
+    int ret;
+    struct scmi_channel *channel;
+    int n_agents;
+    scmi_msg_header_t hdr;
+    struct scmi_msg_base_attributes_p2a rx;
+
+    ASSERT(scmi_node != NULL);
+
+    INIT_LIST_HEAD(&scmi_data.channel_list);
+    spin_lock_init(&scmi_data.channel_list_lock);
+
+    if ( !acpi_disabled )
+    {
+        printk(XENLOG_WARNING "scmi: is not supported when using ACPI\n");
+        return -EINVAL;
+    }
+
+    ret = scmi_check_smccc_ver();
+    if ( ret )
+        return ret;
+
+    ret = scmi_dt_hyp_channel_read(scmi_node, &scmi_data, &addr);
+    if ( ret )
+        return ret;
+
+    scmi_data.dt_dev = scmi_node;
+
+    channel = smc_create_channel(SCMI_BASE_AGENT_ID_OWN, scmi_data.func_id, addr);
+    if ( IS_ERR(channel) )
+        goto out;
+
+    /* Request agent id for Xen management channel  */
+    ret = collect_agent_id(channel);
+    if ( ret )
+        return ret;
+
+    /* Save the agent id for Xen management channel */
+    scmi_data.hyp_channel_agent_id = channel->agent_id;
+
+    ret = map_channel_memory(channel);
+    if ( ret )
+        goto out;
+
+    channel->domain_id = DOMID_XEN;
+
+    hdr.id = SCMI_BASE_PROTOCOL_ATTIBUTES;
+    hdr.type = 0;
+    hdr.protocol = SCMI_BASE_PROTOCOL;
+
+    ret = do_smc_xfer(channel, &hdr, NULL, 0, &rx, sizeof(rx));
+    if ( ret )
+        goto error;
+
+    n_agents = SCMI_FIELD_GET(SCMI_BASE_ATTR_NUM_AGENT, rx.attributes);
+    printk(XENLOG_DEBUG "scmi: Got agent count %d\n", n_agents);
+    ret = collect_agents(scmi_node);
+    if ( ret )
+        goto error;
+
+    ret = sci_register(&scmi_ops);
+    if ( ret )
+    {
+        printk(XENLOG_ERR "SCMI: mediator already registered (ret = %d)\n",
+               ret);
+        return ret;
+    }
+
+    scmi_data.initialized = true;
+    goto out;
+
+error:
+    unmap_channel_memory(channel);
+    free_channel_list();
+out:
+    return ret;
+}
+
+static const struct dt_device_match scmi_smc_match[] __initconst = {
+    DT_MATCH_PATH("/chosen/xen,config/scmi"),
+    { /* sentinel */ },
+};
+
+DT_DEVICE_START(scmi_smc_ma, "SCMI SMC MEDIATOR", DEVICE_FIRMWARE)
+        .dt_match = scmi_smc_match,
+        .init = scmi_probe,
+DT_DEVICE_END
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index 095b1a23e3..30e46de6d7 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -329,6 +329,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 
 #define XEN_DOMCTL_CONFIG_ARM_SCI_NONE      0
 #define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC  1
+#define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA  2
 
 struct xen_arch_domainconfig {
     /* IN/OUT */
@@ -355,6 +356,8 @@ struct xen_arch_domainconfig {
     uint32_t clock_frequency;
     /* IN */
     uint8_t arm_sci_type;
+    /* IN */
+    uint8_t arm_sci_agent_id;
 };
 #endif /* __XEN__ || __XEN_TOOLS__ */
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [RFC PATCH v5 10/10] docs: arm: add SCI SCMI SMC multi-agent driver docs
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (8 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers Oleksii Moisieiev
@ 2025-07-22 11:41 ` Oleksii Moisieiev
  2025-08-26  0:44   ` Stefano Stabellini
  2025-08-23  0:34 ` [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Stefano Stabellini
  10 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 11:41 UTC (permalink / raw)
  To: xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Oleksii Moisieiev,
	Roger Pau Monné, Stefano Stabellini, Volodymyr Babchuk,
	Grygorii Strashko

From: Grygorii Strashko <grygorii_strashko@epam.com>

Add SCI SCMI SMC multi-agent driver documentation.
It includes a detailed description of the SCMI multi-agent driver.
This document explains the driver's functionality, configuration,
and the compilation process. The Xen SCMI multi-agent driver is
designed to provide SCMI access to system resources from different
domains.

Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
---

Changes in v5:
- rework multi-agent driver to leave Host Device-tree unmodified

 .../arm/firmware/arm-scmi.rst                 | 341 +++++++++++++++++-
 1 file changed, 340 insertions(+), 1 deletion(-)

diff --git a/docs/hypervisor-guide/arm/firmware/arm-scmi.rst b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
index a084c0caa3..2ab56af879 100644
--- a/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
+++ b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
@@ -31,7 +31,10 @@ domain serving as Driver domain).
 
 The below sections describe SCMI support options available for Xen.
 
-[1] `Arm SCMI <https://developer.arm.com/documentation/den0056/latest/>`_
+| [1] `Arm SCMI <https://developer.arm.com/documentation/den0056/latest/>`_
+| [2] `System Control and Management Interface (SCMI) bindings <https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml>`_
+| [3] `Generic Domain Access Controllers bindings <https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml>`_
+
 
 Simple SCMI over SMC/HVC calls forwarding driver (EL3)
 ------------------------------------------------------
@@ -175,3 +178,339 @@ enabling SCMI with "arm_sci" xl.cfg option.
     ->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
     ->        xen,force-assign-without-iommu;
       };
+
+SCMI SMC/HVC multi-agent driver (EL3)
+-------------------------------------
+
+The SCMI SMC/HVC multi-agent driver enables support for ARM EL3 Trusted Firmware-A (TF-A) which
+provides SCMI interface with multi-agnet support, as shown below.
+
+::
+
+      +-----------------------------------------+
+      |                                         |
+      | EL3 TF-A SCMI                           |
+      +-------+--+-------+--+-------+--+-------++
+      |shmem1 |  |shmem0 |  |shmem2 |  |shmemX |
+      +-----+-+  +---+---+  +--+----+  +---+---+
+    smc-id1 |        |         |           |
+    agent1  |        |         |           |
+      +-----v--------+---------+-----------+----+
+      |              |         |           |    |
+      |              |         |           |    |
+      +--------------+---------+-----------+----+
+             smc-id0 |  smc-id2|    smc-idX|
+             agent0  |  agent2 |    agentX |
+                     |         |           |
+                +----v---+  +--v-----+  +--v-----+
+                |        |  |        |  |        |
+                | Dom0   |  | Dom1   |  | DomX   |
+                |        |  |        |  |        |
+                |        |  |        |  |        |
+                +--------+  +--------+  +--------+
+
+The EL3 SCMI multi-agent firmware expected to provide SCMI SMC/HVC shared-memory transport
+for every Agent in the system. The SCMI Agent transport channel defined by pair:
+
+- smc-id: SMC/HVC function id used for Doorbell
+- shmem: shared memory for messages transfer, **Xen page aligned**.
+  Shared memory is mapped with the following flags: MT_DEVICE_nGnRE and _PAGE_DEVICE, indicating that this
+  memory is mapped as device memory.
+
+The following SCMI Agents expected to be defined by SCMI FW to enable SCMI multi-agent functionality
+under Xen:
+
+- Xen management agent: trusted agents that accesses to the Base Protocol commands to configure
+  agent specific permissions
+- OSPM VM agents: non-trusted agent, one for each Guest domain which is  allowed direct HW access.
+  At least one OSPM VM agent has to be provided by FW if HW is handled only by Dom0 or Driver Domain.
+
+The EL3 SCMI FW expected to implement following Base protocol messages:
+
+- BASE_DISCOVER_AGENT (optional if agent_id was provided)
+- BASE_RESET_AGENT_CONFIGURATION (optional)
+- BASE_SET_DEVICE_PERMISSIONS (optional)
+
+The number of supported SCMI agents and their transport specifications are SCMI FW implementation
+specific.
+
+Compiling with multi-agent support
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To build with the SCMI SMC/HVC multi-agent driver support, enable Kconfig option:
+
+::
+
+    CONFIG_SCMI_SMC_MA
+
+
+Driver functionality
+^^^^^^^^^^^^^^^^^^^^
+
+The SCI SCMI SMC multi-agent driver implements following functionality:
+
+- The driver is initialized based on the ``xen,config`` node under ``chosen``
+  (only one SCMI interface is supported), which describes the Xen management
+  agent SCMI interface.
+
+.. code::
+
+    scmi_shm_1: sram@47ff1000 {
+              compatible = "arm,scmi-shmem";
+              reg = <0x0 0x47ff1000 0x0 0x1000>;
+    };
+    scmi_xen: scmi {
+            compatible = "arm,scmi-smc";
+            arm,smc-id = <0x82000002>; <--- Xen manegement agent smc-id
+            #address-cells = < 1>;
+            #size-cells = < 0>;
+            #access-controller-cells = < 1>;
+            shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
+    };
+
+- The driver obtains Xen specific SCMI Agent's configuration from the Host DT, probes Agents and
+  builds SCMI Agents list. The Agents configuration is taken from "scmi-secondary-agents"
+  property where first item is "arm,smc-id", second - "arm,scmi-shmem" phandle and third is
+  optional "agent_id":
+
+.. code::
+
+    chosen {
+      ranges; <--- set default ranges so address can be translated when parsing scmi_shm node
+      xen,config {
+        ranges; <--- set default ranges so address can be translated when parsing scmi_shm node
+        scmi-secondary-agents = <
+                      0x82000003 &scmi_shm_0 0
+                      0x82000004 &scmi_shm_2 2
+                      0x82000005 &scmi_shm_3 3
+                      0x82000006 &scmi_shm_4 4>;
+        #scmi-secondary-agents-cells = <3>; <--- optional, default 3
+
+        scmi_shm_0 : sram@47ff0000 {
+            compatible = "arm,scmi-shmem";
+            reg = <0x0 0x47ff0000 0x0 0x1000>;
+        };
+
+        scmi_shm_2: sram@47ff2000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff2000 0x0 0x1000>;
+        };
+        scmi_shm_3: sram@47ff3000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff3000 0x0 0x1000>;
+        };
+        scmi_shm_4: sram@47ff4000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff4000 0x0 0x1000>;
+        };
+
+        // Xen SCMI management channel
+        scmi_shm_1: sram@47ff1000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff1000 0x0 0x1000>;
+        };
+
+        scmi_xen: scmi {
+            compatible = "arm,scmi-smc";
+            arm,smc-id = <0x82000002>; <--- Xen manegement agent smc-id
+            #address-cells = < 1>;
+            #size-cells = < 0>;
+            #access-controller-cells = < 1>;
+            shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
+        };
+      };
+    };
+
+    /{
+        // Host SCMI OSPM channel - provided to the Dom0 as is if SCMI enabled for it
+        scmi_shm: sram@47ff1000 {
+                compatible = "arm,scmi-shmem";
+                reg = <0x0 0x47ff1000 0x0 0x1000>;
+        };
+
+        firmware {
+            scmi: scmi {
+                compatible = "arm,scmi-smc";
+                arm,smc-id = <0x82000003>; <--- Host OSPM agent smc-id
+                #address-cells = < 1>;
+                #size-cells = < 0>;
+                shmem = <&scmi_shm>; <--- Host OSPM agent shmem
+
+                protocol@X{
+                };
+            };
+        };
+    };
+
+  This approach allows defining multiple SCMI Agents by adding Xen-specific properties under
+  the ``/chosen`` node to the Host Device Tree, leaving the main part unchanged. The Host DT
+  SCMI channel will be passed to Dom0.
+
+  The Xen management agent is described as a ``scmi_xen`` node under the ``/chosen`` node, which
+  is used by Xen to control other SCMI Agents in the system.
+
+  All secondary agents' configurations are provided in the ``scmi-secondary-agents`` property with
+  an optional ``agent_id`` field.
+
+  The ``agent_id`` from the ``scmi-secondary-agents`` property is used to identify the agent in the
+  system and can be omitted by setting ``#scmi-secondary-agents-cells = <2>``, so the Secondary
+  Agents configuration will look like this:
+
+.. code::
+
+    chosen {
+      xen,config {
+        scmi-secondary-agents = <
+                      0x82000003 &scmi_shm_0
+                      0x82000004 &scmi_shm_2
+                      0x82000005 &scmi_shm_3
+                      0x82000006 &scmi_shm_4>;
+        #scmi-secondary-agents-cells = <2>;
+      };
+    }
+
+  In this case, Xen will use the ``SCMI_BASE_DISCOVER_AGENT`` call to discover the ``agent_id``
+  for each secondary agent. Providing the ``agent_id`` in the ``scmi-secondary-agents`` property
+  allows skipping the discovery call, which is useful when the secondary agent's shared memory is
+  not accessible by Xen or when boot time is important because it allows skipping the agent
+  discovery procedure.
+
+.. note::
+
+    Note that Xen is the only one entry in the system which need to know about SCMI multi-agent support.
+
+- The driver implements the SCI subsystem interface required for configuring and enabling SCMI
+  functionality for Dom0/hwdom and Guest domains. To enable SCMI functionality for guest domain
+  it has to be configured with unique supported SCMI Agent_id and use corresponding SCMI SMC/HVC
+  shared-memory transport ``[smc-id, shmem]`` defined for this SCMI Agent_id.
+
+- Once Xen domain is configured it can communicate with EL3 SCMI FW:
+
+  - zero-copy, the guest domain puts/gets SCMI message in/from shmem;
+  - the guest triggers SMC/HVC exception with agent "smc-id" (doorbell);
+  - the Xen driver catches exception, do checks and synchronously forwards it to EL3 FW.
+
+- the Xen driver sends BASE_RESET_AGENT_CONFIGURATION message to Xen management agent channel on
+  domain destroy event. This allows to reset resources used by domain and so implement use-case
+  like domain reboot.
+
+
+Configure SCMI for Dom0
+^^^^^^^^^^^^^^^^^^^^^^^
+The **"dom0_scmi_agent_id=<dom0_agent_id>"** Xen command line is used to enable SCMI functionality for
+Dom0. if not provided SCMI will be disabled for Dom0 and all SCMI nodes removed from Dom0 DT.
+
+Xen utilizes Host DT SCMI node to configure Dom0 SCMI Agent so the device-tree remains unchanged
+except for the Xen specific properties under ``/chosen`` node. If Xen device-tree doesn't include
+``/firmware/scmi`` node or it's disabled, the Dom0 SCMI Agent will not be configured.
+
+.. note::
+
+    The **dom0_scmi_agent_id** value should match the ``func_id`` and ``shmem`` in the ``/firmware/scmi`` node
+    to set the correct Dom0 SCMI Agent.
+
+Configure SCMI for for guest domain with toolstack
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* In domain's xl.cfg file add **"arm_sci"** option as below
+
+::
+
+    arm_sci = "type=scmi_smc_multiagent,agent_id=2"
+
+* In domain's xl.cfg file enable access to the "arm,scmi-shmem" which should correspond
+  assigned "agent_id" for the domain, for example:
+
+::
+
+    iomem = [
+        "47ff2,1@22001",
+    ]
+
+.. note:: It's up to the user to select guest IPA for mapping SCMI shared-memory.
+
+* Add SCMI nodes to the Driver domain partial device tree as in the below example.
+  The "arm,smc-id" should correspond assigned agent_id for the domain:
+
+.. code::
+
+    passthrough {
+       scmi_shm_0: sram@22001000 {
+           compatible = "arm,scmi-shmem";
+           reg = <0x0 0x22001000 0x0 0x1000>;
+       };
+
+       firmware {
+            compatible = "simple-bus";
+                scmi: scmi {
+                    compatible = "arm,scmi-smc";
+                    arm,smc-id = <0x82000004>;
+                    shmem = <&scmi_shm_0>;
+                    ...
+                }
+        }
+    }
+
+**Device specific access control**
+
+The XEN SCMI SMC/HVC multi-agent driver performs "access-controller" provider function in case
+EL3 SCMI FW implements SCMI "4.2.1.1 Device specific access control" and provides the
+BASE_SET_DEVICE_PERMISSIONS command to configure the devices that an agents have access to.
+The Host DT SCMI node should have "#access-controller-cells=<1>" property and DT devices should
+be bound to the SCMI node using Access Controllers bindings [3].
+
+For example:
+
+.. code::
+
+    &i2c1 {
+            access-controllers = <&scmi 0>;
+    };
+
+Use domain's xl.cfg file **"dtdev"** property to assign SCMI devices from toolstack to the guest:
+
+::
+
+    dtdev = [
+        "/soc/i2c@e6508000",
+    ]
+
+.. note::
+
+    xl.cfg:"dtdev" need contain all nodes which are under SCMI management (not only those which are
+    behind IOMMU) and passed-through to the guest domain.
+
+Configure SCMI for predefined domains (dom0less)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+* add "xen,sci_type" and "xen,sci_agent_id" properties for required DomU ("xen,domain") node
+
+::
+
+    xen,sci_type="scmi_smc_multiagent"
+    xen,sci_agent_id=2
+
+* add scmi nodes to the Driver domain partial device tree the same way as above (toolstack case) and
+  enable access to the "arm,scmi-shmem" according to the dom0less documentation. For example:
+
+.. code::
+
+      scmi_shm_0: sram@22001000 {
+            compatible = "arm,scmi-shmem";
+            reg = <0x00 0x22001000 0x00 0x1000>;
+    ->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
+    ->        xen,force-assign-without-iommu;
+      };
+
+* For SCMI device access control configure pass-through devices in the guest partial DT according to
+  the dom0less documentation and ensure that devices SCMI management has "xen,path" property set:
+
+.. code::
+
+		i2c@e6508000 {
+            ...
+			reg = <0x00 0xe6508000 0x00 0x1000>;
+    ->        xen,path = "/soc/i2c@e6508000"
+    ->        xen,reg = <0x0 0xe6508000 0x0 0x1000 0x0 0xe6508000>;
+    ->        xen,force-assign-without-iommu;
+        };
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
  2025-07-22 11:41 ` [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent Oleksii Moisieiev
@ 2025-07-22 12:21   ` Jan Beulich
  2025-07-22 15:09     ` Oleksii Moisieiev
  2025-07-30 13:19   ` Anthony PERARD
  2025-08-23  0:22   ` Stefano Stabellini
  2 siblings, 1 reply; 37+ messages in thread
From: Jan Beulich @ 2025-07-22 12:21 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org

On 22.07.2025 13:41, Oleksii Moisieiev wrote:
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -1096,6 +1096,15 @@ affinities to prefer but be not limited to the specified node(s).
>  
>  Pin dom0 vcpus to their respective pcpus
>  
> +### scmi_smc_passthrough (ARM)

May I ask that new command line options please use dashes in favor of
underscores?

Jan


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 05/10] drivers: iommu: change error code when iommu is disabled
  2025-07-22 11:41 ` [RFC PATCH v5 05/10] drivers: iommu: change error code when iommu is disabled Oleksii Moisieiev
@ 2025-07-22 12:29   ` Jan Beulich
  0 siblings, 0 replies; 37+ messages in thread
From: Jan Beulich @ 2025-07-22 12:29 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org

On 22.07.2025 13:41, Oleksii Moisieiev wrote:
> Change -ENOPNOTSUPP error code to -ENXIO when iommu is disabled during
> iommu_do_domctl call. As was discussed in [1]
> 
> [0]: https://lore.kernel.org/xen-devel/alpine.DEB.2.22.394.2506171701190.1780597@ubuntu-linux-20-04-desktop/

Hmm, I can't read any justification for the choice of the particular error
code out of that email. How's ENXIO going to be (and remain) unique? If you
need a specific indication of the IOMMU being disabled, I think you want to
have a specific query for that. Assuming XEN_SYSCTL_PHYSCAP_directio isn't
enough (for whatever reason).

Jan


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
  2025-07-22 11:41 ` [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu Oleksii Moisieiev
@ 2025-07-22 12:34   ` Jan Beulich
  2025-08-28  5:48     ` Oleksii Moisieiev
  0 siblings, 1 reply; 37+ messages in thread
From: Jan Beulich @ 2025-07-22 12:34 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org

On 22.07.2025 13:41, Oleksii Moisieiev wrote:
> @@ -859,7 +860,25 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>      case XEN_DOMCTL_test_assign_device:
>      case XEN_DOMCTL_deassign_device:
>      case XEN_DOMCTL_get_device_group:
> +        int ret1;
> +        
>          ret = iommu_do_domctl(op, d, u_domctl);
> +        if ( ret < 0 && ret != -ENXIO )
> +            return ret;

If this is where you want the ENXIO for that the previous patch switched to,
then I see no reason for that earlier change at all. Inside the hypervisor
you can simply figure out what the right thing to do is; you could avoid
calling iommu_do_domctl() altogether and call ...

> +        /*
> +         * Add chained handling of assigned DT devices to support
> +         * access-controller functionality through SCI framework, so
> +         * DT device assign request can be passed to FW for processing and
> +         * enabling VM access to requested device.
> +         * The access-controller DT device processing is chained after IOMMU
> +         * processing and expected to be executed for any DT device
> +         * regardless if DT device is protected by IOMMU or not (or IOMMU
> +         * is disabled).
> +         */
> +        ret1 = sci_do_domctl(op, d, u_domctl);

... this one right away, for example. (Which of course doesn't eliminate the
question towards the overloading done here, which iirc was raised before.)

Jan


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers
  2025-07-22 11:41 ` [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers Oleksii Moisieiev
@ 2025-07-22 12:43   ` Jan Beulich
  2025-08-23  0:40   ` Stefano Stabellini
  1 sibling, 0 replies; 37+ messages in thread
From: Jan Beulich @ 2025-07-22 12:43 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org

On 22.07.2025 13:41, Oleksii Moisieiev wrote:
> This commit introduces two helper functions, `__memcpy_fromio` and
> `__memcpy_toio`, to provide a robust mechanism for copying data between
> standard memory and memory-mapped I/O (MMIO) space for the ARM
> architecture.
> 
> These functions are designed to handle memory transfers safely,
> accounting for potential address alignment issues to ensure correctness
> and improve performance where possible. The implementation is specific
> to ARM and uses relaxed I/O accessors.

The implementation could be reused by any arch providing
{read,write}*_relaxed(), couldn't it?

> __memcpy_fromio:
> Copies a block of data from an I/O memory source to a destination in
> standard ("real") memory. The implementation first handles any unaligned
> bytes at the beginning of the source buffer individually using byte-wise
> reads. It then copies the bulk of the data using 32-bit reads for
> efficiency, and finally processes any remaining bytes at the end of the
> buffer.
> 
> __memcpy_toio:
> Copies a block of data from standard memory to a destination in I/O
> memory space. It follows a similar strategy, handling any initial
> unaligned portion of the destination buffer byte-by-byte before using
> more efficient 32-bit writes for the main, aligned part of the transfer.
> Any trailing bytes are also handled individually.
> xen/include/xen/lib/arm/io.h

Why exactly do the functions need two leading underscores in their names?

> --- a/xen/lib/Makefile
> +++ b/xen/lib/Makefile
> @@ -1,4 +1,5 @@
>  obj-$(CONFIG_X86) += x86/
> +obj-$(CONFIG_ARM) += arm/

Nit: Alphabetically sorted please.

> --- /dev/null
> +++ b/xen/lib/arm/Makefile
> @@ -0,0 +1 @@
> +obj-y += io.o
> \ No newline at end of file

Please make sure all files properly end in a newline.

> --- /dev/null
> +++ b/xen/lib/arm/io.c
> @@ -0,0 +1,80 @@
> +#include <asm/io.h>
> +#include <xen/lib/arm/io.h>
> +
> +/*
> + * memcpy_fromio - Copy data from IO memory space to "real" memory space.
> + * @to: Where to copy to
> + * @from: Where to copy from
> + * @count: The size of the area.
> + */
> +void __memcpy_fromio(void *to, const volatile void __iomem *from,
> +                     size_t count)
> +{
> +    while ( count && !IS_ALIGNED((unsigned long)from, 4) )
> +    {
> +        *(u8 *)to = readb_relaxed(from);

No u<N> anymore in new code please; use uint<N>_t instead.

Further, what tells you that accessing a 16-bit register residing in MMIO
can legitimately be accessed using two 8-bit accesses?

> +        from++;
> +        to++;
> +        count--;
> +    }
> +
> +    while ( count >= 4 )
> +    {
> +        *(u32 *)to = readl_relaxed(from);
> +        from += 4;
> +        to += 4;
> +        count -= 4;
> +    }

Not attempting 64-bit accesses on 64-bit arches will want an explanatory
comment, I think.

> +    while ( count )
> +    {
> +        *(u8 *)to = readb_relaxed(from);
> +        from++;
> +        to++;
> +        count--;
> +    }
> +}
> +
> +/*
> + * memcpy_toio - Copy data from "real" memory space to IO memory space.
> + * @to: Where to copy to
> + * @from: Where to copy from
> + * @count: The size of the area.
> + */
> +void __memcpy_toio(volatile void __iomem *to, const void *from,
> +                   size_t count)
> +{
> +    while ( count && !IS_ALIGNED((unsigned long)to, 4) )
> +    {
> +        writeb_relaxed(*(u8 *)from, to);

Please never cast away const-ness. This is a violation of some Misra rule,
iirc.

Jan


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
  2025-07-22 11:41 ` [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Oleksii Moisieiev
@ 2025-07-22 12:46   ` Jan Beulich
  2025-07-30 13:29   ` Anthony PERARD
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 37+ messages in thread
From: Jan Beulich @ 2025-07-22 12:46 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org

On 22.07.2025 13:41, Oleksii Moisieiev wrote:
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -1105,6 +1105,15 @@ which serves as Driver domain. The SCMI will be disabled for Dom0/hwdom and
>  SCMI nodes removed from Dom0/hwdom device tree.
>  (for example, thin Dom0 with Driver domain use-case).
>  
> +### dom0_scmi_agent_id (ARM)

New Dom0-specific options would imo better all be sub-options to "dom0=".

Also, just to reiterate: Please prefer dashes over underscores.

Jan


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
  2025-07-22 12:21   ` Jan Beulich
@ 2025-07-22 15:09     ` Oleksii Moisieiev
  0 siblings, 0 replies; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-07-22 15:09 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org

Hi Jan,

On 22/07/2025 15:21, Jan Beulich wrote:
> On 22.07.2025 13:41, Oleksii Moisieiev wrote:
>> --- a/docs/misc/xen-command-line.pandoc
>> +++ b/docs/misc/xen-command-line.pandoc
>> @@ -1096,6 +1096,15 @@ affinities to prefer but be not limited to the specified node(s).
>>   
>>   Pin dom0 vcpus to their respective pcpus
>>   
>> +### scmi_smc_passthrough (ARM)
> May I ask that new command line options please use dashes in favor of
> underscores?
>
> Jan
Here is an example from the device tree configuration on my system:

         bootargs = "dom0_mem=320M console=dtuart 
dtuart=/soc/serial@e6540000 dom0_max_vcpus=2 loglvl=all xsm=flask 
flask=permissive bootscrub=0 console_timestamps=boot scmi_smc_passthrough";
         xen,dom0-bootargs = "root=/dev/ram0 console=hvc0 
ignore_loglevel clk_ignore_unused";

I have referred to the dom0_mem property as a guide.
I will update scmi_smc_passthrough to scmi-smc-passthrough
--
Oleksii.

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
  2025-07-22 11:41 ` [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent Oleksii Moisieiev
  2025-07-22 12:21   ` Jan Beulich
@ 2025-07-30 13:19   ` Anthony PERARD
  2025-08-23  0:22   ` Stefano Stabellini
  2 siblings, 0 replies; 37+ messages in thread
From: Anthony PERARD @ 2025-07-30 13:19 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, Jul 22, 2025 at 11:41:39AM +0000, Oleksii Moisieiev wrote:
> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index 4ffcbf624b..68d2ebeb9f 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -1284,6 +1284,36 @@ out:
>      if (rc) exit(EXIT_FAILURE);
>  }
>  
> +static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci,
> +                                const char *str)
> +{
> +    int ret = 0;
> +    char *buf2, *ptr;
> +    char *oparg;
> +
> +    if (NULL == (buf2 = ptr = strdup(str)))
> +        return ERROR_NOMEM;
> +
> +    ptr = strtok(buf2, ",");
> +    while (ptr != NULL)
> +    {
> +        if (MATCH_OPTION("type", ptr, oparg)) {
> +            ret = libxl_arm_sci_type_from_string(oparg, &arm_sci->type);
> +            if (ret) {
> +                fprintf(stderr, "Unknown ARM_SCI type: %s\n", oparg);
> +                ret = ERROR_INVAL;
> +                goto parse_error;
> +            }
> +        }
> +
> +        ptr = strtok(NULL, ",");
> +    }
> +
> +parse_error:

This label could be named "out", as it just a path out of the function,
both on success and error.

> +    free(buf2);
> +    return ret;
> +}
> +

The patch looks fine to me for the toolstack part, so:
Acked-by: Anthony PERARD <anthony.perard@vates.tech> # tools

TODO on commit (or before): regen golang/xenlight/{helpers,types}.gen.go
due to change in libxl_types.idl.

Thanks,

-- 
Anthony PERARD


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
  2025-07-22 11:41 ` [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Oleksii Moisieiev
  2025-07-22 12:46   ` Jan Beulich
@ 2025-07-30 13:29   ` Anthony PERARD
  2025-08-26  0:37   ` Stefano Stabellini
  2025-08-27 19:35   ` Oleksandr Tyshchenko
  3 siblings, 0 replies; 37+ messages in thread
From: Anthony PERARD @ 2025-07-30 13:29 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, Jul 22, 2025 at 11:41:41AM +0000, Oleksii Moisieiev wrote:
> This patch introduces SCI driver to support for ARM EL3 Trusted Firmware-A
> (TF-A) which provides SCMI interface with multi-agnet support, as shown
> below.

[...]

> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
> ---
>  docs/man/xl.cfg.5.pod.in                    |  13 +
>  tools/libs/light/libxl_arm.c                |   4 +
>  tools/libs/light/libxl_types.idl            |   4 +-
>  tools/xl/xl_parse.c                         |  12 +

For the tools:
Acked-by: Anthony PERARD <anthony.perard@vates.tech> # tools

Thanks,

-- 
Anthony PERARD


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
  2025-07-22 11:41 ` [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent Oleksii Moisieiev
  2025-07-22 12:21   ` Jan Beulich
  2025-07-30 13:19   ` Anthony PERARD
@ 2025-08-23  0:22   ` Stefano Stabellini
  2 siblings, 0 replies; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-23  0:22 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> From: Grygorii Strashko <grygorii_strashko@epam.com>
> 
> The commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls
> handling layer") introduces simple driver which forwards SCMI over SMC
> calls from hwdom/dom0 to EL3 firmware (TF-A) with a single SCMI OSPM agent
> support. While it is working gracefully for hwdom/dom0 use case it doesn't
> cover "thin Dom0 with guest domain, which serves as Driver domain"
> use-case. In this case HW need to be enable in Driver domain and dom0 is
> performing only control functions.
> 
> The EL3 SCMI firmware (TF-A) with a single SCMI OSPM agent support is
> pretty generic case for the default vendors SDK and new platforms.
> 
> This patch enables passthrough of SCMI SMC single agent interface to the
> one guest domain serving as Driver domain.
> 
> Configure Dom0 to enable SCMI passthrough:
> 
>  - dom0: add scmi_smc_passthrough to the Xen Command Line
> 
> Enabled SCMI passthrough for guest using toolstack in the following way:
> 
>  - domD: xl.cfg add "arm_sci" option as below
> 
>    arm_sci = "type=scmi_smc"
> 
>  - domD: xl.cfg enable access to the "arm,scmi-shmem"
> 
> iomem = [
>     "47ff0,1@22001",
> ]
> 
>  - domD: add SCMI nodes to the Driver domain partial device tree as in the
>  below example:
> 
> passthrough {
>    scmi_shm_0: sram@22001000 {
>        compatible = "arm,scmi-shmem";
>        reg = <0x0 0x22001000 0x0 0x1000>;
>    };
> 
>    firmware {
>         compatible = "simple-bus";
>             scmi: scmi {
>                 compatible = "arm,scmi-smc";
>                 shmem = <&scmi_shm_0>;
>                 ...
>             }
>     }
> }
> 
> dom0less case configuration:
> 
> - add "xen,sci_type" property for required DomU ("xen,domain") node
> 
>    xen,sci_type="scmi_smc"
> 
> - add scmi nodes to the Driver domain partial device tree the same way
> as above and enable access to the "arm,scmi-shmem" according to
> dom0less documentation. For example:
> 
>   scmi_shm_0: sram@22001000 {
>         compatible = "arm,scmi-shmem";
>         reg = <0x00 0x22001000 0x00 0x1000>;
> ->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
> ->        xen,force-assign-without-iommu;
>   };
> 
> The SCMI SMC single agent interface can be enabled for one and only one
> domain. In general, the configuration is similar to any other HW
> passthrough, except explicitly enabling SCMI with "arm_sci" xl.cfg option.
> 
> Note that "arm,scmi-smc" and "arm,scmi-shmem" nodes will be removed from
> dom0/hwdom DT in case of

This patch needs to be rebased, other than that, it is OK



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 01/10] xen/arm: add generic SCI subsystem
  2025-07-22 11:41 ` [RFC PATCH v5 01/10] xen/arm: add generic SCI subsystem Oleksii Moisieiev
@ 2025-08-23  0:26   ` Stefano Stabellini
  2025-08-28 13:46     ` Oleksii Moisieiev
  0 siblings, 1 reply; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-23  0:26 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> This patch adds the basic framework for ARM SCI mediator. SCI is System
> Control Interface, which is designed to redirect requests from the Domains
> to ARM specific Firmware (for example SCMI). This will allow the devices,
> passed-through to the different Domains, to access to the System resources
> (such as clocks/resets etc) by sending requests to the firmware.
> 
> ARM SCI subsystem allows to implement different SCI drivers to handle
> specific ARM firmware interfaces (like ARM SCMI) and mediate requests
> -between the Domains and the Firmware. Also it allows SCI drivers to perform
> proper action during Domain creation/destruction which is vital for
> handling use cases like Domain reboot.
> 
> This patch introduces new DEVICE_FIRMWARE device subclass for probing SCI
> drivers basing on device tree, SCI drivers register itself with
> DT_DEVICE_START/END macro. On init - the SCI drivers should register its
> SCI ops with sci_register(). Only one SCI driver can be supported.
> 
> At run-time, the following SCI API calls are introduced:
> 
> - sci_domain_sanitise_config() called from arch_sanitise_domain_config()
> - sci_domain_init() called from arch_domain_create()
> - sci_relinquish_resources() called from domain_relinquish_resources()
> - sci_domain_destroy() called from arch_domain_destroy()
> - sci_handle_call() called from vsmccc_handle_call()
> - sci_dt_handle_node()
> - sci_dt_finalize() called from handle_node() (Dom0 DT)
> 
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>

The patch needs rebasing


> ---
> 
> Changes in v5:
> - update Maintainers file. Set role as a Reviewer
> - rebased on the latest master branch
> - Introduce arch_handle_passthrough_prop call to handle arm specific nodes
> 
> Changes in v4:
> - fix SPDX-License
> - rename DEVICE_ARM_SCI DT device class to FIRMWARE_DEVICE
> - move XEN_DOMCTL_assign_device code in separate patch
> - Add documentation for SCI SCMI drivers
> 
>  MAINTAINERS                              |   6 +
>  xen/arch/arm/device.c                    |   5 +
>  xen/arch/arm/dom0less-build.c            |   8 +
>  xen/arch/arm/domain.c                    |  12 +-
>  xen/arch/arm/domain_build.c              |   8 +
>  xen/arch/arm/firmware/Kconfig            |   8 +
>  xen/arch/arm/firmware/Makefile           |   1 +
>  xen/arch/arm/firmware/sci.c              | 154 +++++++++++++++++
>  xen/arch/arm/include/asm/domain.h        |   5 +
>  xen/arch/arm/include/asm/firmware/sci.h  | 200 +++++++++++++++++++++++
>  xen/arch/arm/vsmc.c                      |   3 +
>  xen/common/device-tree/dom0less-build.c  |   4 +
>  xen/include/asm-generic/device.h         |   1 +
>  xen/include/asm-generic/dom0less-build.h |   9 +
>  xen/include/public/arch-arm.h            |   4 +
>  15 files changed, 427 insertions(+), 1 deletion(-)
>  create mode 100644 xen/arch/arm/firmware/sci.c
>  create mode 100644 xen/arch/arm/include/asm/firmware/sci.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c4886c1159..31dbba54bb 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -509,6 +509,12 @@ R:	George Dunlap <gwd@xenproject.org>
>  S:	Supported
>  F:	xen/common/sched/
>  
> +SCI MEDIATORS
> +R:	Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> +S:	Supported
> +F:	xen/arch/arm/firmware/sci.c
> +F:	xen/arch/arm/include/asm/firmware/sci.h
> +
>  SEABIOS UPSTREAM
>  M:	Wei Liu <wl@xen.org>
>  S:	Supported
> diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
> index 11523750ae..74b54cad34 100644
> --- a/xen/arch/arm/device.c
> +++ b/xen/arch/arm/device.c
> @@ -13,6 +13,7 @@
>  #include <xen/iocap.h>
>  #include <xen/lib.h>
>  
> +#include <asm/firmware/sci.h>
>  #include <asm/setup.h>
>  
>  int map_irq_to_domain(struct domain *d, unsigned int irq,
> @@ -303,6 +304,10 @@ int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt,
>                  return res;
>              }
>          }
> +
> +        res = sci_assign_dt_device(d, dev);
> +        if ( res )
> +            return res;
>      }
>  
>      res = map_device_irqs_to_domain(d, dev, own_device, irq_ranges);
> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> index 4b285cff5e..2a0bf817ba 100644
> --- a/xen/arch/arm/dom0less-build.c
> +++ b/xen/arch/arm/dom0less-build.c
> @@ -22,6 +22,7 @@
>  #include <asm/arm64/sve.h>
>  #include <asm/dom0less-build.h>
>  #include <asm/domain_build.h>
> +#include <asm/firmware/sci.h>
>  #include <asm/grant_table.h>
>  #include <asm/setup.h>
>  
> @@ -272,6 +273,12 @@ int __init init_vuart(struct domain *d, struct kernel_info *kinfo,
>      return rc;
>  }
>  
> +int __init arch_handle_passthrough_prop(struct kernel_info *kinfo,
> +                                        struct dt_device_node *node)
> +{
> +    return sci_assign_dt_device(kinfo->d, node);
> +}
> +
>  void __init arch_create_domUs(struct dt_device_node *node,
>                         struct xen_domctl_createdomain *d_cfg,
>                         unsigned int flags)
> @@ -280,6 +287,7 @@ void __init arch_create_domUs(struct dt_device_node *node,
>  
>      d_cfg->arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
>      d_cfg->flags |= XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap;
> +    d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
>  
>      if ( !dt_property_read_u32(node, "nr_spis", &d_cfg->arch.nr_spis) )
>      {
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 79a144e61b..d0146da5da 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -24,6 +24,7 @@
>  #include <asm/platform.h>
>  #include <asm/procinfo.h>
>  #include <asm/regs.h>
> +#include <asm/firmware/sci.h>
>  #include <asm/tee/tee.h>
>  #include <asm/vfp.h>
>  #include <asm/vgic.h>
> @@ -699,7 +700,7 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
>          return -EINVAL;
>      }
>  
> -    return 0;
> +    return sci_domain_sanitise_config(config);
>  }
>  
>  int arch_domain_create(struct domain *d,
> @@ -791,6 +792,9 @@ int arch_domain_create(struct domain *d,
>      d->arch.sve_vl = config->arch.sve_vl;
>  #endif
>  
> +    if ( (rc = sci_domain_init(d, config)) != 0 )
> +        goto fail;
> +
>      return 0;
>  
>  fail:
> @@ -851,6 +855,7 @@ void arch_domain_destroy(struct domain *d)
>      domain_vgic_free(d);
>      domain_vuart_free(d);
>      free_xenheap_page(d->shared_info);
> +    sci_domain_destroy(d);
>  #ifdef CONFIG_ACPI
>      free_xenheap_pages(d->arch.efi_acpi_table,
>                         get_order_from_bytes(d->arch.efi_acpi_len));
> @@ -1044,6 +1049,7 @@ enum {
>      PROG_p2m_root,
>      PROG_p2m,
>      PROG_p2m_pool,
> +    PROG_sci,
>      PROG_done,
>  };
>  
> @@ -1103,6 +1109,10 @@ int domain_relinquish_resources(struct domain *d)
>          ret = relinquish_p2m_mapping(d);
>          if ( ret )
>              return ret;
> +    PROGRESS(sci):
> +        ret = sci_relinquish_resources(d);
> +        if ( ret )
> +            return ret;
>  
>      PROGRESS(p2m_root):
>          /*
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index ed668bd61c..92039cf213 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -26,6 +26,7 @@
>  #include <asm/setup.h>
>  #include <asm/tee/tee.h>
>  #include <asm/pci.h>
> +#include <asm/firmware/sci.h>
>  #include <asm/platform.h>
>  #include <asm/psci.h>
>  #include <asm/setup.h>
> @@ -1639,6 +1640,9 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>          return 0;
>      }
>  
> +    if ( sci_dt_handle_node(d, node) )
> +        return 0;
> +
>      /*
>       * The vGIC does not support routing hardware PPIs to guest. So
>       * we need to skip any node using PPIs.
> @@ -1739,6 +1743,10 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>          if ( res )
>              return res;
>  
> +        res = sci_dt_finalize(d, kinfo->fdt);
> +        if ( res )
> +            return res;
> +
>          /*
>           * Create a second memory node to store the ranges covering
>           * reserved-memory regions.
> diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
> index 817da745fd..fc7918c7fc 100644
> --- a/xen/arch/arm/firmware/Kconfig
> +++ b/xen/arch/arm/firmware/Kconfig
> @@ -1,3 +1,11 @@
> +config ARM_SCI
> +	bool
> +	depends on ARM
> +	help
> +	  This option enables generic Arm SCI (System Control Interface) mediators
> +	  support. It allows domains to control system resources via one of
> +	  Arm SCI mediators drivers implemented in XEN, like SCMI.
> +
>  menu "Firmware Drivers"
>  
>  config SCMI_SMC
> diff --git a/xen/arch/arm/firmware/Makefile b/xen/arch/arm/firmware/Makefile
> index a5e4542666..71bdefc24a 100644
> --- a/xen/arch/arm/firmware/Makefile
> +++ b/xen/arch/arm/firmware/Makefile
> @@ -1 +1,2 @@
> +obj-$(CONFIG_ARM_SCI) += sci.o
>  obj-$(CONFIG_SCMI_SMC) += scmi-smc.o
> diff --git a/xen/arch/arm/firmware/sci.c b/xen/arch/arm/firmware/sci.c
> new file mode 100644
> index 0000000000..e1522e10e2
> --- /dev/null
> +++ b/xen/arch/arm/firmware/sci.c
> @@ -0,0 +1,154 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Generic part of the SCI (System Control Interface) subsystem.
> + *
> + * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> + * Copyright (c) 2025 EPAM Systems
> + */
> +
> +#include <xen/acpi.h>
> +#include <xen/errno.h>
> +#include <xen/init.h>
> +#include <xen/sched.h>
> +#include <xen/types.h>
> +
> +#include <asm/firmware/sci.h>
> +
> +static const struct sci_mediator_ops __read_mostly *cur_mediator;
> +
> +int sci_register(const struct sci_mediator_ops *ops)
> +{
> +    if ( cur_mediator )
> +        return -EEXIST;
> +
> +    if ( !ops->domain_init || !ops->domain_destroy || !ops->handle_call )
> +        return -EINVAL;
> +
> +    cur_mediator = ops;
> +
> +    return 0;
> +};
> +
> +bool sci_handle_call(struct cpu_user_regs *args)
> +{
> +    if ( unlikely(!cur_mediator) )
> +        return false;

should we check that sci_domain_is_enabled ?


> +    return cur_mediator->handle_call(args);
> +}
> +
> +int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config)
> +{
> +    if ( !cur_mediator )
> +        return 0;
> +
> +    return cur_mediator->domain_init(d, config);
> +}
> +
> +int sci_domain_sanitise_config(struct xen_domctl_createdomain *config)
> +{
> +    if ( !cur_mediator )
> +        return 0;
> +
> +    if ( !cur_mediator->domain_sanitise_config )
> +        return 0;
> +
> +    return cur_mediator->domain_sanitise_config(config);
> +}
> +
> +void sci_domain_destroy(struct domain *d)
> +{
> +    if ( !cur_mediator )
> +        return;
> +
> +    cur_mediator->domain_destroy(d);
> +}
> +
> +int sci_relinquish_resources(struct domain *d)
> +{
> +    if ( !cur_mediator )
> +        return 0;
> +
> +    if ( !cur_mediator->relinquish_resources )
> +        return 0;
> +
> +    return cur_mediator->relinquish_resources(d);
> +}
> +
> +bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node)
> +{
> +    if ( !cur_mediator )
> +        return 0;
> +
> +    if ( !cur_mediator->dom0_dt_handle_node )
> +        return 0;
> +
> +    return cur_mediator->dom0_dt_handle_node(d, node);
> +}
> +
> +int sci_dt_finalize(struct domain *d, void *fdt)
> +{
> +    if ( !cur_mediator )
> +        return 0;
> +
> +    if ( !cur_mediator->dom0_dt_finalize )
> +        return 0;
> +
> +    return cur_mediator->dom0_dt_finalize(d, fdt);
> +}
> +
> +int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev)
> +{
> +    struct dt_phandle_args ac_spec;
> +    int index = 0;
> +    int ret;
> +
> +    if ( !cur_mediator )
> +        return 0;
> +
> +    if ( !cur_mediator->assign_dt_device )
> +        return 0;
> +
> +    while ( !dt_parse_phandle_with_args(dev, "access-controllers",
> +                                        "#access-controller-cells", index,
> +                                        &ac_spec) )
> +    {
> +        printk(XENLOG_DEBUG "sci: assign device %s to %pd\n",
> +               dt_node_full_name(dev), d);
> +
> +        ret = cur_mediator->assign_dt_device(d, &ac_spec);
> +        if ( ret )
> +            return ret;
> +
> +        index++;
> +    }
> +
> +    return 0;
> +}
> +
> +static int __init sci_init(void)
> +{
> +    struct dt_device_node *np;
> +    unsigned int num_sci = 0;
> +    int rc;
> +
> +    dt_for_each_device_node(dt_host, np)
> +    {
> +        rc = device_init(np, DEVICE_FIRMWARE, NULL);
> +        if ( !rc && num_sci )
> +        {
> +            printk(XENLOG_ERR
> +                   "SCMI: Only one SCI controller is supported. found second %s\n",
> +                   np->name);
> +            return -EOPNOTSUPP;
> +        }
> +        else if ( !rc )
> +            num_sci++;
> +        else if ( rc != -EBADF && rc != -ENODEV )
> +            return rc;
> +    }
> +
> +    return 0;
> +}
> +
> +__initcall(sci_init);
> diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
> index a3487ca713..af3e168374 100644
> --- a/xen/arch/arm/include/asm/domain.h
> +++ b/xen/arch/arm/include/asm/domain.h
> @@ -120,6 +120,11 @@ struct arch_domain
>  #ifdef CONFIG_TEE
>      void *tee;
>  #endif
> +#ifdef CONFIG_ARM_SCI
> +    bool sci_enabled;
> +    /* ARM SCI driver's specific data */
> +    void *sci_data;
> +#endif
>  
>  }  __cacheline_aligned;
>  
> diff --git a/xen/arch/arm/include/asm/firmware/sci.h b/xen/arch/arm/include/asm/firmware/sci.h
> new file mode 100644
> index 0000000000..71fb54852e
> --- /dev/null
> +++ b/xen/arch/arm/include/asm/firmware/sci.h
> @@ -0,0 +1,200 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Generic ARM SCI (System Control Interface) subsystem.
> + *
> + * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> + * Copyright (c) 2025 EPAM Systems
> + */
> +
> +#ifndef __ASM_ARM_SCI_H
> +#define __ASM_ARM_SCI_H
> +
> +#include <xen/lib.h>
> +#include <xen/types.h>
> +#include <xen/device_tree.h>
> +#include <xen/errno.h>
> +#include <xen/sched.h>
> +
> +#ifdef CONFIG_ARM_SCI
> +
> +struct sci_mediator_ops {
> +    /*
> +     * Called during domain construction. If it is requested to enable
> +     * SCI support, so SCI driver can create own structures for the new domain
> +     * and inform firmware about new domain (if required).
> +     * Mandatory.
> +     */
> +    int (*domain_init)(struct domain *d,
> +                       struct xen_domctl_createdomain *config);
> +
> +    /*
> +     * Called during domain construction. The SCI driver uses
> +     * it to sanitize domain SCI configuration parameters.
> +     * Optional.
> +     */
> +    int (*domain_sanitise_config)(struct xen_domctl_createdomain *config);
> +
> +    /*
> +     * Called during domain destruction, releases all resources, that
> +     * were allocated for domain.
> +     * Mandatory.
> +     */
> +    void (*domain_destroy)(struct domain *d);
> +
> +    /*
> +     * Called during domain destruction to relinquish resources used
> +     * by SCI driver itself and request resources releasing from firmware.
> +     * Optional.
> +     */
> +    int (*relinquish_resources)(struct domain *d);
> +
> +    /* SMC/HVC Handle callback */
> +    bool (*handle_call)(struct cpu_user_regs *regs);
> +
> +    /*
> +     * Dom0 DT nodes handling callback so SCI driver can detect DT nodes it
> +     * need to handle and decide if those nodes need to be provided to Dom0.
> +     * Optional.
> +     */
> +    bool (*dom0_dt_handle_node)(struct domain *d, struct dt_device_node *node);
> +
> +    /*
> +     * SCI driver callback called at the end of Dom0 DT generation, so
> +     * it can perform steps to modify DT to enable/disable SCI
> +     * functionality for Dom0.
> +     */
> +    int (*dom0_dt_finalize)(struct domain *d, void *fdt);
> +
> +    /*
> +     * SCI driver callback called when DT device is passed through to guest,
> +     * so SCI driver can enable device access to the domain if SCI FW provides
> +     * Device specific access control functionality.
> +     * Optional.
> +     */
> +    int (*assign_dt_device)(struct domain *d, struct dt_phandle_args *ac_spec);
> +};
> +
> +
> +static inline bool sci_domain_is_enabled(struct domain *d)
> +{
> +    return d->arch.sci_enabled;
> +}
> +
> +/*
> + * Register SCI subsystem ops.
> + *
> + * Register SCI drivers operation and so enable SCI functionality.
> + * Only one SCI driver is supported.
> + */
> +int sci_register(const struct sci_mediator_ops *ops);
> +
> +/*
> + * Initialize SCI functionality for domain if configured.
> + *
> + * Initialization routine to enable SCI functionality for the domain.
> + * The SCI configuration data and decision about enabling SCI functionality
> + * for the domain is SCI driver specific.
> + */
> +int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config);
> +
> +/*
> + * Sanitise domain configuration parameters.
> + *
> + */
> +int sci_domain_sanitise_config(struct xen_domctl_createdomain *config);
> +
> +/*
> + * Destroy SCI domain instance.
> + */
> +void sci_domain_destroy(struct domain *d);
> +
> +/*
> + * Free resources assigned to the certain domain.
> + */
> +int sci_relinquish_resources(struct domain *d);
> +
> +/*
> + * SMC/HVC Handle callback.
> + *
> + * SCI driver acts as SMC/HVC server for the registered domains and
> + * does redirection of the domain calls to the SCI firmware,
> + * such as ARM TF-A or similar.
> + */
> +bool sci_handle_call(struct cpu_user_regs *regs);
> +
> +/*
> + * Dom0 DT nodes handling function.
> + *
> + * Allows SCI driver to detect DT nodes it need to handle and decide if
> + * those nodes need to be provided to Dom0.
> + */
> +bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node);
> +
> +/*
> + * Dom0 DT generation finalize.
> + *
> + * Called at the end of Dom0 DT generation, so SCI driver can perform steps
> + * to modify DT to enable/disable SCI functionality for Dom0.
> + */
> +int sci_dt_finalize(struct domain *d, void *fdt);
> +
> +/*
> + * Assign DT device to domain.
> + *
> + * Called when DT device is passed through to guest, so SCI driver can enable
> + * device access to the domain if SCI FW provides "Device specific access
> + * control" functionality.
> + */
> +int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev);
> +#else
> +
> +static inline bool sci_domain_is_enabled(struct domain *d)
> +{
> +    return false;
> +}
> +
> +static inline int sci_domain_init(struct domain *d,
> +                                  struct xen_domctl_createdomain *config)
> +{
> +    return 0;
> +}
> +
> +static inline int
> +sci_domain_sanitise_config(struct xen_domctl_createdomain *config)
> +{
> +    return 0;
> +}
> +
> +static inline void sci_domain_destroy(struct domain *d)
> +{}
> +
> +static inline int sci_relinquish_resources(struct domain *d)
> +{
> +    return 0;
> +}
> +
> +static inline bool sci_handle_call(struct cpu_user_regs *args)
> +{
> +    return false;
> +}
> +
> +static inline bool sci_dt_handle_node(struct domain *d,
> +                                      struct dt_device_node *node)
> +{
> +    return false;
> +}
> +
> +static inline int sci_dt_finalize(struct domain *d, void *fdt)
> +{
> +    return false;

should return int, not bool


> +}
> +
> +static inline int sci_assign_dt_device(struct domain *d,
> +                                       struct dt_device_node *dev)
> +{
> +    return 0;
> +}
> +
> +#endif /* CONFIG_ARM_SCI */
> +
> +#endif /* __ASM_ARM_SCI_H */
> diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c
> index 6081f14ed0..2469738fcc 100644
> --- a/xen/arch/arm/vsmc.c
> +++ b/xen/arch/arm/vsmc.c
> @@ -12,6 +12,7 @@
>  #include <public/arch-arm/smccc.h>
>  #include <asm/cpuerrata.h>
>  #include <asm/cpufeature.h>
> +#include <asm/firmware/sci.h>
>  #include <asm/monitor.h>
>  #include <asm/regs.h>
>  #include <asm/smccc.h>
> @@ -300,6 +301,8 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs)
>              break;
>          case ARM_SMCCC_OWNER_SIP:
>              handled = handle_sip(regs);
> +            if ( !handled )
> +                handled = sci_handle_call(regs);
>              break;
>          case ARM_SMCCC_OWNER_TRUSTED_APP ... ARM_SMCCC_OWNER_TRUSTED_APP_END:
>          case ARM_SMCCC_OWNER_TRUSTED_OS ... ARM_SMCCC_OWNER_TRUSTED_OS_END:
> diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c
> index 0012046574..f29656a27e 100644
> --- a/xen/common/device-tree/dom0less-build.c
> +++ b/xen/common/device-tree/dom0less-build.c
> @@ -228,6 +228,10 @@ static int __init handle_passthrough_prop(struct kernel_info *kinfo,
>      if ( res < 0 )
>          return res;
>  
> +    res = arch_handle_passthrough_prop(kinfo, node);
> +    if ( res )
> +        return res;
> +
>      /* If xen_force, we allow assignment of devices without IOMMU protection. */
>      if ( xen_force && !dt_device_is_protected(node) )
>          return 0;
> diff --git a/xen/include/asm-generic/device.h b/xen/include/asm-generic/device.h
> index 1acd1ba1d8..e96c5558c2 100644
> --- a/xen/include/asm-generic/device.h
> +++ b/xen/include/asm-generic/device.h
> @@ -18,6 +18,7 @@ enum device_class
>      DEVICE_IOMMU,
>      DEVICE_INTERRUPT_CONTROLLER,
>      DEVICE_PCI_HOSTBRIDGE,
> +    DEVICE_FIRMWARE,
>      /* Use for error */
>      DEVICE_UNKNOWN,
>  };
> diff --git a/xen/include/asm-generic/dom0less-build.h b/xen/include/asm-generic/dom0less-build.h
> index e0ad0429ec..1c56441c33 100644
> --- a/xen/include/asm-generic/dom0less-build.h
> +++ b/xen/include/asm-generic/dom0less-build.h
> @@ -61,6 +61,9 @@ void set_domain_type(struct domain *d, struct kernel_info *kinfo);
>  int init_intc_phandle(struct kernel_info *kinfo, const char *name,
>                        const int node_next, const void *pfdt);
>  
> +int arch_handle_passthrough_prop(struct kernel_info *kinfo,
> +                                 struct dt_device_node *node);
> +
>  #else /* !CONFIG_DOM0LESS_BOOT */
>  
>  static inline void create_domUs(void) {}
> @@ -70,6 +73,12 @@ static inline bool is_dom0less_mode(void)
>  }
>  static inline void set_xs_domain(struct domain *d) {}
>  
> +static inline int arch_handle_passthrough_prop(struct kernel_info *kinfo,
> +                                               struct dt_device_node *node)
> +{
> +    return 0;
> +}
> +
>  #endif /* CONFIG_DOM0LESS_BOOT */
>  
>  #endif /* __ASM_GENERIC_DOM0LESS_BUILD_H__ */
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index 24840eeaa6..55eed9992c 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -327,6 +327,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>  #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
>  #define XEN_DOMCTL_CONFIG_TEE_FFA       2
>  
> +#define XEN_DOMCTL_CONFIG_ARM_SCI_NONE      0
> +
>  struct xen_arch_domainconfig {
>      /* IN/OUT */
>      uint8_t gic_version;
> @@ -350,6 +352,8 @@ struct xen_arch_domainconfig {
>       *
>       */
>      uint32_t clock_frequency;
> +    /* IN */
> +    uint8_t arm_sci_type;
>  };
>  #endif /* __XEN__ || __XEN_TOOLS__ */
>  
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem
  2025-07-22 11:41 ` [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem Oleksii Moisieiev
@ 2025-08-23  0:26   ` Stefano Stabellini
  2025-08-27  9:02     ` Oleksii Moisieiev
  0 siblings, 1 reply; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-23  0:26 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> From: Grygorii Strashko <grygorii_strashko@epam.com>
> 
> The introduced SCI (System Control Interface) subsystem provides unified
> interface to integrate in Xen SCI drivers which adds support for ARM
> firmware (EL3, SCP) based software interfaces (like SCMI) that are used in
> system management. The SCI subsystem allows to add drivers for different FW
> interfaces or have different drivers for the same FW interface (for example,
> SCMI with different transports).
> 
> This patch updates SCMI over SMC calls handling layer, introduced by
> commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls handling
> layer"), to be SCI driver:
> - convert to DT device;
> - convert to SCI Xen interface.
> 
> There are no functional changes in general, the driver is just adopted
> to the SCI interface.
> 
> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> ---
> 
> 
> 
>  xen/arch/arm/firmware/Kconfig                | 13 ++-
>  xen/arch/arm/firmware/scmi-smc.c             | 93 +++++++++++---------
>  xen/arch/arm/include/asm/firmware/scmi-smc.h | 41 ---------
>  xen/arch/arm/vsmc.c                          |  5 +-
>  xen/include/public/arch-arm.h                |  1 +
>  5 files changed, 64 insertions(+), 89 deletions(-)
>  delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
> 
> diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
> index fc7918c7fc..bbf88fbb9a 100644
> --- a/xen/arch/arm/firmware/Kconfig
> +++ b/xen/arch/arm/firmware/Kconfig
> @@ -8,9 +8,18 @@ config ARM_SCI
>  
>  menu "Firmware Drivers"
>  
> +choice
> +	prompt "ARM SCI driver type"
> +	default SCMI_SMC
> +	help
> +	Choose which ARM SCI driver to enable.
> +
> +config ARM_SCI_NONE
> +	bool "none"
> +
>  config SCMI_SMC
>  	bool "Forward SCMI over SMC calls from hwdom to EL3 firmware"
> -	default y
> +	select ARM_SCI
>  	help
>  	  This option enables basic awareness for SCMI calls using SMC as
>  	  doorbell mechanism and Shared Memory for transport ("arm,scmi-smc"
> @@ -18,4 +27,6 @@ config SCMI_SMC
>  	  firmware node is used to trap and forward corresponding SCMI SMCs
>  	  to firmware running at EL3, for calls coming from the hardware domain.
>  
> +endchoice
> +
>  endmenu
> diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c
> index 33473c04b1..13d1137592 100644
> --- a/xen/arch/arm/firmware/scmi-smc.c
> +++ b/xen/arch/arm/firmware/scmi-smc.c
> @@ -9,6 +9,7 @@
>   * Copyright 2024 NXP
>   */
>  
> +#include <asm/device.h>
>  #include <xen/acpi.h>
>  #include <xen/device_tree.h>
>  #include <xen/errno.h>
> @@ -16,12 +17,11 @@
>  #include <xen/sched.h>
>  #include <xen/types.h>
>  
> +#include <asm/firmware/sci.h>
>  #include <asm/smccc.h>
> -#include <asm/firmware/scmi-smc.h>
>  
>  #define SCMI_SMC_ID_PROP   "arm,smc-id"
>  
> -static bool __ro_after_init scmi_enabled;
>  static uint32_t __ro_after_init scmi_smc_id;
>  
>  /*
> @@ -41,14 +41,11 @@ static bool scmi_is_valid_smc_id(uint32_t fid)
>   *
>   * Returns true if SMC was handled (regardless of response), false otherwise.
>   */
> -bool scmi_handle_smc(struct cpu_user_regs *regs)
> +static bool scmi_handle_smc(struct cpu_user_regs *regs)
>  {
>      uint32_t fid = (uint32_t)get_user_reg(regs, 0);
>      struct arm_smccc_res res;
>  
> -    if ( !scmi_enabled )
> -        return false;
> -
>      if ( !scmi_is_valid_smc_id(fid) )
>          return false;
>  
> @@ -78,49 +75,45 @@ bool scmi_handle_smc(struct cpu_user_regs *regs)
>      return true;
>  }
>  
> -static int __init scmi_check_smccc_ver(void)
> +static int scmi_smc_domain_init(struct domain *d,
> +                                struct xen_domctl_createdomain *config)
>  {
> -    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
> -    {
> -        printk(XENLOG_WARNING
> -               "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
> -        return -ENOSYS;
> -    }
> +    if ( !is_hardware_domain(d) )
> +        return 0;

Should we also check for config->arch.sci_type ==
XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC ?


> +    d->arch.sci_enabled = true;
> +    printk(XENLOG_DEBUG "SCMI: %pd init\n", d);
>      return 0;
>  }



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 04/10] docs: arm: add docs for SCMI over SMC calls forwarding driver
  2025-07-22 11:41 ` [RFC PATCH v5 04/10] docs: arm: add docs for SCMI over SMC calls forwarding driver Oleksii Moisieiev
@ 2025-08-23  0:30   ` Stefano Stabellini
  0 siblings, 0 replies; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-23  0:30 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> From: Grygorii Strashko <grygorii_strashko@epam.com>
> 
> Add documentation section for Simple Arm SCMI over SMC/HVC calls forwarding
> driver (EL3).
> 
> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>

This doc looks good, a couple of minor suggestions:
- briefly document the bindings expected as input (e.g. compatible
  "arm,scmi-smc" and "arm,scmi-shmem") or simply provide links to official docs
- it says "SCMI over SMC/HVC" but I am not sure if HVC would actually
  work


> ---
> 
> Changes in v5:
> - rename dom0_scmi_smc_passthrough in documentation
> 
>  .../arm/firmware/arm-scmi.rst                 | 177 ++++++++++++++++++
>  docs/hypervisor-guide/arm/index.rst           |   9 +
>  docs/hypervisor-guide/index.rst               |   1 +
>  3 files changed, 187 insertions(+)
>  create mode 100644 docs/hypervisor-guide/arm/firmware/arm-scmi.rst
>  create mode 100644 docs/hypervisor-guide/arm/index.rst
> 
> diff --git a/docs/hypervisor-guide/arm/firmware/arm-scmi.rst b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
> new file mode 100644
> index 0000000000..a084c0caa3
> --- /dev/null
> +++ b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
> @@ -0,0 +1,177 @@
> +.. SPDX-License-Identifier: CC-BY-4.0
> +
> +ARM System Control and Management Interface (SCMI)
> +==================================================
> +
> +The System Control and Management Interface (SCMI) [1], which is a set of operating
> +system-independent software interfaces that are used in system management. SCMI currently
> +provides interfaces for:
> +
> +- Discovery and self-description of the interfaces it supports
> +- Power domain management
> +- Clock management
> +- Reset domain management
> +- Voltage domain management
> +- Sensor management
> +- Performance management
> +- Power capping and monitoring
> +- Pin control protocol.
> +
> +The SCMI compliant firmware could run:
> +
> +- as part of EL3 secure world software (like Trusted Firmware-A) with
> +  ARM SMC/HVC shared-memory transport;
> +- on dedicated System Control Processor (SCP) with HW mailbox shared-memory transport
> +
> +The major purpose of enabling SCMI support in Xen is to enable guest domains access to the SCMI
> +interfaces for performing management actions on passed-through devices (such as clocks/resets etc)
> +without accessing directly to the System control HW (like clock controllers) which in most cases
> +can't shared/split between domains. Or, at minimum, allow SCMI access for dom0/hwdom (or guest
> +domain serving as Driver domain).
> +
> +The below sections describe SCMI support options available for Xen.
> +
> +[1] `Arm SCMI <https://developer.arm.com/documentation/den0056/latest/>`_
> +
> +Simple SCMI over SMC/HVC calls forwarding driver (EL3)
> +------------------------------------------------------
> +
> +The EL3 SCMI firmware (TF-A) with a single SCMI OSPM agent support is pretty generic case for
> +the default vendors SDK and new platforms with SCMI support. Such EL3 SCMI firmware supports only
> +single SCMI OSPM transport (agent) with Shared memory based transport and SMC/HVC calls as doorbell.
> +
> +The SCMI over SMC/HVC calls forwarding driver solves major problem for this case by allowing
> +SMC/HVC calls to be forwarded form guest to the EL3 SCMI firmware.
> +
> +By default, the SCMI over SMC/HVC calls forwarding is enabled for Dom0/hwdom.
> +
> +::
> +
> +    +--------------------------+
> +    |                          |
> +    | EL3 SCMI FW (TF-A)       |
> +    ++-------+--^--------------+
> +     |shmem  |  | smc-id
> +     +----^--+  |
> +          |     |
> +     +----|-+---+---+----------+
> +     |    | |  FWD  |      Xen |
> +     |    | +---^---+          |
> +     +----|-----|--------------+
> +          |     | smc-id
> +     +----v-----+--+ +---------+
> +     |             | |         |
> +     | Dom0/hwdom  | | DomU    |
> +     |             | |         |
> +     |             | |         |
> +     +-------------+ +---------+
> +
> +
> +The SCMI messages are passed directly through SCMI shared-memory (zero-copy) and driver only
> +forwards SMC/HVC calls.
> +
> +Compiling
> +^^^^^^^^^
> +
> +To build with the SCMI over SMC/HVC calls forwarding enabled support, enable Kconfig option
> +
> +::
> +
> +    CONFIG_SCMI_SMC
> +
> +The ``CONFIG_SCMI_SMC`` is enabled by default.
> +
> +Pass-through SCMI SMC to domain which serves as Driver domain
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +This section describes how to configure the SCMI over SMC/HVC calls forwarding driver to handle use
> +case "thin Dom0 with guest domain, which serves as Driver domain". In this case HW need to be
> +enabled in Driver domain and dom0 is performing only control functions (without accessing FW) and so,
> +the SCMI need to be enabled in Driver domain.
> +
> +::
> +
> +     +--------------------------+
> +     |EL3 SCMI FW (TF-A)        |
> +     |                          |
> +     +-------------^--+-------+-+
> +             smc-id|  |shmem0 |
> +                   |  +----^--+
> +    +-------------++------+|----+
> +    |Xen          |  FWD  ||    |
> +    |             +--^----+|    |
> +    +----------------|-----|----+
> +              smc-id |     |
> +    +-----------+ +--+-----v-----+
> +    |           | |              |
> +    | Dom0      | |    Driver    |
> +    | Control   | |    domain    |
> +    |           | |              |
> +    +-----------+ +--------------+
> +
> +The SCMI can be enabled for one and only one guest domain.
> +
> +First. configure Dom0 to enable SCMI pass-through using Xen Command Line
> +**"scmi_smc_passthrough"** option. This will disable SCMI for Dom0/hwdom and SCMI nodes will
> +be removed from Dom0/hwdom device tree.
> +
> +**Configure SCMI pass-through for guest domain with toolstack**
> +
> +* In domain's xl.cfg file add **"arm_sci"** option as below
> +
> +::
> +
> +    arm_sci = "type=scmi_smc"
> +
> +* In domain's xl.cfg file enable access to the "arm,scmi-shmem"
> +
> +::
> +
> +    iomem = [
> +        "47ff0,1@22001",
> +    ]
> +
> +.. note:: It's up to the user to select guest IPA for mapping SCMI shared-memory.
> +
> +* Add SCMI nodes to the Driver domain partial device tree as in the below example:
> +
> +.. code::
> +
> +    passthrough {
> +       scmi_shm_0: sram@22001000 {
> +           compatible = "arm,scmi-shmem";
> +           reg = <0x0 0x22001000 0x0 0x1000>;
> +       };
> +
> +       firmware {
> +            compatible = "simple-bus";
> +                scmi: scmi {
> +                    compatible = "arm,scmi-smc";
> +                    shmem = <&scmi_shm_0>;
> +                    ...
> +                }
> +        }
> +    }
> +
> +In general, the configuration is similar to any other HW pass-through, except explicitly
> +enabling SCMI with "arm_sci" xl.cfg option.
> +
> +**Configure SCMI pass-through for predefined domain (dom0less)**
> +
> +* add "xen,sci_type" property for required DomU ("xen,domain") node
> +
> +::
> +
> +       xen,sci_type="scmi_smc"
> +
> +* add scmi nodes to the Driver domain partial device tree the same way as above and enable access
> +  to the "arm,scmi-shmem" according to  dom0less documentation. For example:
> +
> +.. code::
> +
> +      scmi_shm_0: sram@22001000 {
> +            compatible = "arm,scmi-shmem";
> +            reg = <0x00 0x22001000 0x00 0x1000>;
> +    ->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
> +    ->        xen,force-assign-without-iommu;
> +      };
> diff --git a/docs/hypervisor-guide/arm/index.rst b/docs/hypervisor-guide/arm/index.rst
> new file mode 100644
> index 0000000000..7aae4a0a03
> --- /dev/null
> +++ b/docs/hypervisor-guide/arm/index.rst
> @@ -0,0 +1,9 @@
> +.. SPDX-License-Identifier: CC-BY-4.0
> +
> +ARM
> +===
> +
> +.. toctree::
> +   :maxdepth: 2
> +
> +   firmware/arm-scmi
> diff --git a/docs/hypervisor-guide/index.rst b/docs/hypervisor-guide/index.rst
> index e4393b0697..520fe01554 100644
> --- a/docs/hypervisor-guide/index.rst
> +++ b/docs/hypervisor-guide/index.rst
> @@ -9,3 +9,4 @@ Hypervisor documentation
>     code-coverage
>  
>     x86/index
> +   arm/index
> \ No newline at end of file
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 07/10] xen: arm: smccc: add INVALID_PARAMETER error code
  2025-07-22 11:41 ` [RFC PATCH v5 07/10] xen: arm: smccc: add INVALID_PARAMETER error code Oleksii Moisieiev
@ 2025-08-23  0:33   ` Stefano Stabellini
  0 siblings, 0 replies; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-23  0:33 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> According to the "7.1 Return Codes" section of DEN0028 [1]
> INVALID_PARAMETER code (-3) is returned when one of the call
> parameters has a non-supported value.
> Adding this error code to the common smccc header file.
> 
> [1]: https://documentation-service.arm.com/static/5f8edaeff86e16515cdbe4c6
> 
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>

Acked-by: Stefano Stabellini <sstabellini@kernel.org>

> ---
> 
> 
> 
>  xen/arch/arm/include/asm/smccc.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/xen/arch/arm/include/asm/smccc.h b/xen/arch/arm/include/asm/smccc.h
> index a289c48b7f..dc6af94db1 100644
> --- a/xen/arch/arm/include/asm/smccc.h
> +++ b/xen/arch/arm/include/asm/smccc.h
> @@ -381,6 +381,7 @@ void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args,
>                         0x3FFF)
>  
>  /* SMCCC error codes */
> +#define ARM_SMCCC_INVALID_PARAMETER     (-3)
>  #define ARM_SMCCC_NOT_REQUIRED          (-2)
>  #define ARM_SMCCC_ERR_UNKNOWN_FUNCTION  (-1)
>  #define ARM_SMCCC_NOT_SUPPORTED         (-1)
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support
  2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
                   ` (9 preceding siblings ...)
  2025-07-22 11:41 ` [RFC PATCH v5 10/10] docs: arm: add SCI SCMI SMC multi-agent driver docs Oleksii Moisieiev
@ 2025-08-23  0:34 ` Stefano Stabellini
  2025-08-27  9:10   ` Oleksii Moisieiev
  10 siblings, 1 reply; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-23  0:34 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

I think it should be feasible to commit at least patches 1-4 in time for
the release

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> Inroducing V4 RFC patch series  on top of the Xen version 4.20-rc2
> which includes implementation of the SCI SCMI SMC multi-agent support.
> 
> Patch 1 "xen/arm: add generic SCI subsystem"
> - rebased and refactored
> - introduced DEVICE_ARM_SCI DT device class and used for SCI drivers probing
> instead of custom,
>   linker sections based implementation.
> - added SCI API for Dom0 DT handling, instead of manipulating with ARM arch
> dom0 code directly.
> - RFC changes in XEN_DOMCTL_assign_device OP processing
> - Introduce arch_handle_passthrough_prop call to handle arm specific
> nodes
> 
> Patch 2 "xen/arm: scmi-smc: update to be used under sci subsystem"
> - update driver introduced by commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI
> over SMC calls
> handling layer") be used under sci subsystem.
> - no functional changes in general
> 
> Patch 3 "xen/arm: scmi-smc: passthrough SCMI SMC to guest domain
> This is new change which allows passthrough SCMI SMC, single agent interface to
> guest domain
> cover use case "thin Dom0 with guest domain, which serves as Driver domain".
> See patch commit message for full description.
> 
> Patch 4 - docs: arm: add docs for SCMI over SMC calls forwarding
> driver
> - add documentation section for Simple Arm SCMI over SMC/HVC calls
> forwarding driver.
> 
> Patch 6 - xen/domctl: extend XEN_DOMCTL_assign_device to handle not
> only iommu
> - add chainged handling of assigned DT devices to support
> access-controller functionality through SCI framework.
> Change was done in two parts:
>  - update iommu_do_dt_domctl() to check for dt_device_is_protected()
>  and not fail if DT device is not protected by IOMMU
>  -add chained call to sci_do_domctl() to do_domctl()
> 
> Patch 9 - xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
> - added "scmi-secondary-agents" and "#scmi-secondary-agent-cells"
>   property to "xen,config" node in "chosen" to inform SCI SCMI
>   multi-agent driver about available agents and their
>   configuration. It defines <agent_id> to <smc-id,scmi_shm> map.
>   This option is Xen specific as Xen is the only one entry in the
>   system which need to know about SCMI multi-agent support and configuration.
> - each guest using SCMI should be configured with SCMI agent_id, so SCMI
>   FW can implement Agent-specific permission policy.
>   -- dom0: dom0_scmi_agent_id=<agent_id> in Xen command line option
>   -- toolstack: arm_sci = "type=scmi_smc_multiagent,agent_id=<agent_id>"
>   -- dom0less: "xen,sci_type", "xen,sci_agent_id" properties in
> "xen,domain" nodes.
> - factored out SCMI generic definitions (re-usable)
> - factored out SCMI shmem code (re-usable)
> - the SCMI passthrough configuration for guest domains is similar to any other
> HW passthrough cfg.
> 
> Patch 10 - docs: arm: add SCI SCMI SMC multi-agent driver docs
> - add SCI SCMI SMC multi-agent driver documentation.
> 
> Add separate SCMI DT node for Xen management agent under "xen,config"
> node under chosen.
> 
> All Xen-specific configuration provided under "/chosen" node. This
> approach allows to isolate modifications to Host DT only under
> "/chosen" node.
> 
> This approach provides the following device tree (DT)
> parameters (placed under xen,config node):
> 
> - "scmi-secondary-agents": A Xen-specific parameter under the
>   "/chosen" node, which describes the SCMI agent configuration for
>   the domains.
> - the SCMI configuration for Xen (privileged agent) and the shared
>   memory configuration for all agents are provided under the "/chosen"
>   node and are used strictly by Xen for its initial configuration.
> - the scmi_shm and SCMI configuration for Dom0 are placed in the
>   "/firmware/scmi" node so that they can be moved to Dom0 without
>   any changes.
> 
> This configuration allows the use of Xen-specific nodes to provide
> information strictly needed by Xen while using the default SCMI
> configuration for Dom0 and other domains. As a result, no additional
> bindings need to be introduced to the device tree.
> This simplifies the Xen SCMI multi-agent configuration and utilizes
> generic device tree bindings for the domains.
> 
> NOTE: Haven't added RB tags for patch 1 and 2 because rebase and some
> minor changes were done.
> 
> Code can be found at:
> https://github.com/oleksiimoisieiev/xen/tree/scmi_upstrv5
> 
> [1] RFC v2:
> http://patchwork.kernel.org/project/xen-devel/cover/cover.1644341635.git.oleksii_moisieiev@epam.com/
> [2] RFC v3:
> https://patchwork.kernel.org/project/xen-devel/patch/20250311111618.1850927-1-grygorii_strashko@epam.com
> SCMI spec:
> https://developer.arm.com/documentation/den0056/e/?lang=en
> 
> SCMI bindings:
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml
> 
> Reference EL3 FW:
> RPI5: https://github.com/xen-troops/arm-trusted-firmware/commits/rpi5_dev/
> Renesas v4h:
> https://github.com/GrygiriiS/arm-trusted-firmware/commits/rcar_gen4_v2.7_v4x-scmi_upd/
> 
> base-commit: dbe60f244c (Update Xen to 4.21, 2025-02-21)
> 
> Changes in v5:
> - update Maintainers file. Set role as a Reviewer
> - rebased on the latest master branch
> - Introduce arch_handle_passthrough_prop call to handle arm specific nodes
> - rename dom0_scmi_smc_passthrough to scmi_smc_passthrough
> - rename dom0_scmi_smc_passthrough in documentation
> - set error code to -ENXIO when iommu is disabled
> - return -EINVAL if mediator without assign_dt_device was provided
> - invert return code check for iommu_do_domctl in
> XEN_DOMCTL_assign_device domctl processing to make cleaner code
> - change -ENOTSUPP error code to -ENXIO in sci_do_domctl
> - handle -ENXIO return comde of iommu_do_domctl
> - leave !dt_device_is_protected check in iommu_do_dt_domctl to make
> code work the same way it's done in "handle_device" call while
> creating hwdom(dom0) and "handle_passthrough_prop" call for dom0less
> creation
> - drop return check from sci_assign_dt_device call as not needed
> - do not return EINVAL when addign_dt_device is not set. That is
> because this callback is optional and not implemented in single-agent driver
> - move memcpy_toio/fromio to the generic place
> - fix device-tree example format in booting.txt, added ";" after "}".
> - update define in scmi-proto.h
> - update define in scmi-shmem.h file
> - scmi_assign_device - do not ignore -EOPNOTSUPP return
> code of the do_smc_xfer
> - remove overwriting agent_channel->agent_id after
> SCMI_BASE_DISCOVER_AGENT call
> - add multi-agent files to the MAINTAINERS
> - add SCMI multi-agent description to the SUPPORT.md
> - handle ARM_SMCCC_INVALID_PARAMETER return code and return -EINVAL
> for smc call
> - updated collect_agents function. Set agent_id parameter as optional
> in scmi-secondary-agents device-tree property
> - introduce "#scmi-secondary-agents-cells" parameter to set if
> agent_id was provided
> - reanme xen,scmi-secondary-agents property to scmi-secondary-agents
> - move memcpu_toio/fromio for the generic place
> - update Xen to get management channel from /chosen/xen,config node
> - get hypervisor channnel from node instead of using hardcoded
> - update handling scmi and shmem nodes for the domain
> - Set multi-agent driver to support only Arm64
> - rework multi-agent driver to leave Host Device-tree unmodified
> 
> Changes in v4:
> - fix SPDX-License
> - rename DEVICE_ARM_SCI DT device class to FIRMWARE_DEVICE
> - move XEN_DOMCTL_assign_device code in separate patch
> - Add documentation for SCI SCMI drivers
> - xl.cfg doc
> - fix comments from Stefano Stabellini
> - fix toolstack code as sugested by Anthony PERARD
>   - use MATCH_OPTION()
>   - move arm_sci struct and cfg params in "arch_arm"
> - add SCMI passthrough for dom0less case
> - toolstack comments from Anthony PERARD
> - added dom0less support
> - added doc for "xen,scmi-secondary-agents"
> 
> Grygorii Strashko (5):
>   xen/arm: scmi-smc: update to be used under sci subsystem
>   xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
>   docs: arm: add docs for SCMI over SMC calls forwarding driver
>   xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
>   docs: arm: add SCI SCMI SMC multi-agent driver docs
> 
> Oleksii Moisieiev (5):
>   xen/arm: add generic SCI subsystem
>   drivers: iommu: change error code when iommu is disabled
>   xen: arm: smccc: add INVALID_PARAMETER error code
>   lib/arm: Add I/O memory copy helpers
>   xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
> 
>  MAINTAINERS                                   |  10 +
>  SUPPORT.md                                    |  11 +
>  .../arm/firmware/arm-scmi.rst                 | 516 +++++++++++
>  docs/hypervisor-guide/arm/index.rst           |   9 +
>  docs/hypervisor-guide/index.rst               |   1 +
>  docs/man/xl.cfg.5.pod.in                      |  47 +
>  docs/misc/arm/device-tree/booting.txt         | 103 +++
>  docs/misc/xen-command-line.pandoc             |  18 +
>  tools/include/libxl.h                         |   5 +
>  tools/libs/light/libxl_arm.c                  |  18 +
>  tools/libs/light/libxl_types.idl              |  12 +
>  tools/xl/xl_parse.c                           |  48 ++
>  xen/arch/arm/device.c                         |   5 +
>  xen/arch/arm/dom0less-build.c                 |  51 ++
>  xen/arch/arm/domain.c                         |  12 +-
>  xen/arch/arm/domain_build.c                   |  11 +-
>  xen/arch/arm/firmware/Kconfig                 |  37 +-
>  xen/arch/arm/firmware/Makefile                |   2 +
>  xen/arch/arm/firmware/sci.c                   | 189 +++++
>  xen/arch/arm/firmware/scmi-proto.h            | 164 ++++
>  xen/arch/arm/firmware/scmi-shmem.c            | 112 +++
>  xen/arch/arm/firmware/scmi-shmem.h            |  45 +
>  xen/arch/arm/firmware/scmi-smc-multiagent.c   | 803 ++++++++++++++++++
>  xen/arch/arm/firmware/scmi-smc.c              | 191 ++++-
>  xen/arch/arm/include/asm/domain.h             |   5 +
>  xen/arch/arm/include/asm/firmware/sci.h       | 214 +++++
>  xen/arch/arm/include/asm/firmware/scmi-smc.h  |  41 -
>  xen/arch/arm/include/asm/smccc.h              |   1 +
>  xen/arch/arm/vsmc.c                           |   4 +-
>  xen/common/device-tree/dom0less-build.c       |   4 +
>  xen/common/domctl.c                           |  19 +
>  xen/drivers/passthrough/device_tree.c         |   6 +
>  xen/drivers/passthrough/iommu.c               |   2 +-
>  xen/include/asm-generic/device.h              |   1 +
>  xen/include/asm-generic/dom0less-build.h      |   9 +
>  xen/include/public/arch-arm.h                 |   8 +
>  xen/include/xen/lib/arm/io.h                  |  15 +
>  xen/lib/Makefile                              |   1 +
>  xen/lib/arm/Makefile                          |   1 +
>  xen/lib/arm/io.c                              |  80 ++
>  40 files changed, 2744 insertions(+), 87 deletions(-)
>  create mode 100644 docs/hypervisor-guide/arm/firmware/arm-scmi.rst
>  create mode 100644 docs/hypervisor-guide/arm/index.rst
>  create mode 100644 xen/arch/arm/firmware/sci.c
>  create mode 100644 xen/arch/arm/firmware/scmi-proto.h
>  create mode 100644 xen/arch/arm/firmware/scmi-shmem.c
>  create mode 100644 xen/arch/arm/firmware/scmi-shmem.h
>  create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c
>  create mode 100644 xen/arch/arm/include/asm/firmware/sci.h
>  delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
>  create mode 100644 xen/include/xen/lib/arm/io.h
>  create mode 100644 xen/lib/arm/Makefile
>  create mode 100644 xen/lib/arm/io.c
> 
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers
  2025-07-22 11:41 ` [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers Oleksii Moisieiev
  2025-07-22 12:43   ` Jan Beulich
@ 2025-08-23  0:40   ` Stefano Stabellini
  1 sibling, 0 replies; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-23  0:40 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> This commit introduces two helper functions, `__memcpy_fromio` and
> `__memcpy_toio`, to provide a robust mechanism for copying data between
> standard memory and memory-mapped I/O (MMIO) space for the ARM
> architecture.
> 
> These functions are designed to handle memory transfers safely,
> accounting for potential address alignment issues to ensure correctness
> and improve performance where possible. The implementation is specific
> to ARM and uses relaxed I/O accessors.
> 
> __memcpy_fromio:
> Copies a block of data from an I/O memory source to a destination in
> standard ("real") memory. The implementation first handles any unaligned
> bytes at the beginning of the source buffer individually using byte-wise
> reads. It then copies the bulk of the data using 32-bit reads for
> efficiency, and finally processes any remaining bytes at the end of the
> buffer.
> 
> __memcpy_toio:
> Copies a block of data from standard memory to a destination in I/O
> memory space. It follows a similar strategy, handling any initial
> unaligned portion of the destination buffer byte-by-byte before using
> more efficient 32-bit writes for the main, aligned part of the transfer.
> Any trailing bytes are also handled individually.
> xen/include/xen/lib/arm/io.h
> 
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> ---
> 
> Changes in v5:
> - move memcpy_toio/fromio to the generic place
> 
>  xen/include/xen/lib/arm/io.h | 15 +++++++
>  xen/lib/Makefile             |  1 +
>  xen/lib/arm/Makefile         |  1 +
>  xen/lib/arm/io.c             | 80 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 97 insertions(+)
>  create mode 100644 xen/include/xen/lib/arm/io.h
>  create mode 100644 xen/lib/arm/Makefile
>  create mode 100644 xen/lib/arm/io.c
> 
> diff --git a/xen/include/xen/lib/arm/io.h b/xen/include/xen/lib/arm/io.h
> new file mode 100644
> index 0000000000..86973660ba
> --- /dev/null
> +++ b/xen/include/xen/lib/arm/io.h
> @@ -0,0 +1,15 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +#ifndef _XEN_LIB_ARM_IO_H
> +#define _XEN_LIB_ARM_IO_H
> +
> +#include <xen/types.h>
> +
> +/*
> + * Prototypes for I/O memory access functions.
> + */
> +extern void __memcpy_fromio(void *to, const volatile void __iomem *from,
> +                     size_t count);
> +extern void __memcpy_toio(volatile void __iomem *to, const void *from,
> +                   size_t count);
> +
> +#endif /* _XEN_LIB_ARM_IO_H */
> diff --git a/xen/lib/Makefile b/xen/lib/Makefile
> index 5ccb1e5241..efa8157a72 100644
> --- a/xen/lib/Makefile
> +++ b/xen/lib/Makefile
> @@ -1,4 +1,5 @@
>  obj-$(CONFIG_X86) += x86/
> +obj-$(CONFIG_ARM) += arm/
>  
>  lib-y += bsearch.o
>  lib-y += ctors.o
> diff --git a/xen/lib/arm/Makefile b/xen/lib/arm/Makefile
> new file mode 100644
> index 0000000000..87250b3822
> --- /dev/null
> +++ b/xen/lib/arm/Makefile
> @@ -0,0 +1 @@
> +obj-y += io.o
> \ No newline at end of file
> diff --git a/xen/lib/arm/io.c b/xen/lib/arm/io.c
> new file mode 100644
> index 0000000000..d267bd28e4
> --- /dev/null
> +++ b/xen/lib/arm/io.c
> @@ -0,0 +1,80 @@
> +#include <asm/io.h>
> +#include <xen/lib/arm/io.h>

Please add the SPDX tag


> +/*
> + * memcpy_fromio - Copy data from IO memory space to "real" memory space.
> + * @to: Where to copy to
> + * @from: Where to copy from
> + * @count: The size of the area.
> + */
> +void __memcpy_fromio(void *to, const volatile void __iomem *from,
> +                     size_t count)
> +{
> +    while ( count && !IS_ALIGNED((unsigned long)from, 4) )
> +    {
> +        *(u8 *)to = readb_relaxed(from);
> +        from++;
> +        to++;
> +        count--;
> +    }
> +
> +    while ( count >= 4 )
> +    {
> +        *(u32 *)to = readl_relaxed(from);
> +        from += 4;
> +        to += 4;
> +        count -= 4;
> +    }
> +
> +    while ( count )
> +    {
> +        *(u8 *)to = readb_relaxed(from);
> +        from++;
> +        to++;
> +        count--;
> +    }
> +}
> +
> +/*
> + * memcpy_toio - Copy data from "real" memory space to IO memory space.
> + * @to: Where to copy to
> + * @from: Where to copy from
> + * @count: The size of the area.
> + */
> +void __memcpy_toio(volatile void __iomem *to, const void *from,
> +                   size_t count)
> +{
> +    while ( count && !IS_ALIGNED((unsigned long)to, 4) )
> +    {
> +        writeb_relaxed(*(u8 *)from, to);
> +        from++;
> +        to++;
> +        count--;
> +    }
> +
> +    while ( count >= 4 )
> +    {
> +        writel_relaxed(*(u32 *)from, to);
> +        from += 4;
> +        to += 4;
> +        count -= 4;
> +    }
> +
> +    while ( count )
> +    {
> +        writeb_relaxed(*(u8 *)from, to);
> +        from++;
> +        to++;
> +        count--;
> +    }
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 8
> + * tab-width: 8
> + * indent-tabs-mode: t
> + * End:
> + */
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
  2025-07-22 11:41 ` [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Oleksii Moisieiev
  2025-07-22 12:46   ` Jan Beulich
  2025-07-30 13:29   ` Anthony PERARD
@ 2025-08-26  0:37   ` Stefano Stabellini
  2025-08-27 19:35   ` Oleksandr Tyshchenko
  3 siblings, 0 replies; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-26  0:37 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> This patch introduces SCI driver to support for ARM EL3 Trusted Firmware-A
> (TF-A) which provides SCMI interface with multi-agnet support, as shown

multi-agent


> below.
> 
>   +-----------------------------------------+
>   |                                         |
>   | EL3 TF-A SCMI                           |
>   +-------+--+-------+--+-------+--+-------++
>   |shmem1 |  |shmem0 |  |shmem2 |  |shmemX |
>   +-----+-+  +---+---+  +--+----+  +---+---+
> smc-id1 |        |         |           |
> agent1  |        |         |           |
>   +-----v--------+---------+-----------+----+
>   |              |         |           |    |
>   |              |         |           |    |
>   +--------------+---------+-----------+----+
>          smc-id0 |  smc-id2|    smc-idX|
>          agent0  |  agent2 |    agentX |
>                  |         |           |
>             +----v---+  +--v-----+  +--v-----+
>             |        |  |        |  |        |
>             | Dom0   |  | Dom1   |  | DomX   |
>             |        |  |        |  |        |
>             |        |  |        |  |        |
>             +--------+  +--------+  +--------+
> 
> The EL3 SCMI multi-agent firmware expected to provide SCMI SMC/HVC shared
> memory transport for every Agent in the system.
> 
> The SCMI Agent transport channel defined by pair:
>  - smc-id: SMC/HVC id used for Doorbell
>  - shmem: shared memory for messages transfer, Xen page
>  aligned. Shared memort is mapped with the following flags:
>  MT_DEVICE_nGnRE.
> 
> The follwoing SCMI Agents expected to be defined by SCMI FW to enable SCMI
> multi-agent functionality under Xen:
> - Xen manegement agent: trusted agents that accesses to the Base Protocol

management


> commands to configure agent specific permissions
> - OSPM VM agents: non-trusted agent, one for each Guest domain which is
>   allowed direct HW access. At least one OSPM VM agent has to be provided
>   by FW if HW is handled only by Dom0 or Driver Domain.
> 
> The EL3 SCMI FW expected to implement following Base protocol messages:
> - BASE_DISCOVER_AGENT (optional if agent_id was provided)
> - BASE_RESET_AGENT_CONFIGURATION (optional)
> - BASE_SET_DEVICE_PERMISSIONS (optional)
> 
> The SCI SCMI SMC multi-agent driver implements following
> functionality:
> - The driver is initialized based on the ``xen,config`` node under ``chosen``
>   (only one SCMI interface is supported), which describes the Xen management
>   agent SCMI interface.
> 
> scmi_shm_1: sram@47ff1000 {
>           compatible = "arm,scmi-shmem";
>           reg = <0x0 0x47ff1000 0x0 0x1000>;
> };
> scmi_xen: scmi {
>         compatible = "arm,scmi-smc";
>         arm,smc-id = <0x82000003>; <--- Xen manegement agent smc-id
>         #address-cells = < 1>;
>         #size-cells = < 0>;
>         #access-controller-cells = < 1>;
>         shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
> };
> 
> - The driver obtains Xen specific SCMI Agent's configuration from the Host DT, probes Agents and
>   builds SCMI Agents list. The Agents configuration is taken from "scmi-secondary-agents"
>   property where first item is "arm,smc-id", second - "arm,scmi-shmem" phandle and third is
>   optional "agent_id":
> 
> chosen {
>   ranges;
>   xen,config {

The node name could be xen-config, but it doesn't matter because we
should check for the compatible string instead (no check on node name).

We need to add a compatible string here, I would use "xen,scmi":

    compatible = "xen,scmi";


>     ranges;
>     scmi-secondary-agents = <
>                   0x82000003 &scmi_shm_0 0
>                   0x82000004 &scmi_shm_2 2
>                   0x82000005 &scmi_shm_3 3
>                   0x82000006 &scmi_shm_4 4>;
>     #scmi-secondary-agents-cells = <3>; <--- optional, default 3
> 
>     scmi_shm_0 : sram@47ff0000 {
>         compatible = "arm,scmi-shmem";
>         reg = <0x0 0x47ff0000 0x0 0x1000>;
>     };
> 
>     scmi_shm_2: sram@47ff2000 {
>             compatible = "arm,scmi-shmem";
>             reg = <0x0 0x47ff2000 0x0 0x1000>;
>     };
>     scmi_shm_3: sram@47ff3000 {
>             compatible = "arm,scmi-shmem";
>             reg = <0x0 0x47ff3000 0x0 0x1000>;
>     };
>     scmi_shm_4: sram@47ff4000 {
>             compatible = "arm,scmi-shmem";
>             reg = <0x0 0x47ff4000 0x0 0x1000>;
>     };
> 
>     // Xen SCMI management channel
>     scmi_shm_1: sram@47ff1000 {
>             compatible = "arm,scmi-shmem";
>             reg = <0x0 0x47ff1000 0x0 0x1000>;
>     };
> 
>     scmi_xen: scmi {
>         compatible = "arm,scmi-smc";
>         arm,smc-id = <0x82000002>; <--- Xen manegement agent smc-id
>         #address-cells = < 1>;
>         #size-cells = < 0>;
>         #access-controller-cells = < 1>;
>         shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
>     };
>   };
> };
> 
> /{
>     // Host SCMI OSPM channel - provided to the Dom0 as is if SCMI enabled for it
>     scmi_shm: sram@47ff0000 {
>             compatible = "arm,scmi-shmem";
>             reg = <0x0 0x47ff0000 0x0 0x1000>;
>     };
> 
>     firmware {
>         scmi: scmi {
>             compatible = "arm,scmi-smc";
>             arm,smc-id = <0x82000002>; <--- Host OSPM agent smc-id
>             #address-cells = < 1>;
>             #size-cells = < 0>;
>             shmem = <&scmi_shm>; <--- Host OSPM agent shmem
> 
>             protocol@X{
>             };
>         };
>     };
> };
> 
> This approach allows defining multiple SCMI Agents by adding Xen-specific properties under
> the ``/chosen`` node to the Host Device Tree, leaving the main part unchanged. The Host DT
> SCMI channel will be passed to Dom0.
> 
> The Xen management agent is described as a ``scmi_xen`` node under the ``/chosen`` node, which
> is used by Xen to control other SCMI Agents in the system.
> 
> All secondary agents' configurations are provided in the ``scmi-secondary-agents`` property with
> an optional ``agent_id`` field.
> 
> The ``agent_id`` from the ``scmi-secondary-agents`` property is used to identify the agent in the
> system and can be omitted by setting ``#scmi-secondary-agents-cells = <2>``, so the Secondary
> Agents configuration will look like this:
> 
> chosen {
>   xen,config {
>     scmi-secondary-agents = <
>                   0x82000003 &scmi_shm_0
>                   0x82000004 &scmi_shm_2
>                   0x82000005 &scmi_shm_3
>                   0x82000006 &scmi_shm_4>;
>     #scmi-secondary-agents-cells = <2>;
>   };
> }
> 
> In this case, Xen will use the ``SCMI_BASE_DISCOVER_AGENT`` call to discover the ``agent_id``
> for each secondary agent. Providing the ``agent_id`` in the ``scmi-secondary-agents`` property
> allows skipping the discovery call, which is useful when the secondary agent's shared memory is
> not accessible by Xen or when boot time is important because it allows skipping the agent
> discovery procedure.
> 
>   Note that Xen is the only one entry in the system which need to know
>   about SCMI multi-agent support.
> 
> - It implements the SCI subsystem interface required for configuring and
> enabling SCMI functionality for Dom0/hwdom and Guest domains. To enable
> SCMI functionality for domain it has to be configured with unique supported
> SCMI Agent_id and use corresponding SCMI SMC/HVC shared memory transport
> [smc-id, shmem] defined for this SCMI Agent_id.
> - Once Xen domain is configured it can communicate with EL3 SCMI FW:
>   -- zero-copy, the guest domain puts SCMI message in shmem;
>   -- the guest triggers SMC/HVC exception with smc-id (doorbell);
>   -- the Xen driver catches exception, do checks and synchronously forwards
>   it to EL3 FW.
> - the Xen driver sends BASE_RESET_AGENT_CONFIGURATION message to Xen
>   management agent channel on domain destroy event. This allows to reset
>   resources used by domain and so implement use-case like domain reboot.
> 
> Dom0 Enable SCMI SMC:
>  - pass dom0_scmi_agent_id=<agent_id> in Xen command line. if not provided
>    SCMI will be disabled for Dom0 and all SCMI nodes removed from Dom0 DT.
>    The driver updates Dom0 DT SCMI node "arm,smc-id" value and fix up shmem
>    node according to assigned agent_id.
> 
> Guest domains enable SCMI SMC:
>  - xl.cfg: add configuration option as below
> 
>    arm_sci = "type=scmi_smc_multiagent,agent_id=2"
> 
>  - xl.cfg: enable access to the "arm,scmi-shmem" which should correspond assigned agent_id for
>    the domain, for example:
> 
> iomem = [
>     "47ff2,1@22001",
> ]
> 
>  - DT: add SCMI nodes to the Driver domain partial device tree as in the
>  below example. The "arm,smc-id" should correspond assigned agent_id for the domain:
> 
> passthrough {
>    scmi_shm_0: sram@22001000 {
>        compatible = "arm,scmi-shmem";
>        reg = <0x0 0x22001000 0x0 0x1000>;
>    };
> 
>    firmware {
>         compatible = "simple-bus";
>             scmi: scmi {
>                 compatible = "arm,scmi-smc";
>                 arm,smc-id = <0x82000004>;
>                 shmem = <&scmi_shm_0>;
>                 ...
>             }
>     }
> }
> 
> SCMI "4.2.1.1 Device specific access control"
> 
> The XEN SCI SCMI SMC multi-agent driver performs "access-controller" provider function
> in case EL3 SCMI FW implements SCMI "4.2.1.1 Device specific access control" and provides the
> BASE_SET_DEVICE_PERMISSIONS command to configure the devices that an agents have access to.
> The DT SCMI node should "#access-controller-cells=<1>" property and DT devices should be bound
> to the Xen SCMI.
> 
> &i2c1 {
> 	access-controllers = <&scmi 0>;
> };
> 
> The Dom0 and dom0less domains DT devices will be processed automatically through
> sci_assign_dt_device() call, but to assign SCMI devices from toolstack the xl.cfg:"dtdev" property
> shell be used:

shall

> 
> dtdev = [
>     "/soc/i2c@e6508000",
> ]
> 
> xl.cfg:dtdev will contain all nodes which are under SCMI management (not only those which are behind IOMMU).
> 
> [1] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
> [2] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml
> 
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
> ---
> 
> Changes in v5:
> - fix device-tree example format in booting.txt, added ";" after "}".
> - update define in scmi-proto.h
> - update define in scmi-shmem.h file
> - scmi_assign_device - do not ignore -EOPNOTSUPP return
> code of the do_smc_xfer
> - remove overwriting agent_channel->agent_id after
> SCMI_BASE_DISCOVER_AGENT call
> - add multi-agent files to the MAINTAINERS
> - add SCMI multi-agent description to the SUPPORT.md
> - handle ARM_SMCCC_INVALID_PARAMETER return code and return -EINVAL
> for smc call
> - updated collect_agents function. Set agent_id parameter as optional
> in scmi-secondary-agents device-tree property
> - introduce "#scmi-secondary-agents-cells" parameter to set if
> agent_id was provided
> - reanme xen,scmi-secondary-agents property to scmi-secondary-agents
> - move memcpu_toio/fromio for the generic place
> - update Xen to get management channel from /chosen/xen,config node
> - get hypervisor channnel from node instead of using hardcoded
> - update handling scmi and shmem nodes for the domain
> - Set multi-agent driver to support only Arm64
> 
> Changes in v4:
> - toolstack comments from Anthony PERARD
> - added dom0less support
> - added doc for "xen,scmi-secondary-agents"
> 
>  MAINTAINERS                                 |   4 +
>  SUPPORT.md                                  |  11 +
>  docs/man/xl.cfg.5.pod.in                    |  13 +
>  docs/misc/arm/device-tree/booting.txt       |  88 +++
>  docs/misc/xen-command-line.pandoc           |   9 +
>  tools/libs/light/libxl_arm.c                |   4 +
>  tools/libs/light/libxl_types.idl            |   4 +-
>  tools/xl/xl_parse.c                         |  12 +
>  xen/arch/arm/dom0less-build.c               |  11 +
>  xen/arch/arm/domain_build.c                 |   3 +-
>  xen/arch/arm/firmware/Kconfig               |  12 +
>  xen/arch/arm/firmware/Makefile              |   1 +
>  xen/arch/arm/firmware/scmi-proto.h          | 164 ++++
>  xen/arch/arm/firmware/scmi-shmem.c          | 112 +++
>  xen/arch/arm/firmware/scmi-shmem.h          |  45 ++
>  xen/arch/arm/firmware/scmi-smc-multiagent.c | 803 ++++++++++++++++++++
>  xen/include/public/arch-arm.h               |   3 +
>  17 files changed, 1297 insertions(+), 2 deletions(-)
>  create mode 100644 xen/arch/arm/firmware/scmi-proto.h
>  create mode 100644 xen/arch/arm/firmware/scmi-shmem.c
>  create mode 100644 xen/arch/arm/firmware/scmi-shmem.h
>  create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 31dbba54bb..1b6b58cbb7 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -514,6 +514,10 @@ R:	Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>  S:	Supported
>  F:	xen/arch/arm/firmware/sci.c
>  F:	xen/arch/arm/include/asm/firmware/sci.h
> +F:	xen/arch/arm/firmware/scmi-smc-multiagent.c
> +F:	xen/arch/arm/firmware/scmi-shmem.c
> +F:	xen/arch/arm/firmware/scmi-shmem.h
> +F:	xen/arch/arm/firmware/scmi-proto.h
>  
>  SEABIOS UPSTREAM
>  M:	Wei Liu <wl@xen.org>
> diff --git a/SUPPORT.md b/SUPPORT.md
> index 6a82a92189..9d7857d953 100644
> --- a/SUPPORT.md
> +++ b/SUPPORT.md
> @@ -956,6 +956,17 @@ by hwdom. Some platforms use SCMI for access to system-level resources.
>  
>      Status: Supported
>  
> +### Arm: SCMI SMC multi-agent support
> +
> +Enable support for the multi-agent configuration of the EL3 Firmware, which
> +allows Xen to provide an SCMI interface to the Domains.
> +Xen manages access permissions to the HW resources and provides an SCMI interface
> +to the Domains. Each Domain is represented as a separate Agent, which can
> +communicate with EL3 Firmware using a dedicated shared memory region, and
> +notifications are passed through by Xen.
> +
> +    Status, ARM64: Tech Preview
> +
>  ### ARM: Guest PSCI support
>  
>  Emulated PSCI interface exposed to guests. We support all mandatory
> diff --git a/docs/man/xl.cfg.5.pod.in b/docs/man/xl.cfg.5.pod.in
> index 8f1a203e21..f6cf2d4567 100644
> --- a/docs/man/xl.cfg.5.pod.in
> +++ b/docs/man/xl.cfg.5.pod.in
> @@ -3103,8 +3103,21 @@ single SCMI OSPM agent support.
>  Should be used together with B<scmi_smc_passthrough> Xen command line
>  option.
>  
> +=item B<scmi_smc_multiagent>
> +
> +Enables ARM SCMI SMC multi-agent support for the guest by enabling SCMI over
> +SMC calls forwarding from domain to the EL3 firmware (like Trusted Firmware-A)
> +with a multi SCMI OSPM agent support. The SCMI B<agent_id> should be
> +specified for the guest.
> +
>  =back
>  
> +=item B<agent_id=NUMBER>
> +
> +Specifies a non-zero ARM SCI agent id for the guest. This option is mandatory
> +if the SCMI SMC support is enabled for the guest. The agent ids of domains
> +existing on a single host must be unique and in the range [1..255].

Why is the option mandatory if the commit description explains that the
agent_id can be probed by Xen? In the commit message, the mandatory
field is smc-id instead?

I guess it is because we expect Xen to have already the agent_id->smc-id
mapping and we expect the agent_id to be easier to remember and to write
in the config file?


>  =back
>  
>  =back
> diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
> index 8ea11c1551..10a99cfd15 100644
> --- a/docs/misc/arm/device-tree/booting.txt
> +++ b/docs/misc/arm/device-tree/booting.txt
> @@ -322,6 +322,20 @@ with the following properties:
>      Should be used together with scmi_smc_passthrough Xen command line
>      option.
>  
> +    - "scmi_smc_multiagent"
> +
> +    Enables ARM SCMI SMC multi-agent support for the guest by enabling SCMI over
> +    SMC calls forwarding from domain to the EL3 firmware (like ARM
> +    Trusted Firmware-A) with a multi SCMI OSPM agent support.
> +    The SCMI agent_id should be specified for the guest with "xen,sci_agent_id"
> +    property.
> +
> +- "xen,sci_agent_id"
> +
> +    Specifies a non-zero ARM SCI agent id for the guest. This option is
> +    mandatory if the SCMI SMC "scmi_smc_multiagent" support is enabled for
> +    the guest. The agent ids of guest must be unique and in the range [1..255].

same question


>  Under the "xen,domain" compatible node, one or more sub-nodes are present
>  for the DomU kernel and ramdisk.
>  
> @@ -824,3 +838,77 @@ The automatically allocated static shared memory will get mapped at
>  0x80000000 in DomU1 guest physical address space, and at 0x90000000 in DomU2
>  guest physical address space. DomU1 is explicitly defined as the owner domain,
>  and DomU2 is the borrower domain.
> +
> +SCMI SMC multi-agent support
> +============================
> +
> +For enabling the ARM SCMI SMC multi-agent support (enabled by CONFIG_SCMI_SMC_MA)
> +the Xen specific SCMI Agent's configuration shell be provided in the Host DT

shall


> +according to the SCMI compliant EL3 Firmware specification with
> +ARM SMC/HVC transport using property "scmi-secondary-agents" placed in "xen,config"
> +node under "chosen" node:
> +
> +- scmi-secondary-agents
> +
> +    Defines a set of SCMI agents configuration supported by SCMI EL3 FW and
> +    available for Xen. Each Agent defined as triple consisting of:
> +    SMC/HVC function_id assigned for the agent transport ("arm,smc-id"),
> +    phandle to SCMI SHM assigned for the agent transport ("arm,scmi-shmem"),
> +    SCMI agent_id (optional) if not set - Xen will determine Agent ID for
> +    each provided channel using BASE_DISCOVER_AGENT message.
> +
> +As an example:
> +
> +/{
> +chosen {
> +    xen,config {

same comment about node name and compatible string


> +        scmi_shm_1: sram@47ff1000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff1000 0x0 0x1000>;
> +        };
> +        scmi_shm_2: sram@47ff2000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff2000 0x0 0x1000>;
> +        };
> +        scmi_shm_3: sram@47ff3000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff3000 0x0 0x1000>;
> +        };
> +        scmi_shm_3: sram@47ff4000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff4000 0x0 0x1000>;
> +        };
> +        scmi-secondary-agents = <
> +            0x82000003 &scmi_shm_1 1
> +            0x82000004 &scmi_shm_2 2
> +            0x82000005 &scmi_shm_3 3
> +            0x82000006 &scmi_shm_4 4>;
> +            #scmi-secondary-agents-cells = <3>;
> +        };
> +    };
> +};
> +
> +- #scmi-secondary-agents-cells
> +
> +    Defines whether Agent_id is set in the "scmi-secondary-agents" property.
> +    Possible values are: 2, 3.
> +    When set to 3 (the default), expect agent_id to be present in the secondary
> +    agents list.
> +    When set to 2, agent_id will be discovered for each channel using
> +    BASE_DISCOVER_AGENT message.
> +
> +
> +Example:
> +
> +/{
> +chosen {
> +    xen,config {
> +        scmi-secondary-agents = <
> +            0x82000003 &scmi_shm_1
> +            0x82000004 &scmi_shm_2
> +            0x82000005 &scmi_shm_3
> +            0x82000006 &scmi_shm_4>;
> +            #scmi-secondary-agents-cells = <2>;


In the example we should also add Xen own nodes like you did in the
commit message.


> +        };
> +    };
> +};
> diff --git a/docs/misc/xen-command-line.pandoc b/docs/misc/xen-command-line.pandoc
> index 7a1f723e63..5a1c1e072c 100644
> --- a/docs/misc/xen-command-line.pandoc
> +++ b/docs/misc/xen-command-line.pandoc
> @@ -1105,6 +1105,15 @@ which serves as Driver domain. The SCMI will be disabled for Dom0/hwdom and
>  SCMI nodes removed from Dom0/hwdom device tree.
>  (for example, thin Dom0 with Driver domain use-case).
>  
> +### dom0_scmi_agent_id (ARM)
> +> `= <integer>`
> +
> +The option is available when `CONFIG_SCMI_SMC_MA` is compiled in, and allows to
> +enable SCMI functionality for Dom0 by specifying a non-zero ARM SCMI agent id.
> +The SCMI will be disabled for Dom0 if this option is not specified
> +(for example, thin Dom0 or dom0less use-cases).
> +The agent ids of domains existing on a single host must be unique.

Same question about agent id vs. smc-id


>  ### dtuart (ARM)
>  > `= path [:options]`
>  
> diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
> index e4407d6e3f..be0e6263ae 100644
> --- a/tools/libs/light/libxl_arm.c
> +++ b/tools/libs/light/libxl_arm.c
> @@ -240,6 +240,10 @@ int libxl__arch_domain_prepare_config(libxl__gc *gc,
>      case LIBXL_ARM_SCI_TYPE_SCMI_SMC:
>          config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
>          break;
> +    case LIBXL_ARM_SCI_TYPE_SCMI_SMC_MULTIAGENT:
> +        config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
> +        config->arch.arm_sci_agent_id = d_config->b_info.arch_arm.arm_sci.agent_id;
> +        break;
>      default:
>          LOG(ERROR, "Unknown ARM_SCI type %d",
>              d_config->b_info.arch_arm.arm_sci.type);
> diff --git a/tools/libs/light/libxl_types.idl b/tools/libs/light/libxl_types.idl
> index c8bc0f8521..da7f87cd0c 100644
> --- a/tools/libs/light/libxl_types.idl
> +++ b/tools/libs/light/libxl_types.idl
> @@ -553,11 +553,13 @@ libxl_sve_type = Enumeration("sve_type", [
>  
>  libxl_arm_sci_type = Enumeration("arm_sci_type", [
>      (0, "none"),
> -    (1, "scmi_smc")
> +    (1, "scmi_smc"),
> +    (2, "scmi_smc_multiagent")
>      ], init_val = "LIBXL_ARM_SCI_TYPE_NONE")
>  
>  libxl_arm_sci = Struct("arm_sci", [
>      ("type", libxl_arm_sci_type),
> +    ("agent_id", uint8)
>      ])
>  
>  libxl_rdm_reserve = Struct("rdm_reserve", [
> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index 68d2ebeb9f..4c05b20c06 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -1306,6 +1306,18 @@ static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci,
>              }
>          }
>  
> +        if (MATCH_OPTION("agent_id", ptr, oparg)) {
> +            unsigned long val = parse_ulong(oparg);
> +
> +            if (!val || val > 255) {
> +                fprintf(stderr, "An invalid ARM_SCI agent_id specified (%lu). Valid range [1..255]\n",
> +                        val);
> +                ret = ERROR_INVAL;
> +                goto parse_error;
> +            }
> +            arm_sci->agent_id = val;
> +        }
> +
>          ptr = strtok(NULL, ",");
>      }
>  
> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> index d28143f98b..6ca17b0ce6 100644
> --- a/xen/arch/arm/dom0less-build.c
> +++ b/xen/arch/arm/dom0less-build.c
> @@ -299,6 +299,17 @@ int __init domu_dt_sci_parse(struct dt_device_node *node,
>          d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
>      else if ( !strcmp(sci_type, "scmi_smc") )
>          d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
> +    else if ( !strcmp(sci_type, "scmi_smc_multiagent") )
> +    {
> +        uint32_t agent_id = 0;
> +
> +        if ( !dt_property_read_u32(node, "xen,sci_agent_id", &agent_id) ||
> +             !agent_id )
> +            return -EINVAL;
> +
> +        d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
> +        d_cfg->arch.arm_sci_agent_id = agent_id;
> +    }
>      else
>      {
>          printk(XENLOG_ERR "xen,sci_type in not valid (%s) for domain %s\n",
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 92039cf213..ea13e374a0 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -508,7 +508,8 @@ static int __init write_properties(struct domain *d, struct kernel_info *kinfo,
>                   dt_property_name_is_equal(prop, "linux,uefi-mmap-start") ||
>                   dt_property_name_is_equal(prop, "linux,uefi-mmap-size") ||
>                   dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-size") ||
> -                 dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-ver"))
> +                 dt_property_name_is_equal(prop, "linux,uefi-mmap-desc-ver") ||
> +                 dt_property_name_is_equal(prop, "xen,config") )
>                  continue;

please match by compatible string rather than by node name


>              if ( dt_property_name_is_equal(prop, "xen,dom0-bootargs") )
> diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
> index 5c5f0880c4..972cd9b173 100644
> --- a/xen/arch/arm/firmware/Kconfig
> +++ b/xen/arch/arm/firmware/Kconfig
> @@ -29,6 +29,18 @@ config SCMI_SMC
>  	  driver domain.
>  	  Use with EL3 firmware which supports only single SCMI OSPM agent.
>  
> +config SCMI_SMC_MA
> +	bool "Enable ARM SCMI SMC multi-agent driver"
> +	depends on ARM_64
> +	select ARM_SCI
> +	help
> +	  Enables SCMI SMC/HVC multi-agent in XEN to pass SCMI requests from Domains
> +	  to EL3 firmware (TF-A) which supports multi-agent feature.
> +	  This feature allows to enable SCMI per Domain using unique SCMI agent_id,
> +	  so Domain is identified by EL3 firmware as an SCMI Agent and can access
> +	  allowed platform resources through dedicated SMC/HVC Shared memory based
> +	  transport.
> +
>  endchoice
>  
>  endmenu
> diff --git a/xen/arch/arm/firmware/Makefile b/xen/arch/arm/firmware/Makefile
> index 71bdefc24a..37927e690e 100644
> --- a/xen/arch/arm/firmware/Makefile
> +++ b/xen/arch/arm/firmware/Makefile
> @@ -1,2 +1,3 @@
>  obj-$(CONFIG_ARM_SCI) += sci.o
>  obj-$(CONFIG_SCMI_SMC) += scmi-smc.o
> +obj-$(CONFIG_SCMI_SMC_MA) += scmi-shmem.o scmi-smc-multiagent.o
> diff --git a/xen/arch/arm/firmware/scmi-proto.h b/xen/arch/arm/firmware/scmi-proto.h
> new file mode 100644
> index 0000000000..e290d6630d
> --- /dev/null
> +++ b/xen/arch/arm/firmware/scmi-proto.h
> @@ -0,0 +1,164 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Arm System Control and Management Interface definitions
> + * Version 3.0 (DEN0056C)
> + *
> + * Copyright (c) 2024 EPAM Systems
> + */
> +
> +#ifndef ARM_FIRMWARE_SCMI_PROTO_H_
> +#define ARM_FIRMWARE_SCMI_PROTO_H_
> +
> +#include <xen/stdint.h>
> +
> +#define SCMI_SHORT_NAME_MAX_SIZE 16
> +
> +/* SCMI status codes. See section 4.1.4 */
> +#define SCMI_SUCCESS              0
> +#define SCMI_NOT_SUPPORTED      (-1)
> +#define SCMI_INVALID_PARAMETERS (-2)
> +#define SCMI_DENIED             (-3)
> +#define SCMI_NOT_FOUND          (-4)
> +#define SCMI_OUT_OF_RANGE       (-5)
> +#define SCMI_BUSY               (-6)
> +#define SCMI_COMMS_ERROR        (-7)
> +#define SCMI_GENERIC_ERROR      (-8)
> +#define SCMI_HARDWARE_ERROR     (-9)
> +#define SCMI_PROTOCOL_ERROR     (-10)
> +
> +/* Protocol IDs */
> +#define SCMI_BASE_PROTOCOL 0x10
> +
> +/* Base protocol message IDs */
> +#define SCMI_BASE_PROTOCOL_VERSION            0x0
> +#define SCMI_BASE_PROTOCOL_ATTIBUTES          0x1
> +#define SCMI_BASE_PROTOCOL_MESSAGE_ATTRIBUTES 0x2
> +#define SCMI_BASE_DISCOVER_AGENT              0x7
> +#define SCMI_BASE_SET_DEVICE_PERMISSIONS      0x9
> +#define SCMI_BASE_RESET_AGENT_CONFIGURATION   0xB
> +
> +typedef struct scmi_msg_header {
> +    uint8_t id;
> +    uint8_t type;
> +    uint8_t protocol;
> +    uint32_t status;
> +} scmi_msg_header_t;
> +
> +/* Table 2 Message header format */
> +#define SCMI_HDR_ID    GENMASK(7, 0)
> +#define SCMI_HDR_TYPE  GENMASK(9, 8)
> +#define SCMI_HDR_PROTO GENMASK(17, 10)
> +
> +#define SCMI_FIELD_GET(_mask, _reg)                                            \
> +    ((typeof(_mask))(((_reg) & (_mask)) >> (ffs64(_mask) - 1)))

ffs64 is declared in xen/bitops.h


> +#define SCMI_FIELD_PREP(_mask, _val)                                           \
> +    (((typeof(_mask))(_val) << (ffs64(_mask) - 1)) & (_mask))
> +
> +static inline uint32_t pack_scmi_header(scmi_msg_header_t *hdr)
> +{
> +    return SCMI_FIELD_PREP(SCMI_HDR_ID, hdr->id) |
> +           SCMI_FIELD_PREP(SCMI_HDR_TYPE, hdr->type) |
> +           SCMI_FIELD_PREP(SCMI_HDR_PROTO, hdr->protocol);
> +}
> +
> +static inline void unpack_scmi_header(uint32_t msg_hdr, scmi_msg_header_t *hdr)
> +{
> +    hdr->id = SCMI_FIELD_GET(SCMI_HDR_ID, msg_hdr);
> +    hdr->type = SCMI_FIELD_GET(SCMI_HDR_TYPE, msg_hdr);
> +    hdr->protocol = SCMI_FIELD_GET(SCMI_HDR_PROTO, msg_hdr);
> +}
> +
> +static inline int scmi_to_xen_errno(int scmi_status)
> +{
> +    if ( scmi_status == SCMI_SUCCESS )
> +        return 0;
> +
> +    switch ( scmi_status )
> +    {
> +    case SCMI_NOT_SUPPORTED:
> +        return -EOPNOTSUPP;
> +    case SCMI_INVALID_PARAMETERS:
> +        return -EINVAL;
> +    case SCMI_DENIED:
> +        return -EACCES;
> +    case SCMI_NOT_FOUND:
> +        return -ENOENT;
> +    case SCMI_OUT_OF_RANGE:
> +        return -ERANGE;
> +    case SCMI_BUSY:
> +        return -EBUSY;
> +    case SCMI_COMMS_ERROR:
> +        return -ENOTCONN;
> +    case SCMI_GENERIC_ERROR:
> +        return -EIO;
> +    case SCMI_HARDWARE_ERROR:
> +        return -ENXIO;
> +    case SCMI_PROTOCOL_ERROR:
> +        return -EBADMSG;
> +    default:
> +        return -EINVAL;
> +    }
> +}
> +
> +/* PROTOCOL_VERSION */
> +#define SCMI_VERSION_MINOR GENMASK(15, 0)
> +#define SCMI_VERSION_MAJOR GENMASK(31, 16)
> +
> +struct scmi_msg_prot_version_p2a {
> +    uint32_t version;
> +} __packed;
> +
> +/* BASE PROTOCOL_ATTRIBUTES */
> +#define SCMI_BASE_ATTR_NUM_PROTO GENMASK(7, 0)
> +#define SCMI_BASE_ATTR_NUM_AGENT GENMASK(15, 8)
> +
> +struct scmi_msg_base_attributes_p2a {
> +    uint32_t attributes;
> +} __packed;
> +
> +/*
> + * BASE_DISCOVER_AGENT
> + */
> +#define SCMI_BASE_AGENT_ID_OWN 0xFFFFFFFF
> +
> +struct scmi_msg_base_discover_agent_a2p {
> +    uint32_t agent_id;
> +} __packed;
> +
> +struct scmi_msg_base_discover_agent_p2a {
> +    uint32_t agent_id;
> +    char name[SCMI_SHORT_NAME_MAX_SIZE];
> +} __packed;
> +
> +/*
> + * BASE_SET_DEVICE_PERMISSIONS
> + */
> +#define SCMI_BASE_DEVICE_ACCESS_ALLOW           BIT(0, UL)
> +
> +struct scmi_msg_base_set_device_permissions_a2p {
> +    uint32_t agent_id;
> +    uint32_t device_id;
> +    uint32_t flags;
> +} __packed;
> +
> +/*
> + * BASE_RESET_AGENT_CONFIGURATION
> + */
> +#define SCMI_BASE_AGENT_PERMISSIONS_RESET       BIT(0, UL)
> +
> +struct scmi_msg_base_reset_agent_cfg_a2p {
> +    uint32_t agent_id;
> +    uint32_t flags;
> +} __packed;
> +
> +#endif /* ARM_FIRMWARE_SCMI_PROTO_H_ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/firmware/scmi-shmem.c b/xen/arch/arm/firmware/scmi-shmem.c
> new file mode 100644
> index 0000000000..8fc8ca356b
> --- /dev/null
> +++ b/xen/arch/arm/firmware/scmi-shmem.c
> @@ -0,0 +1,112 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * SCI SCMI multi-agent driver, using SMC/HVC shmem as transport.
> + *
> + * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> + * Copyright (c) 2025 EPAM Systems
> + */
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +#include <asm/io.h>
> +#include <xen/err.h>
> +#include <xen/lib/arm/io.h>
> +
> +#include "scmi-proto.h"
> +#include "scmi-shmem.h"
> +
> +static inline int
> +shmem_channel_is_free(const volatile struct scmi_shared_mem __iomem *shmem)
> +{
> +    return (readl(&shmem->channel_status) &
> +            SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE) ? 0 : -EBUSY;
> +}
> +
> +int shmem_put_message(volatile struct scmi_shared_mem __iomem *shmem,
> +                      scmi_msg_header_t *hdr, void *data, int len)
> +{
> +    int ret;
> +
> +    if ( (len + sizeof(shmem->msg_header)) > SCMI_SHMEM_MAPPED_SIZE )

shouldn't this take into account offsetof(struct scmi_shared_mem,
msg_header) ?




> +    {
> +        printk(XENLOG_ERR "scmi: Wrong size of smc message. Data is invalid\n");
> +        return -EINVAL;
> +    }
> +
> +    ret = shmem_channel_is_free(shmem);
> +    if ( ret )
> +        return ret;
> +
> +    writel_relaxed(0x0, &shmem->channel_status);
> +    /* Writing 0x0 right now, but "shmem"_FLAG_INTR_ENABLED can be set */
> +    writel_relaxed(0x0, &shmem->flags);
> +    writel_relaxed(sizeof(shmem->msg_header) + len, &shmem->length);
> +    writel(pack_scmi_header(hdr), &shmem->msg_header);
> +
> +    if ( len > 0 && data )
> +        __memcpy_toio(shmem->msg_payload, data, len);
> +
> +    return 0;
> +}
> +
> +int shmem_get_response(const volatile struct scmi_shared_mem __iomem *shmem,
> +                       scmi_msg_header_t *hdr, void *data, int len)
> +{
> +    int recv_len;
> +    int ret;
> +    int pad = sizeof(hdr->status);
> +
> +    if ( len >= SCMI_SHMEM_MAPPED_SIZE - sizeof(shmem) )

should this be sizeof(*shmem) ?


> +    {
> +        printk(XENLOG_ERR
> +               "scmi: Wrong size of input smc message. Data may be invalid\n");
> +        return -EINVAL;
> +    }
> +
> +    ret = shmem_channel_is_free(shmem);
> +    if ( ret )
> +        return ret;
> +
> +    recv_len = readl(&shmem->length) - sizeof(shmem->msg_header);
> +
> +    if ( recv_len < 0 )
> +    {
> +        printk(XENLOG_ERR
> +               "scmi: Wrong size of smc message. Data may be invalid\n");
> +        return -EINVAL;
> +    }
> +
> +    unpack_scmi_header(readl(&shmem->msg_header), hdr);
> +
> +    hdr->status = readl(&shmem->msg_payload);
> +    recv_len = recv_len > pad ? recv_len - pad : 0;
> +
> +    ret = scmi_to_xen_errno(hdr->status);
> +    if ( ret )
> +    {
> +        printk(XENLOG_DEBUG "scmi: Error received: %d\n", ret);
> +        return ret;
> +    }
> +
> +    if ( recv_len > len )
> +    {
> +        printk(XENLOG_ERR
> +               "scmi: Not enough buffer for message %d, expecting %d\n",
> +               recv_len, len);
> +        return -EINVAL;
> +    }
> +
> +    if ( recv_len > 0 )
> +        __memcpy_fromio(data, shmem->msg_payload + pad, recv_len);
> +
> +    return 0;
> +}
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/firmware/scmi-shmem.h b/xen/arch/arm/firmware/scmi-shmem.h
> new file mode 100644
> index 0000000000..7313cb6b26
> --- /dev/null
> +++ b/xen/arch/arm/firmware/scmi-shmem.h
> @@ -0,0 +1,45 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Arm System Control and Management Interface definitions
> + * Version 3.0 (DEN0056C)
> + * Shared Memory based Transport
> + *
> + * Copyright (c) 2024 EPAM Systems
> + */
> +
> +#ifndef ARM_FIRMWARE_SCMI_SHMEM_H_
> +#define ARM_FIRMWARE_SCMI_SHMEM_H_
> +
> +#include <xen/stdint.h>
> +
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE  BIT(0, UL)
> +#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1, UL)
> +
> +struct scmi_shared_mem {
> +    uint32_t reserved;
> +    uint32_t channel_status;
> +    uint32_t reserved1[2];
> +    uint32_t flags;
> +    uint32_t length;
> +    uint32_t msg_header;
> +    uint8_t msg_payload[];
> +};
> +
> +#define SCMI_SHMEM_MAPPED_SIZE PAGE_SIZE
> +
> +int shmem_put_message(volatile struct scmi_shared_mem __iomem *shmem,
> +                      scmi_msg_header_t *hdr, void *data, int len);
> +
> +int shmem_get_response(const volatile struct scmi_shared_mem __iomem *shmem,
> +                       scmi_msg_header_t *hdr, void *data, int len);
> +#endif /* ARM_FIRMWARE_SCMI_SHMEM_H_ */
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/arch/arm/firmware/scmi-smc-multiagent.c b/xen/arch/arm/firmware/scmi-smc-multiagent.c
> new file mode 100644
> index 0000000000..9f839147d4
> --- /dev/null
> +++ b/xen/arch/arm/firmware/scmi-smc-multiagent.c
> @@ -0,0 +1,803 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * SCI SCMI multi-agent driver, using SMC/HVC shmem as transport.
> + *
> + * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> + * Copyright (c) 2025 EPAM Systems
> + */
> +
> +#include <xen/acpi.h>
> +
> +#include <xen/device_tree.h>
> +#include <xen/init.h>
> +#include <xen/iocap.h>
> +#include <xen/err.h>
> +#include <xen/libfdt/libfdt.h>
> +#include <xen/param.h>
> +#include <xen/sched.h>
> +#include <xen/vmap.h>
> +
> +#include <asm/firmware/sci.h>
> +#include <asm/smccc.h>
> +
> +#include "scmi-proto.h"
> +#include "scmi-shmem.h"
> +
> +#define SCMI_AGENT_ID_INVALID 0xFF
> +
> +static uint8_t __initdata opt_dom0_scmi_agent_id = SCMI_AGENT_ID_INVALID;
> +integer_param("dom0_scmi_agent_id", opt_dom0_scmi_agent_id);
> +
> +#define SCMI_SECONDARY_AGENTS "scmi-secondary-agents"
> +
> +struct scmi_channel {
> +    uint32_t agent_id;
> +    uint32_t func_id;
> +    domid_t domain_id;
> +    uint64_t paddr;
> +    uint64_t len;

doesn't seem to be used


> +    struct scmi_shared_mem __iomem *shmem;
> +    spinlock_t lock;
> +    struct list_head list;
> +};
> +
> +struct scmi_data {
> +    struct list_head channel_list;
> +    spinlock_t channel_list_lock;
> +    uint32_t func_id;
> +    bool initialized;
> +    uint32_t shmem_phandle;
> +    uint32_t hyp_channel_agent_id;
> +    struct dt_device_node *dt_dev;
> +};
> +
> +static struct scmi_data scmi_data;
> +
> +static int send_smc_message(struct scmi_channel *chan_info,
> +                            scmi_msg_header_t *hdr, void *data, int len)
> +{
> +    struct arm_smccc_res resp;
> +    int ret;
> +
> +    ret = shmem_put_message(chan_info->shmem, hdr, data, len);
> +    if ( ret )
> +        return ret;
> +
> +    arm_smccc_1_1_smc(chan_info->func_id, 0, 0, 0, 0, 0, 0, 0, &resp);
> +
> +    if ( resp.a0 == ARM_SMCCC_INVALID_PARAMETER )
> +        return -EINVAL;
> +
> +    if ( resp.a0 )
> +        return -EOPNOTSUPP;
> +
> +    return 0;
> +}
> +
> +static int do_smc_xfer(struct scmi_channel *chan_info, scmi_msg_header_t *hdr,
> +                       void *tx_data, int tx_size, void *rx_data, int rx_size)
> +{
> +    int ret = 0;
> +
> +    ASSERT(chan_info && chan_info->shmem);
> +
> +    if ( !hdr )
> +        return -EINVAL;
> +
> +    spin_lock(&chan_info->lock);
> +
> +    printk(XENLOG_DEBUG
> +           "scmi: agent_id = %d msg_id = %x type = %d, proto = %x\n",
> +           chan_info->agent_id, hdr->id, hdr->type, hdr->protocol);
> +
> +    ret = send_smc_message(chan_info, hdr, tx_data, tx_size);
> +    if ( ret )
> +        goto clean;
> +
> +    ret = shmem_get_response(chan_info->shmem, hdr, rx_data, rx_size);
> +
> +clean:
> +    printk(XENLOG_DEBUG
> +           "scmi: get smc response agent_id = %d msg_id = %x proto = %x res=%d\n",
> +           chan_info->agent_id, hdr->id, hdr->protocol, ret);
> +
> +    spin_unlock(&chan_info->lock);
> +
> +    return ret;
> +}
> +
> +static struct scmi_channel *get_channel_by_id(uint32_t agent_id)
> +{
> +    struct scmi_channel *curr;
> +    bool found = false;
> +
> +    spin_lock(&scmi_data.channel_list_lock);
> +    list_for_each_entry(curr, &scmi_data.channel_list, list)
> +    {
> +        if ( curr->agent_id == agent_id )
> +        {
> +            found = true;
> +            break;
> +        }
> +    }
> +
> +    spin_unlock(&scmi_data.channel_list_lock);
> +    if ( found )
> +        return curr;
> +
> +    return NULL;
> +}
> +
> +static struct scmi_channel *acquire_scmi_channel(struct domain *d,
> +                                                 uint32_t agent_id)
> +{
> +    struct scmi_channel *curr;
> +    struct scmi_channel *ret = ERR_PTR(-ENOENT);
> +
> +    spin_lock(&scmi_data.channel_list_lock);
> +    list_for_each_entry(curr, &scmi_data.channel_list, list)
> +    {
> +        if ( curr->agent_id == agent_id )
> +        {
> +            if ( curr->domain_id != DOMID_INVALID )
> +            {
> +                ret = ERR_PTR(-EEXIST);
> +                break;
> +            }
> +
> +            curr->domain_id = d->domain_id;
> +            ret = curr;
> +            break;
> +        }
> +    }
> +
> +    spin_unlock(&scmi_data.channel_list_lock);
> +
> +    return ret;
> +}
> +
> +static void relinquish_scmi_channel(struct scmi_channel *channel)
> +{
> +    ASSERT(channel != NULL);
> +
> +    spin_lock(&scmi_data.channel_list_lock);
> +    channel->domain_id = DOMID_INVALID;
> +    spin_unlock(&scmi_data.channel_list_lock);
> +}
> +
> +static int map_channel_memory(struct scmi_channel *channel)
> +{
> +    ASSERT(channel && channel->paddr);
> +    channel->shmem = ioremap_nocache(channel->paddr, SCMI_SHMEM_MAPPED_SIZE);
> +    if ( !channel->shmem )
> +        return -ENOMEM;
> +
> +    channel->shmem->channel_status = SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE;
> +    printk(XENLOG_DEBUG "scmi: Got shmem %lx after vmap %p\n", channel->paddr,
> +           channel->shmem);
> +
> +    return 0;
> +}
> +
> +static void unmap_channel_memory(struct scmi_channel *channel)
> +{
> +    ASSERT(channel && channel->shmem);
> +    iounmap(channel->shmem);
> +    channel->shmem = NULL;
> +}
> +
> +static struct scmi_channel *smc_create_channel(uint32_t agent_id,
> +                                               uint32_t func_id, uint64_t addr)
> +{
> +    struct scmi_channel *channel;
> +
> +    channel = get_channel_by_id(agent_id);
> +    if ( channel )
> +        return ERR_PTR(EEXIST);
> +
> +    channel = xmalloc(struct scmi_channel);
> +    if ( !channel )
> +        return ERR_PTR(ENOMEM);
> +
> +    spin_lock_init(&channel->lock);
> +    channel->agent_id = agent_id;
> +    channel->func_id = func_id;
> +    channel->domain_id = DOMID_INVALID;
> +    channel->shmem = NULL;
> +    channel->paddr = addr;
> +    list_add_tail(&channel->list, &scmi_data.channel_list);
> +    return channel;
> +}
> +
> +static void free_channel_list(void)
> +{
> +    struct scmi_channel *curr, *_curr;
> +
> +    list_for_each_entry_safe(curr, _curr, &scmi_data.channel_list, list)
> +    {
> +        list_del(&curr->list);
> +        xfree(curr);
> +    }
> +}
> +
> +static int __init
> +scmi_dt_read_hyp_channel_addr(struct dt_device_node *scmi_node, u64 *addr,
> +                              u64 *size)
> +{
> +    struct dt_device_node *shmem_node;
> +    const __be32 *prop;
> +
> +    prop = dt_get_property(scmi_node, "shmem", NULL);
> +    if ( !prop )
> +        return -EINVAL;
> +
> +    shmem_node = dt_find_node_by_phandle(be32_to_cpu(*prop));
> +    if ( IS_ERR_OR_NULL(shmem_node) )
> +    {
> +        printk(XENLOG_ERR
> +               "scmi: Device tree error, can't parse reserved memory %ld\n",
> +               PTR_ERR(shmem_node));
> +        return PTR_ERR(shmem_node);
> +    }
> +
> +    return dt_device_get_address(shmem_node, 0, addr, size);
> +}
> +
> +/*
> + * Handle Dom0 SCMI specific DT nodes
> + *
> + * Make a decision on copying SCMI specific nodes into Dom0 device tree.
> + * For SCMI multi-agent case:
> + * - shmem nodes will not be copied and generated instead if SCMI
> + *   is enabled for Dom0
> + * - scmi node will be copied if SCMI is enabled for Dom0
> + */
> +static bool scmi_dt_handle_node(struct domain *d, struct dt_device_node *node)
> +{
> +    static const struct dt_device_match shmem_matches[] __initconst = {
> +        DT_MATCH_COMPATIBLE("arm,scmi-shmem"),
> +        { /* sentinel */ },
> +    };
> +    static const struct dt_device_match scmi_matches[] __initconst = {
> +        DT_MATCH_PATH("/firmware/scmi"),
> +        { /* sentinel */ },
> +    };
> +
> +    if ( !scmi_data.initialized )
> +        return false;
> +
> +    /* skip scmi shmem node for dom0 if scmi not enabled */
> +    if ( dt_match_node(shmem_matches, node) && !sci_domain_is_enabled(d) )
> +    {
> +        dt_dprintk("  Skip scmi shmem node\n");
> +        return true;
> +    }
> +
> +    /* drop scmi if not enabled */
> +    if ( dt_match_node(scmi_matches, node) && !sci_domain_is_enabled(d) )
> +    {
> +        dt_dprintk("  Skip scmi node\n");
> +        return true;
> +    }
> +
> +    return false;
> +}
> +
> +static int scmi_assign_device(uint32_t agent_id, uint32_t device_id,
> +                              uint32_t flags)
> +{
> +    struct scmi_msg_base_set_device_permissions_a2p tx;
> +    struct scmi_channel *channel;
> +    scmi_msg_header_t hdr;
> +
> +    channel = get_channel_by_id(scmi_data.hyp_channel_agent_id);
> +    if ( !channel )
> +        return -EINVAL;
> +
> +    hdr.id = SCMI_BASE_SET_DEVICE_PERMISSIONS;
> +    hdr.type = 0;
> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> +
> +    tx.agent_id = agent_id;
> +    tx.device_id = device_id;
> +    tx.flags = flags;
> +
> +    return do_smc_xfer(channel, &hdr, &tx, sizeof(tx), NULL, 0);
> +}
> +
> +static int scmi_dt_assign_device(struct domain *d,
> +                                 struct dt_phandle_args *ac_spec)
> +{
> +    struct scmi_channel *agent_channel;
> +    uint32_t scmi_device_id = ac_spec->args[0];
> +    int ret;
> +
> +    if ( !d->arch.sci_data )
> +        return 0;
> +
> +    /* The access-controllers is specified for DT dev, but it's not a SCMI */
> +    if ( ac_spec->np != scmi_data.dt_dev )
> +        return 0;
> +
> +    agent_channel = d->arch.sci_data;
> +
> +    spin_lock(&agent_channel->lock);
> +
> +    ret = scmi_assign_device(agent_channel->agent_id, scmi_device_id,
> +                             SCMI_BASE_DEVICE_ACCESS_ALLOW);
> +    if ( ret )
> +    {
> +        printk(XENLOG_ERR
> +               "scmi: could not assign dev for %pd agent:%d dev_id:%u (%d)",
> +               d, agent_channel->agent_id, scmi_device_id, ret);
> +    }
> +
> +    spin_unlock(&agent_channel->lock);
> +    return ret;
> +}
> +
> +static int collect_agent_id(struct scmi_channel *agent_channel)
> +{
> +    int ret;
> +    scmi_msg_header_t hdr;
> +    struct scmi_msg_base_discover_agent_p2a da_rx;
> +    struct scmi_msg_base_discover_agent_a2p da_tx;
> +
> +    ret = map_channel_memory(agent_channel);
> +    if ( ret )
> +        return ret;
> +
> +    hdr.id = SCMI_BASE_DISCOVER_AGENT;
> +    hdr.type = 0;
> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> +
> +    da_tx.agent_id = agent_channel->agent_id;
> +
> +    ret = do_smc_xfer(agent_channel, &hdr, &da_tx, sizeof(da_tx), &da_rx,
> +                        sizeof(da_rx));
> +    if ( agent_channel->domain_id != DOMID_XEN )
> +        unmap_channel_memory(agent_channel);
> +    if ( ret )
> +        return ret;
> +
> +    printk(XENLOG_DEBUG "id=0x%x name=%s\n", da_rx.agent_id, da_rx.name);
> +    agent_channel->agent_id = da_rx.agent_id;
> +    return 0;
> +}
> +
> +static __init int collect_agents(struct dt_device_node *scmi_node)
> +{
> +    const struct dt_device_node *config_node;
> +    const __be32 *prop;
> +    uint32_t len;
> +    const __be32 *end;
> +    uint32_t cells_per_entry = 3; /* Default to 3 cells if property is absent. */
> +
> +    config_node = dt_find_node_by_path("/chosen/xen,config");

Please use compatible strings, not paths


> +    if ( !config_node )
> +    {
> +        printk(XENLOG_WARNING "scmi: /chosen/xen,config node not found, no agents to collect.\n");
> +        return -ENOENT;
> +    }
> +
> +    /* Check for the optional '#scmi-secondary-agents-cells' property. */
> +    if ( dt_property_read_u32(config_node, "#scmi-secondary-agents-cells",
> +                              &cells_per_entry) )
> +    {
> +        if ( cells_per_entry != 2 && cells_per_entry != 3 )
> +        {
> +            printk(XENLOG_ERR "scmi: Invalid #scmi-secondary-agents-cells value: %u\n",
> +                   cells_per_entry);
> +            return -EINVAL;
> +        }
> +    }
> +
> +    prop = dt_get_property(config_node, SCMI_SECONDARY_AGENTS, &len);
> +    if ( !prop )
> +    {
> +        /* This is not an error, as there may be no secondary agents. */
> +        printk(XENLOG_WARNING "scmi: No %s property found, no agents to collect.\n",
> +               SCMI_SECONDARY_AGENTS);
> +        return -EINVAL;

While the comment says this is not a fatal error, returning -EINVAL
leads to scmi_probe taking the error path

> +    }
> +
> +    /* Validate that the property length is a multiple of the cell size. */
> +    if ( len == 0 || len % (cells_per_entry * sizeof(uint32_t)) != 0 )
> +    {
> +        printk(XENLOG_ERR "scmi: Invalid length of %s property: %u for %u cells per entry\n",
> +               SCMI_SECONDARY_AGENTS, len, cells_per_entry);
> +        return -EINVAL;
> +    }
> +
> +    end = (const __be32 *)((const u8 *)prop + len);
> +
> +    for ( ; prop < end; )
> +    {
> +        uint32_t agent_id;
> +        uint32_t smc_id;
> +        uint32_t shmem_phandle;
> +        struct dt_device_node *node;
> +        u64 addr, size;
> +        int ret;
> +        struct scmi_channel *agent_channel;
> +
> +        smc_id = be32_to_cpu(*prop++);
> +        shmem_phandle = be32_to_cpu(*prop++);
> +
> +        if ( cells_per_entry == 3 )
> +            agent_id = be32_to_cpu(*prop++);
> +        else
> +            agent_id = SCMI_BASE_AGENT_ID_OWN;
> +
> +        node = dt_find_node_by_phandle(shmem_phandle);
> +        if ( !node )
> +        {
> +            printk(XENLOG_ERR "scmi: Could not find shmem node for agent %u\n",
> +                   agent_id);
> +            return -EINVAL;
> +        }
> +
> +        ret = dt_device_get_address(node, 0, &addr, &size);
> +        if ( ret )
> +        {
> +            printk(XENLOG_ERR
> +                   "scmi: Could not read shmem address for agent %u: %d\n",
> +                   agent_id, ret);
> +            return ret;

why no "goto error" ?

> +        }
> +
> +        if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) )

should we also check that size % SCMI_SHMEM_MAPPED_SIZE == 0 ?


> +        {
> +            printk(XENLOG_ERR "scmi: shmem memory is not aligned\n");
> +            return -EINVAL;
> +        }
> +
> +        agent_channel = smc_create_channel(agent_id, smc_id, addr);
> +        if ( IS_ERR(agent_channel) )
> +        {
> +            printk(XENLOG_ERR "scmi: Could not create channel for agent %u: %ld\n",
> +                   agent_id, PTR_ERR(agent_channel));
> +            return PTR_ERR(agent_channel);
> +        }
> +
> +        if ( cells_per_entry == 2 )
> +        {
> +            ret = collect_agent_id(agent_channel);
> +            if ( ret )
> +                return ret;
> +        }
> +
> +        printk(XENLOG_DEBUG "scmi: Agent %u SMC %X addr %lx\n", agent_channel->agent_id,
> +               smc_id, (unsigned long)addr);
> +    }
> +
> +    return 0;
> +}
> +
> +static int scmi_domain_init(struct domain *d,
> +                            struct xen_domctl_createdomain *config)
> +{
> +    struct scmi_channel *channel;
> +    int ret;
> +
> +    if ( !scmi_data.initialized )
> +        return 0;
> +
> +    /*
> +     * Special case for Dom0 - the SCMI support is enabled basing on
> +     * "dom0_sci_agent_id" Xen command line parameter
> +     */
> +    if ( is_hardware_domain(d) )
> +    {
> +        if ( opt_dom0_scmi_agent_id != SCMI_AGENT_ID_INVALID )
> +        {
> +            config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
> +            config->arch.arm_sci_agent_id = opt_dom0_scmi_agent_id;
> +        }
> +        else
> +            config->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
> +    }
> +
> +    if ( config->arch.arm_sci_type == XEN_DOMCTL_CONFIG_ARM_SCI_NONE )
> +        return 0;
> +
> +    channel = acquire_scmi_channel(d, config->arch.arm_sci_agent_id);
> +    if ( IS_ERR(channel) )
> +    {
> +        printk(XENLOG_ERR
> +               "scmi: Failed to acquire SCMI channel for agent_id %u: %ld\n",
> +               config->arch.arm_sci_agent_id, PTR_ERR(channel));
> +        return PTR_ERR(channel);
> +    }
> +
> +    printk(XENLOG_INFO
> +           "scmi: Acquire channel id = 0x%x, domain_id = %d paddr = 0x%lx\n",
> +           channel->agent_id, channel->domain_id, channel->paddr);
> +
> +    /*
> +     * Dom0 (if present) needs to have an access to the guest memory range
> +     * to satisfy iomem_access_permitted() check in XEN_DOMCTL_iomem_permission
> +     * domctl.
> +     */
> +    if ( hardware_domain && !is_hardware_domain(d) )
> +    {
> +        ret = iomem_permit_access(hardware_domain, paddr_to_pfn(channel->paddr),
> +                                  paddr_to_pfn(channel->paddr + PAGE_SIZE - 1));
> +        if ( ret )
> +            goto error;
> +    }
> +
> +    d->arch.sci_data = channel;
> +    d->arch.sci_enabled = true;
> +
> +    return 0;
> +
> +error:
> +    relinquish_scmi_channel(channel);
> +    return ret;
> +}
> +
> +int scmi_domain_sanitise_config(struct xen_domctl_createdomain *config)
> +{
> +    if ( config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_NONE &&
> +         config->arch.arm_sci_type != XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA )
> +    {
> +        dprintk(XENLOG_INFO, "scmi: Unsupported ARM_SCI type\n");
> +        return -EINVAL;
> +    }
> +    else if ( config->arch.arm_sci_type ==
> +              XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA &&
> +              config->arch.arm_sci_agent_id == 0 )
> +    {
> +        dprintk(XENLOG_INFO,
> +                "scmi: A zero ARM SCMI agent_id is not supported\n");
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static int scmi_relinquish_resources(struct domain *d)
> +{
> +    int ret;
> +    struct scmi_channel *channel, *agent_channel;
> +    scmi_msg_header_t hdr;
> +    struct scmi_msg_base_reset_agent_cfg_a2p tx;
> +
> +    if ( !d->arch.sci_data )
> +        return 0;
> +
> +    agent_channel = d->arch.sci_data;
> +
> +    spin_lock(&agent_channel->lock);
> +    tx.agent_id = agent_channel->agent_id;
> +    spin_unlock(&agent_channel->lock);
> +
> +    channel = get_channel_by_id(scmi_data.hyp_channel_agent_id);
> +    if ( !channel )
> +    {
> +        printk(XENLOG_ERR
> +               "scmi: Unable to get Hypervisor scmi channel for domain %d\n",
> +               d->domain_id);
> +        return -EINVAL;
> +    }
> +
> +    hdr.id = SCMI_BASE_RESET_AGENT_CONFIGURATION;
> +    hdr.type = 0;
> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> +
> +    tx.flags = 0;
> +
> +    ret = do_smc_xfer(channel, &hdr, &tx, sizeof(tx), NULL, 0);
> +    if ( ret == -EOPNOTSUPP )
> +        return 0;
> +
> +    return ret;
> +}
> +
> +static void scmi_domain_destroy(struct domain *d)
> +{
> +    struct scmi_channel *channel;
> +
> +    if ( !d->arch.sci_data )
> +        return;
> +
> +    channel = d->arch.sci_data;
> +    spin_lock(&channel->lock);
> +
> +    relinquish_scmi_channel(channel);
> +    printk(XENLOG_DEBUG "scmi: Free domain %d\n", d->domain_id);
> +
> +    d->arch.sci_data = NULL;
> +    d->arch.sci_enabled = true;

Should this be false?


> +    spin_unlock(&channel->lock);
> +}
> +
> +static bool scmi_handle_call(struct cpu_user_regs *regs)
> +{
> +    uint32_t fid = (uint32_t)get_user_reg(regs, 0);
> +    struct scmi_channel *agent_channel;
> +    struct domain *d = current->domain;
> +    struct arm_smccc_res resp;
> +    bool res = false;
> +
> +    if ( !sci_domain_is_enabled(d) )
> +        return false;
> +
> +    agent_channel = d->arch.sci_data;
> +    spin_lock(&agent_channel->lock);
> +
> +    if ( agent_channel->func_id != fid )
> +    {
> +        res = false;
> +        goto unlock;
> +    }
> +
> +    arm_smccc_1_1_smc(fid,
> +                      get_user_reg(regs, 1),
> +                      get_user_reg(regs, 2),
> +                      get_user_reg(regs, 3),
> +                      get_user_reg(regs, 4),
> +                      get_user_reg(regs, 5),
> +                      get_user_reg(regs, 6),
> +                      get_user_reg(regs, 7),
> +                      &resp);
> +
> +    set_user_reg(regs, 0, resp.a0);
> +    set_user_reg(regs, 1, resp.a1);
> +    set_user_reg(regs, 2, resp.a2);
> +    set_user_reg(regs, 3, resp.a3);
> +    res = true;
> +unlock:
> +    spin_unlock(&agent_channel->lock);
> +
> +    return res;
> +}
> +
> +static const struct sci_mediator_ops scmi_ops = {
> +    .domain_init = scmi_domain_init,
> +    .domain_destroy = scmi_domain_destroy,
> +    .relinquish_resources = scmi_relinquish_resources,
> +    .handle_call = scmi_handle_call,
> +    .dom0_dt_handle_node = scmi_dt_handle_node,
> +    .domain_sanitise_config = scmi_domain_sanitise_config,
> +    .assign_dt_device = scmi_dt_assign_device,
> +};
> +
> +static int __init scmi_check_smccc_ver(void)
> +{
> +    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
> +    {
> +        printk(XENLOG_WARNING
> +               "scmi: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
> +        return -ENOSYS;
> +    }
> +
> +    return 0;
> +}
> +
> +static int scmi_dt_hyp_channel_read(struct dt_device_node *scmi_node, struct scmi_data *scmi_data,
> +                                    u64 *addr)
> +{
> +    int ret;
> +    u64 size;
> +
> +    if ( !dt_property_read_u32(scmi_node, "arm,smc-id", &scmi_data->func_id) )
> +    {
> +        printk(XENLOG_ERR "scmi: unable to read smc-id from DT\n");
> +        return -ENOENT;
> +    }
> +
> +    ret = scmi_dt_read_hyp_channel_addr(scmi_node, addr, &size);
> +    if ( IS_ERR_VALUE(ret) )
> +        return -ENOENT;
> +
> +    if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) )
> +    {
> +        printk(XENLOG_ERR "scmi: shmem memory is not aligned\n");
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static __init int scmi_probe(struct dt_device_node *scmi_node, const void *data)
> +{
> +    u64 addr;
> +    int ret;
> +    struct scmi_channel *channel;
> +    int n_agents;
> +    scmi_msg_header_t hdr;
> +    struct scmi_msg_base_attributes_p2a rx;
> +
> +    ASSERT(scmi_node != NULL);
> +
> +    INIT_LIST_HEAD(&scmi_data.channel_list);
> +    spin_lock_init(&scmi_data.channel_list_lock);
> +
> +    if ( !acpi_disabled )
> +    {
> +        printk(XENLOG_WARNING "scmi: is not supported when using ACPI\n");
> +        return -EINVAL;
> +    }
> +
> +    ret = scmi_check_smccc_ver();
> +    if ( ret )
> +        return ret;
> +
> +    ret = scmi_dt_hyp_channel_read(scmi_node, &scmi_data, &addr);
> +    if ( ret )
> +        return ret;
> +
> +    scmi_data.dt_dev = scmi_node;
> +
> +    channel = smc_create_channel(SCMI_BASE_AGENT_ID_OWN, scmi_data.func_id, addr);

Should we call this with channel_list_lock held?


> +    if ( IS_ERR(channel) )
> +        goto out;
> +
> +    /* Request agent id for Xen management channel  */

At this poing channel->domain_id == DOMID_INVALID but collect_agent_id
checks for agent_channel->domain_id != DOMID_XEN

> +    ret = collect_agent_id(channel);
> +    if ( ret )
> +        return ret;
> +
> +    /* Save the agent id for Xen management channel */
> +    scmi_data.hyp_channel_agent_id = channel->agent_id;
> +
> +    ret = map_channel_memory(channel);
> +    if ( ret )
> +        goto out;

collect_agent_id already called map_channel_memory it looks like the
code was supposed to not unmap it the memory if domain_id == DOMID_XEN,
although the check doesn't work as expected.


> +    channel->domain_id = DOMID_XEN;
> +
> +    hdr.id = SCMI_BASE_PROTOCOL_ATTIBUTES;
> +    hdr.type = 0;
> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> +
> +    ret = do_smc_xfer(channel, &hdr, NULL, 0, &rx, sizeof(rx));
> +    if ( ret )
> +        goto error;
> +
> +    n_agents = SCMI_FIELD_GET(SCMI_BASE_ATTR_NUM_AGENT, rx.attributes);
> +    printk(XENLOG_DEBUG "scmi: Got agent count %d\n", n_agents);
> +    ret = collect_agents(scmi_node);
> +    if ( ret )
> +        goto error;
> +
> +    ret = sci_register(&scmi_ops);
> +    if ( ret )
> +    {
> +        printk(XENLOG_ERR "SCMI: mediator already registered (ret = %d)\n",
> +               ret);
> +        return ret;
> +    }
> +
> +    scmi_data.initialized = true;
> +    goto out;
> +
> +error:
> +    unmap_channel_memory(channel);
> +    free_channel_list();
> +out:
> +    return ret;
> +}
> +
> +static const struct dt_device_match scmi_smc_match[] __initconst = {
> +    DT_MATCH_PATH("/chosen/xen,config/scmi"),

We should match by compatible string, not by path

> +    { /* sentinel */ },
> +};
> +
> +DT_DEVICE_START(scmi_smc_ma, "SCMI SMC MEDIATOR", DEVICE_FIRMWARE)
> +        .dt_match = scmi_smc_match,
> +        .init = scmi_probe,
> +DT_DEVICE_END
> +
> +/*
> + * Local variables:
> + * mode: C
> + * c-file-style: "BSD"
> + * c-basic-offset: 4
> + * tab-width: 4
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index 095b1a23e3..30e46de6d7 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -329,6 +329,7 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>  
>  #define XEN_DOMCTL_CONFIG_ARM_SCI_NONE      0
>  #define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC  1
> +#define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA  2
>  
>  struct xen_arch_domainconfig {
>      /* IN/OUT */
> @@ -355,6 +356,8 @@ struct xen_arch_domainconfig {
>      uint32_t clock_frequency;
>      /* IN */
>      uint8_t arm_sci_type;
> +    /* IN */
> +    uint8_t arm_sci_agent_id;
>  };
>  #endif /* __XEN__ || __XEN_TOOLS__ */
>  
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 10/10] docs: arm: add SCI SCMI SMC multi-agent driver docs
  2025-07-22 11:41 ` [RFC PATCH v5 10/10] docs: arm: add SCI SCMI SMC multi-agent driver docs Oleksii Moisieiev
@ 2025-08-26  0:44   ` Stefano Stabellini
  0 siblings, 0 replies; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-26  0:44 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Stefano Stabellini,
	Volodymyr Babchuk, Grygorii Strashko

On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> From: Grygorii Strashko <grygorii_strashko@epam.com>
> 
> Add SCI SCMI SMC multi-agent driver documentation.
> It includes a detailed description of the SCMI multi-agent driver.
> This document explains the driver's functionality, configuration,
> and the compilation process. The Xen SCMI multi-agent driver is
> designed to provide SCMI access to system resources from different
> domains.
> 
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>

missing Grygorii's signed-off-by


> ---
> 
> Changes in v5:
> - rework multi-agent driver to leave Host Device-tree unmodified
> 
>  .../arm/firmware/arm-scmi.rst                 | 341 +++++++++++++++++-
>  1 file changed, 340 insertions(+), 1 deletion(-)
> 
> diff --git a/docs/hypervisor-guide/arm/firmware/arm-scmi.rst b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
> index a084c0caa3..2ab56af879 100644
> --- a/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
> +++ b/docs/hypervisor-guide/arm/firmware/arm-scmi.rst
> @@ -31,7 +31,10 @@ domain serving as Driver domain).
>  
>  The below sections describe SCMI support options available for Xen.
>  
> -[1] `Arm SCMI <https://developer.arm.com/documentation/den0056/latest/>`_
> +| [1] `Arm SCMI <https://developer.arm.com/documentation/den0056/latest/>`_
> +| [2] `System Control and Management Interface (SCMI) bindings <https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml>`_
> +| [3] `Generic Domain Access Controllers bindings <https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml>`_
> +
>  
>  Simple SCMI over SMC/HVC calls forwarding driver (EL3)
>  ------------------------------------------------------
> @@ -175,3 +178,339 @@ enabling SCMI with "arm_sci" xl.cfg option.
>      ->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
>      ->        xen,force-assign-without-iommu;
>        };
> +
> +SCMI SMC/HVC multi-agent driver (EL3)
> +-------------------------------------
> +
> +The SCMI SMC/HVC multi-agent driver enables support for ARM EL3 Trusted Firmware-A (TF-A) which
> +provides SCMI interface with multi-agnet support, as shown below.

multi-agent

> +
> +::
> +
> +      +-----------------------------------------+
> +      |                                         |
> +      | EL3 TF-A SCMI                           |
> +      +-------+--+-------+--+-------+--+-------++
> +      |shmem1 |  |shmem0 |  |shmem2 |  |shmemX |
> +      +-----+-+  +---+---+  +--+----+  +---+---+
> +    smc-id1 |        |         |           |
> +    agent1  |        |         |           |
> +      +-----v--------+---------+-----------+----+
> +      |              |         |           |    |
> +      |              |         |           |    |
> +      +--------------+---------+-----------+----+
> +             smc-id0 |  smc-id2|    smc-idX|
> +             agent0  |  agent2 |    agentX |
> +                     |         |           |
> +                +----v---+  +--v-----+  +--v-----+
> +                |        |  |        |  |        |
> +                | Dom0   |  | Dom1   |  | DomX   |
> +                |        |  |        |  |        |
> +                |        |  |        |  |        |
> +                +--------+  +--------+  +--------+
> +
> +The EL3 SCMI multi-agent firmware expected to provide SCMI SMC/HVC shared-memory transport

is expected to provide


> +for every Agent in the system. The SCMI Agent transport channel defined by pair:
> +
> +- smc-id: SMC/HVC function id used for Doorbell
> +- shmem: shared memory for messages transfer, **Xen page aligned**.
> +  Shared memory is mapped with the following flags: MT_DEVICE_nGnRE and _PAGE_DEVICE, indicating that this
> +  memory is mapped as device memory.
> +
> +The following SCMI Agents expected to be defined by SCMI FW to enable SCMI multi-agent functionality

is expected to

> +under Xen:
> +
> +- Xen management agent: trusted agents that accesses to the Base Protocol commands to configure
> +  agent specific permissions
> +- OSPM VM agents: non-trusted agent, one for each Guest domain which is  allowed direct HW access.
> +  At least one OSPM VM agent has to be provided by FW if HW is handled only by Dom0 or Driver Domain.
> +
> +The EL3 SCMI FW expected to implement following Base protocol messages:

is expected to

> +
> +- BASE_DISCOVER_AGENT (optional if agent_id was provided)
> +- BASE_RESET_AGENT_CONFIGURATION (optional)
> +- BASE_SET_DEVICE_PERMISSIONS (optional)
> +
> +The number of supported SCMI agents and their transport specifications are SCMI FW implementation
> +specific.
> +
> +Compiling with multi-agent support
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +To build with the SCMI SMC/HVC multi-agent driver support, enable Kconfig option:
> +
> +::
> +
> +    CONFIG_SCMI_SMC_MA
> +
> +
> +Driver functionality
> +^^^^^^^^^^^^^^^^^^^^
> +
> +The SCI SCMI SMC multi-agent driver implements following functionality:
> +
> +- The driver is initialized based on the ``xen,config`` node under ``chosen``
> +  (only one SCMI interface is supported), which describes the Xen management
> +  agent SCMI interface.
> +
> +.. code::
> +
> +    scmi_shm_1: sram@47ff1000 {
> +              compatible = "arm,scmi-shmem";
> +              reg = <0x0 0x47ff1000 0x0 0x1000>;
> +    };
> +    scmi_xen: scmi {
> +            compatible = "arm,scmi-smc";
> +            arm,smc-id = <0x82000002>; <--- Xen manegement agent smc-id
> +            #address-cells = < 1>;
> +            #size-cells = < 0>;
> +            #access-controller-cells = < 1>;
> +            shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
> +    };
> +
> +- The driver obtains Xen specific SCMI Agent's configuration from the Host DT, probes Agents and
> +  builds SCMI Agents list. The Agents configuration is taken from "scmi-secondary-agents"
> +  property where first item is "arm,smc-id", second - "arm,scmi-shmem" phandle and third is
> +  optional "agent_id":
> +
> +.. code::

.. code-block:: dts


> +    chosen {
> +      ranges; <--- set default ranges so address can be translated when parsing scmi_shm node
> +      xen,config {
> +        ranges; <--- set default ranges so address can be translated when parsing scmi_shm node
> +        scmi-secondary-agents = <
> +                      0x82000003 &scmi_shm_0 0
> +                      0x82000004 &scmi_shm_2 2
> +                      0x82000005 &scmi_shm_3 3
> +                      0x82000006 &scmi_shm_4 4>;
> +        #scmi-secondary-agents-cells = <3>; <--- optional, default 3
> +
> +        scmi_shm_0 : sram@47ff0000 {
> +            compatible = "arm,scmi-shmem";
> +            reg = <0x0 0x47ff0000 0x0 0x1000>;
> +        };
> +
> +        scmi_shm_2: sram@47ff2000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff2000 0x0 0x1000>;
> +        };
> +        scmi_shm_3: sram@47ff3000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff3000 0x0 0x1000>;
> +        };
> +        scmi_shm_4: sram@47ff4000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff4000 0x0 0x1000>;
> +        };
> +
> +        // Xen SCMI management channel
> +        scmi_shm_1: sram@47ff1000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff1000 0x0 0x1000>;
> +        };
> +
> +        scmi_xen: scmi {
> +            compatible = "arm,scmi-smc";
> +            arm,smc-id = <0x82000002>; <--- Xen manegement agent smc-id
> +            #address-cells = < 1>;
> +            #size-cells = < 0>;
> +            #access-controller-cells = < 1>;
> +            shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
> +        };
> +      };
> +    };
> +
> +    /{
> +        // Host SCMI OSPM channel - provided to the Dom0 as is if SCMI enabled for it
> +        scmi_shm: sram@47ff1000 {
> +                compatible = "arm,scmi-shmem";
> +                reg = <0x0 0x47ff1000 0x0 0x1000>;
> +        };
> +
> +        firmware {
> +            scmi: scmi {
> +                compatible = "arm,scmi-smc";
> +                arm,smc-id = <0x82000003>; <--- Host OSPM agent smc-id
> +                #address-cells = < 1>;
> +                #size-cells = < 0>;
> +                shmem = <&scmi_shm>; <--- Host OSPM agent shmem
> +
> +                protocol@X{
> +                };
> +            };
> +        };
> +    };
> +
> +  This approach allows defining multiple SCMI Agents by adding Xen-specific properties under
> +  the ``/chosen`` node to the Host Device Tree, leaving the main part unchanged. The Host DT
> +  SCMI channel will be passed to Dom0.
> +
> +  The Xen management agent is described as a ``scmi_xen`` node under the ``/chosen`` node, which
> +  is used by Xen to control other SCMI Agents in the system.
> +
> +  All secondary agents' configurations are provided in the ``scmi-secondary-agents`` property with
> +  an optional ``agent_id`` field.
> +
> +  The ``agent_id`` from the ``scmi-secondary-agents`` property is used to identify the agent in the
> +  system and can be omitted by setting ``#scmi-secondary-agents-cells = <2>``, so the Secondary
> +  Agents configuration will look like this:
> +
> +.. code::

.. code-block:: dts


> +    chosen {
> +      xen,config {
> +        scmi-secondary-agents = <
> +                      0x82000003 &scmi_shm_0
> +                      0x82000004 &scmi_shm_2
> +                      0x82000005 &scmi_shm_3
> +                      0x82000006 &scmi_shm_4>;
> +        #scmi-secondary-agents-cells = <2>;
> +      };
> +    }
> +
> +  In this case, Xen will use the ``SCMI_BASE_DISCOVER_AGENT`` call to discover the ``agent_id``
> +  for each secondary agent. Providing the ``agent_id`` in the ``scmi-secondary-agents`` property
> +  allows skipping the discovery call, which is useful when the secondary agent's shared memory is
> +  not accessible by Xen or when boot time is important because it allows skipping the agent
> +  discovery procedure.
> +
> +.. note::
> +
> +    Note that Xen is the only one entry in the system which need to know about SCMI multi-agent support.
> +
> +- The driver implements the SCI subsystem interface required for configuring and enabling SCMI
> +  functionality for Dom0/hwdom and Guest domains. To enable SCMI functionality for guest domain
> +  it has to be configured with unique supported SCMI Agent_id and use corresponding SCMI SMC/HVC
> +  shared-memory transport ``[smc-id, shmem]`` defined for this SCMI Agent_id.
> +
> +- Once Xen domain is configured it can communicate with EL3 SCMI FW:
> +
> +  - zero-copy, the guest domain puts/gets SCMI message in/from shmem;
> +  - the guest triggers SMC/HVC exception with agent "smc-id" (doorbell);
> +  - the Xen driver catches exception, do checks and synchronously forwards it to EL3 FW.
> +
> +- the Xen driver sends BASE_RESET_AGENT_CONFIGURATION message to Xen management agent channel on
> +  domain destroy event. This allows to reset resources used by domain and so implement use-case
> +  like domain reboot.
> +
> +
> +Configure SCMI for Dom0
> +^^^^^^^^^^^^^^^^^^^^^^^
> +The **"dom0_scmi_agent_id=<dom0_agent_id>"** Xen command line is used to enable SCMI functionality for
> +Dom0. if not provided SCMI will be disabled for Dom0 and all SCMI nodes removed from Dom0 DT.
> +
> +Xen utilizes Host DT SCMI node to configure Dom0 SCMI Agent so the device-tree remains unchanged
> +except for the Xen specific properties under ``/chosen`` node. If Xen device-tree doesn't include
> +``/firmware/scmi`` node or it's disabled, the Dom0 SCMI Agent will not be configured.
> +
> +.. note::
> +
> +    The **dom0_scmi_agent_id** value should match the ``func_id`` and ``shmem`` in the ``/firmware/scmi`` node
> +    to set the correct Dom0 SCMI Agent.
> +
> +Configure SCMI for for guest domain with toolstack
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +* In domain's xl.cfg file add **"arm_sci"** option as below
> +
> +::
> +
> +    arm_sci = "type=scmi_smc_multiagent,agent_id=2"
> +
> +* In domain's xl.cfg file enable access to the "arm,scmi-shmem" which should correspond
> +  assigned "agent_id" for the domain, for example:
> +
> +::
> +
> +    iomem = [
> +        "47ff2,1@22001",
> +    ]
> +
> +.. note:: It's up to the user to select guest IPA for mapping SCMI shared-memory.
> +
> +* Add SCMI nodes to the Driver domain partial device tree as in the below example.
> +  The "arm,smc-id" should correspond assigned agent_id for the domain:
> +
> +.. code::
> +
> +    passthrough {
> +       scmi_shm_0: sram@22001000 {
> +           compatible = "arm,scmi-shmem";
> +           reg = <0x0 0x22001000 0x0 0x1000>;
> +       };
> +
> +       firmware {
> +            compatible = "simple-bus";
> +                scmi: scmi {
> +                    compatible = "arm,scmi-smc";
> +                    arm,smc-id = <0x82000004>;
> +                    shmem = <&scmi_shm_0>;
> +                    ...
> +                }
> +        }
> +    }
> +
> +**Device specific access control**
> +
> +The XEN SCMI SMC/HVC multi-agent driver performs "access-controller" provider function in case
> +EL3 SCMI FW implements SCMI "4.2.1.1 Device specific access control" and provides the
> +BASE_SET_DEVICE_PERMISSIONS command to configure the devices that an agents have access to.
> +The Host DT SCMI node should have "#access-controller-cells=<1>" property and DT devices should
> +be bound to the SCMI node using Access Controllers bindings [3].
> +
> +For example:
> +
> +.. code::
> +
> +    &i2c1 {
> +            access-controllers = <&scmi 0>;
> +    };
> +
> +Use domain's xl.cfg file **"dtdev"** property to assign SCMI devices from toolstack to the guest:
> +
> +::
> +
> +    dtdev = [
> +        "/soc/i2c@e6508000",
> +    ]
> +
> +.. note::
> +
> +    xl.cfg:"dtdev" need contain all nodes which are under SCMI management (not only those which are
> +    behind IOMMU) and passed-through to the guest domain.
> +
> +Configure SCMI for predefined domains (dom0less)
> +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> +
> +* add "xen,sci_type" and "xen,sci_agent_id" properties for required DomU ("xen,domain") node
> +
> +::
> +
> +    xen,sci_type="scmi_smc_multiagent"
> +    xen,sci_agent_id=2
> +
> +* add scmi nodes to the Driver domain partial device tree the same way as above (toolstack case) and
> +  enable access to the "arm,scmi-shmem" according to the dom0less documentation. For example:
> +
> +.. code::
> +
> +      scmi_shm_0: sram@22001000 {
> +            compatible = "arm,scmi-shmem";
> +            reg = <0x00 0x22001000 0x00 0x1000>;
> +    ->        xen,reg = <0x0 0x47ff0000 0x0 0x1000 0x0 0x22001000>;
> +    ->        xen,force-assign-without-iommu;
> +      };
> +
> +* For SCMI device access control configure pass-through devices in the guest partial DT according to
> +  the dom0less documentation and ensure that devices SCMI management has "xen,path" property set:
> +
> +.. code::
> +
> +		i2c@e6508000 {
> +            ...
> +			reg = <0x00 0xe6508000 0x00 0x1000>;
> +    ->        xen,path = "/soc/i2c@e6508000"
> +    ->        xen,reg = <0x0 0xe6508000 0x0 0x1000 0x0 0xe6508000>;
> +    ->        xen,force-assign-without-iommu;
> +        };
> -- 
> 2.34.1
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem
  2025-08-23  0:26   ` Stefano Stabellini
@ 2025-08-27  9:02     ` Oleksii Moisieiev
  2025-08-27 19:39       ` Stefano Stabellini
  0 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-08-27  9:02 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Volodymyr Babchuk,
	Grygorii Strashko



On 23/08/2025 03:26, Stefano Stabellini wrote:
> On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
>> From: Grygorii Strashko <grygorii_strashko@epam.com>
>>
>> The introduced SCI (System Control Interface) subsystem provides unified
>> interface to integrate in Xen SCI drivers which adds support for ARM
>> firmware (EL3, SCP) based software interfaces (like SCMI) that are used in
>> system management. The SCI subsystem allows to add drivers for different FW
>> interfaces or have different drivers for the same FW interface (for example,
>> SCMI with different transports).
>>
>> This patch updates SCMI over SMC calls handling layer, introduced by
>> commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls handling
>> layer"), to be SCI driver:
>> - convert to DT device;
>> - convert to SCI Xen interface.
>>
>> There are no functional changes in general, the driver is just adopted
>> to the SCI interface.
>>
>> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
>> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>> ---
>>
>>
>>
>>   xen/arch/arm/firmware/Kconfig                | 13 ++-
>>   xen/arch/arm/firmware/scmi-smc.c             | 93 +++++++++++---------
>>   xen/arch/arm/include/asm/firmware/scmi-smc.h | 41 ---------
>>   xen/arch/arm/vsmc.c                          |  5 +-
>>   xen/include/public/arch-arm.h                |  1 +
>>   5 files changed, 64 insertions(+), 89 deletions(-)
>>   delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
>>
>> diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
>> index fc7918c7fc..bbf88fbb9a 100644
>> --- a/xen/arch/arm/firmware/Kconfig
>> +++ b/xen/arch/arm/firmware/Kconfig
>> @@ -8,9 +8,18 @@ config ARM_SCI
>>   
>>   menu "Firmware Drivers"
>>   
>> +choice
>> +	prompt "ARM SCI driver type"
>> +	default SCMI_SMC
>> +	help
>> +	Choose which ARM SCI driver to enable.
>> +
>> +config ARM_SCI_NONE
>> +	bool "none"
>> +
>>   config SCMI_SMC
>>   	bool "Forward SCMI over SMC calls from hwdom to EL3 firmware"
>> -	default y
>> +	select ARM_SCI
>>   	help
>>   	  This option enables basic awareness for SCMI calls using SMC as
>>   	  doorbell mechanism and Shared Memory for transport ("arm,scmi-smc"
>> @@ -18,4 +27,6 @@ config SCMI_SMC
>>   	  firmware node is used to trap and forward corresponding SCMI SMCs
>>   	  to firmware running at EL3, for calls coming from the hardware domain.
>>   
>> +endchoice
>> +
>>   endmenu
>> diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c
>> index 33473c04b1..13d1137592 100644
>> --- a/xen/arch/arm/firmware/scmi-smc.c
>> +++ b/xen/arch/arm/firmware/scmi-smc.c
>> @@ -9,6 +9,7 @@
>>    * Copyright 2024 NXP
>>    */
>>   
>> +#include <asm/device.h>
>>   #include <xen/acpi.h>
>>   #include <xen/device_tree.h>
>>   #include <xen/errno.h>
>> @@ -16,12 +17,11 @@
>>   #include <xen/sched.h>
>>   #include <xen/types.h>
>>   
>> +#include <asm/firmware/sci.h>
>>   #include <asm/smccc.h>
>> -#include <asm/firmware/scmi-smc.h>
>>   
>>   #define SCMI_SMC_ID_PROP   "arm,smc-id"
>>   
>> -static bool __ro_after_init scmi_enabled;
>>   static uint32_t __ro_after_init scmi_smc_id;
>>   
>>   /*
>> @@ -41,14 +41,11 @@ static bool scmi_is_valid_smc_id(uint32_t fid)
>>    *
>>    * Returns true if SMC was handled (regardless of response), false otherwise.
>>    */
>> -bool scmi_handle_smc(struct cpu_user_regs *regs)
>> +static bool scmi_handle_smc(struct cpu_user_regs *regs)
>>   {
>>       uint32_t fid = (uint32_t)get_user_reg(regs, 0);
>>       struct arm_smccc_res res;
>>   
>> -    if ( !scmi_enabled )
>> -        return false;
>> -
>>       if ( !scmi_is_valid_smc_id(fid) )
>>           return false;
>>   
>> @@ -78,49 +75,45 @@ bool scmi_handle_smc(struct cpu_user_regs *regs)
>>       return true;
>>   }
>>   
>> -static int __init scmi_check_smccc_ver(void)
>> +static int scmi_smc_domain_init(struct domain *d,
>> +                                struct xen_domctl_createdomain *config)
>>   {
>> -    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
>> -    {
>> -        printk(XENLOG_WARNING
>> -               "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
>> -        return -ENOSYS;
>> -    }
>> +    if ( !is_hardware_domain(d) )
>> +        return 0;
> Should we also check for config->arch.sci_type ==
> XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC ?
>
Current changes assume that only SCMI_SMC is present. This check was 
added in the subsequent patch when multiagent was introduced.
>> +    d->arch.sci_enabled = true;
>> +    printk(XENLOG_DEBUG "SCMI: %pd init\n", d);
>>       return 0;
>>   }

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support
  2025-08-23  0:34 ` [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Stefano Stabellini
@ 2025-08-27  9:10   ` Oleksii Moisieiev
  2025-08-27 15:37     ` Stefano Stabellini
  0 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-08-27  9:10 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Volodymyr Babchuk,
	Grygorii Strashko

Hi Stefano,

Our use-case imply using scmi-smc-multiagent to be able to split scmi
between the domains,
so we would like to apply all patch series in the release.

On 23/08/2025 03:34, Stefano Stabellini wrote:
> I think it should be feasible to commit at least patches 1-4 in time for
> the release
>
> On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
>> Inroducing V4 RFC patch series  on top of the Xen version 4.20-rc2
>> which includes implementation of the SCI SCMI SMC multi-agent support.
>>
>> Patch 1 "xen/arm: add generic SCI subsystem"
>> - rebased and refactored
>> - introduced DEVICE_ARM_SCI DT device class and used for SCI drivers probing
>> instead of custom,
>>    linker sections based implementation.
>> - added SCI API for Dom0 DT handling, instead of manipulating with ARM arch
>> dom0 code directly.
>> - RFC changes in XEN_DOMCTL_assign_device OP processing
>> - Introduce arch_handle_passthrough_prop call to handle arm specific
>> nodes
>>
>> Patch 2 "xen/arm: scmi-smc: update to be used under sci subsystem"
>> - update driver introduced by commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI
>> over SMC calls
>> handling layer") be used under sci subsystem.
>> - no functional changes in general
>>
>> Patch 3 "xen/arm: scmi-smc: passthrough SCMI SMC to guest domain
>> This is new change which allows passthrough SCMI SMC, single agent interface to
>> guest domain
>> cover use case "thin Dom0 with guest domain, which serves as Driver domain".
>> See patch commit message for full description.
>>
>> Patch 4 - docs: arm: add docs for SCMI over SMC calls forwarding
>> driver
>> - add documentation section for Simple Arm SCMI over SMC/HVC calls
>> forwarding driver.
>>
>> Patch 6 - xen/domctl: extend XEN_DOMCTL_assign_device to handle not
>> only iommu
>> - add chainged handling of assigned DT devices to support
>> access-controller functionality through SCI framework.
>> Change was done in two parts:
>>   - update iommu_do_dt_domctl() to check for dt_device_is_protected()
>>   and not fail if DT device is not protected by IOMMU
>>   -add chained call to sci_do_domctl() to do_domctl()
>>
>> Patch 9 - xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
>> - added "scmi-secondary-agents" and "#scmi-secondary-agent-cells"
>>    property to "xen,config" node in "chosen" to inform SCI SCMI
>>    multi-agent driver about available agents and their
>>    configuration. It defines <agent_id> to <smc-id,scmi_shm> map.
>>    This option is Xen specific as Xen is the only one entry in the
>>    system which need to know about SCMI multi-agent support and configuration.
>> - each guest using SCMI should be configured with SCMI agent_id, so SCMI
>>    FW can implement Agent-specific permission policy.
>>    -- dom0: dom0_scmi_agent_id=<agent_id> in Xen command line option
>>    -- toolstack: arm_sci = "type=scmi_smc_multiagent,agent_id=<agent_id>"
>>    -- dom0less: "xen,sci_type", "xen,sci_agent_id" properties in
>> "xen,domain" nodes.
>> - factored out SCMI generic definitions (re-usable)
>> - factored out SCMI shmem code (re-usable)
>> - the SCMI passthrough configuration for guest domains is similar to any other
>> HW passthrough cfg.
>>
>> Patch 10 - docs: arm: add SCI SCMI SMC multi-agent driver docs
>> - add SCI SCMI SMC multi-agent driver documentation.
>>
>> Add separate SCMI DT node for Xen management agent under "xen,config"
>> node under chosen.
>>
>> All Xen-specific configuration provided under "/chosen" node. This
>> approach allows to isolate modifications to Host DT only under
>> "/chosen" node.
>>
>> This approach provides the following device tree (DT)
>> parameters (placed under xen,config node):
>>
>> - "scmi-secondary-agents": A Xen-specific parameter under the
>>    "/chosen" node, which describes the SCMI agent configuration for
>>    the domains.
>> - the SCMI configuration for Xen (privileged agent) and the shared
>>    memory configuration for all agents are provided under the "/chosen"
>>    node and are used strictly by Xen for its initial configuration.
>> - the scmi_shm and SCMI configuration for Dom0 are placed in the
>>    "/firmware/scmi" node so that they can be moved to Dom0 without
>>    any changes.
>>
>> This configuration allows the use of Xen-specific nodes to provide
>> information strictly needed by Xen while using the default SCMI
>> configuration for Dom0 and other domains. As a result, no additional
>> bindings need to be introduced to the device tree.
>> This simplifies the Xen SCMI multi-agent configuration and utilizes
>> generic device tree bindings for the domains.
>>
>> NOTE: Haven't added RB tags for patch 1 and 2 because rebase and some
>> minor changes were done.
>>
>> Code can be found at:
>> https://github.com/oleksiimoisieiev/xen/tree/scmi_upstrv5
>>
>> [1] RFC v2:
>> http://patchwork.kernel.org/project/xen-devel/cover/cover.1644341635.git.oleksii_moisieiev@epam.com/
>> [2] RFC v3:
>> https://patchwork.kernel.org/project/xen-devel/patch/20250311111618.1850927-1-grygorii_strashko@epam.com
>> SCMI spec:
>> https://developer.arm.com/documentation/den0056/e/?lang=en
>>
>> SCMI bindings:
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
>> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml
>>
>> Reference EL3 FW:
>> RPI5: https://github.com/xen-troops/arm-trusted-firmware/commits/rpi5_dev/
>> Renesas v4h:
>> https://github.com/GrygiriiS/arm-trusted-firmware/commits/rcar_gen4_v2.7_v4x-scmi_upd/
>>
>> base-commit: dbe60f244c (Update Xen to 4.21, 2025-02-21)
>>
>> Changes in v5:
>> - update Maintainers file. Set role as a Reviewer
>> - rebased on the latest master branch
>> - Introduce arch_handle_passthrough_prop call to handle arm specific nodes
>> - rename dom0_scmi_smc_passthrough to scmi_smc_passthrough
>> - rename dom0_scmi_smc_passthrough in documentation
>> - set error code to -ENXIO when iommu is disabled
>> - return -EINVAL if mediator without assign_dt_device was provided
>> - invert return code check for iommu_do_domctl in
>> XEN_DOMCTL_assign_device domctl processing to make cleaner code
>> - change -ENOTSUPP error code to -ENXIO in sci_do_domctl
>> - handle -ENXIO return comde of iommu_do_domctl
>> - leave !dt_device_is_protected check in iommu_do_dt_domctl to make
>> code work the same way it's done in "handle_device" call while
>> creating hwdom(dom0) and "handle_passthrough_prop" call for dom0less
>> creation
>> - drop return check from sci_assign_dt_device call as not needed
>> - do not return EINVAL when addign_dt_device is not set. That is
>> because this callback is optional and not implemented in single-agent driver
>> - move memcpy_toio/fromio to the generic place
>> - fix device-tree example format in booting.txt, added ";" after "}".
>> - update define in scmi-proto.h
>> - update define in scmi-shmem.h file
>> - scmi_assign_device - do not ignore -EOPNOTSUPP return
>> code of the do_smc_xfer
>> - remove overwriting agent_channel->agent_id after
>> SCMI_BASE_DISCOVER_AGENT call
>> - add multi-agent files to the MAINTAINERS
>> - add SCMI multi-agent description to the SUPPORT.md
>> - handle ARM_SMCCC_INVALID_PARAMETER return code and return -EINVAL
>> for smc call
>> - updated collect_agents function. Set agent_id parameter as optional
>> in scmi-secondary-agents device-tree property
>> - introduce "#scmi-secondary-agents-cells" parameter to set if
>> agent_id was provided
>> - reanme xen,scmi-secondary-agents property to scmi-secondary-agents
>> - move memcpu_toio/fromio for the generic place
>> - update Xen to get management channel from /chosen/xen,config node
>> - get hypervisor channnel from node instead of using hardcoded
>> - update handling scmi and shmem nodes for the domain
>> - Set multi-agent driver to support only Arm64
>> - rework multi-agent driver to leave Host Device-tree unmodified
>>
>> Changes in v4:
>> - fix SPDX-License
>> - rename DEVICE_ARM_SCI DT device class to FIRMWARE_DEVICE
>> - move XEN_DOMCTL_assign_device code in separate patch
>> - Add documentation for SCI SCMI drivers
>> - xl.cfg doc
>> - fix comments from Stefano Stabellini
>> - fix toolstack code as sugested by Anthony PERARD
>>    - use MATCH_OPTION()
>>    - move arm_sci struct and cfg params in "arch_arm"
>> - add SCMI passthrough for dom0less case
>> - toolstack comments from Anthony PERARD
>> - added dom0less support
>> - added doc for "xen,scmi-secondary-agents"
>>
>> Grygorii Strashko (5):
>>    xen/arm: scmi-smc: update to be used under sci subsystem
>>    xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
>>    docs: arm: add docs for SCMI over SMC calls forwarding driver
>>    xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
>>    docs: arm: add SCI SCMI SMC multi-agent driver docs
>>
>> Oleksii Moisieiev (5):
>>    xen/arm: add generic SCI subsystem
>>    drivers: iommu: change error code when iommu is disabled
>>    xen: arm: smccc: add INVALID_PARAMETER error code
>>    lib/arm: Add I/O memory copy helpers
>>    xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
>>
>>   MAINTAINERS                                   |  10 +
>>   SUPPORT.md                                    |  11 +
>>   .../arm/firmware/arm-scmi.rst                 | 516 +++++++++++
>>   docs/hypervisor-guide/arm/index.rst           |   9 +
>>   docs/hypervisor-guide/index.rst               |   1 +
>>   docs/man/xl.cfg.5.pod.in                      |  47 +
>>   docs/misc/arm/device-tree/booting.txt         | 103 +++
>>   docs/misc/xen-command-line.pandoc             |  18 +
>>   tools/include/libxl.h                         |   5 +
>>   tools/libs/light/libxl_arm.c                  |  18 +
>>   tools/libs/light/libxl_types.idl              |  12 +
>>   tools/xl/xl_parse.c                           |  48 ++
>>   xen/arch/arm/device.c                         |   5 +
>>   xen/arch/arm/dom0less-build.c                 |  51 ++
>>   xen/arch/arm/domain.c                         |  12 +-
>>   xen/arch/arm/domain_build.c                   |  11 +-
>>   xen/arch/arm/firmware/Kconfig                 |  37 +-
>>   xen/arch/arm/firmware/Makefile                |   2 +
>>   xen/arch/arm/firmware/sci.c                   | 189 +++++
>>   xen/arch/arm/firmware/scmi-proto.h            | 164 ++++
>>   xen/arch/arm/firmware/scmi-shmem.c            | 112 +++
>>   xen/arch/arm/firmware/scmi-shmem.h            |  45 +
>>   xen/arch/arm/firmware/scmi-smc-multiagent.c   | 803 ++++++++++++++++++
>>   xen/arch/arm/firmware/scmi-smc.c              | 191 ++++-
>>   xen/arch/arm/include/asm/domain.h             |   5 +
>>   xen/arch/arm/include/asm/firmware/sci.h       | 214 +++++
>>   xen/arch/arm/include/asm/firmware/scmi-smc.h  |  41 -
>>   xen/arch/arm/include/asm/smccc.h              |   1 +
>>   xen/arch/arm/vsmc.c                           |   4 +-
>>   xen/common/device-tree/dom0less-build.c       |   4 +
>>   xen/common/domctl.c                           |  19 +
>>   xen/drivers/passthrough/device_tree.c         |   6 +
>>   xen/drivers/passthrough/iommu.c               |   2 +-
>>   xen/include/asm-generic/device.h              |   1 +
>>   xen/include/asm-generic/dom0less-build.h      |   9 +
>>   xen/include/public/arch-arm.h                 |   8 +
>>   xen/include/xen/lib/arm/io.h                  |  15 +
>>   xen/lib/Makefile                              |   1 +
>>   xen/lib/arm/Makefile                          |   1 +
>>   xen/lib/arm/io.c                              |  80 ++
>>   40 files changed, 2744 insertions(+), 87 deletions(-)
>>   create mode 100644 docs/hypervisor-guide/arm/firmware/arm-scmi.rst
>>   create mode 100644 docs/hypervisor-guide/arm/index.rst
>>   create mode 100644 xen/arch/arm/firmware/sci.c
>>   create mode 100644 xen/arch/arm/firmware/scmi-proto.h
>>   create mode 100644 xen/arch/arm/firmware/scmi-shmem.c
>>   create mode 100644 xen/arch/arm/firmware/scmi-shmem.h
>>   create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c
>>   create mode 100644 xen/arch/arm/include/asm/firmware/sci.h
>>   delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
>>   create mode 100644 xen/include/xen/lib/arm/io.h
>>   create mode 100644 xen/lib/arm/Makefile
>>   create mode 100644 xen/lib/arm/io.c
>>
>> --
>> 2.34.1
>>

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support
  2025-08-27  9:10   ` Oleksii Moisieiev
@ 2025-08-27 15:37     ` Stefano Stabellini
  0 siblings, 0 replies; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-27 15:37 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Stefano Stabellini, xen-devel@lists.xenproject.org, Andrew Cooper,
	Anthony PERARD, Bertrand Marquis, Jan Beulich, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Volodymyr Babchuk, Grygorii Strashko

I completed the review of the patch series but as you could see from the
comments, the first few patches are far better along than the last two.

The current deadline is on Friday this week. I am happy to review this
series as promptly as I can but I am not sure we'll be able to complete
the last two patches.

Cheers,

Stefano


On Wed, 27 Aug 2025, Oleksii Moisieiev wrote:
> Hi Stefano,
> 
> Our use-case imply using scmi-smc-multiagent to be able to split scmi
> between the domains,
> so we would like to apply all patch series in the release.
> 
> On 23/08/2025 03:34, Stefano Stabellini wrote:
> > I think it should be feasible to commit at least patches 1-4 in time for
> > the release
> >
> > On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> >> Inroducing V4 RFC patch series  on top of the Xen version 4.20-rc2
> >> which includes implementation of the SCI SCMI SMC multi-agent support.
> >>
> >> Patch 1 "xen/arm: add generic SCI subsystem"
> >> - rebased and refactored
> >> - introduced DEVICE_ARM_SCI DT device class and used for SCI drivers probing
> >> instead of custom,
> >>    linker sections based implementation.
> >> - added SCI API for Dom0 DT handling, instead of manipulating with ARM arch
> >> dom0 code directly.
> >> - RFC changes in XEN_DOMCTL_assign_device OP processing
> >> - Introduce arch_handle_passthrough_prop call to handle arm specific
> >> nodes
> >>
> >> Patch 2 "xen/arm: scmi-smc: update to be used under sci subsystem"
> >> - update driver introduced by commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI
> >> over SMC calls
> >> handling layer") be used under sci subsystem.
> >> - no functional changes in general
> >>
> >> Patch 3 "xen/arm: scmi-smc: passthrough SCMI SMC to guest domain
> >> This is new change which allows passthrough SCMI SMC, single agent interface to
> >> guest domain
> >> cover use case "thin Dom0 with guest domain, which serves as Driver domain".
> >> See patch commit message for full description.
> >>
> >> Patch 4 - docs: arm: add docs for SCMI over SMC calls forwarding
> >> driver
> >> - add documentation section for Simple Arm SCMI over SMC/HVC calls
> >> forwarding driver.
> >>
> >> Patch 6 - xen/domctl: extend XEN_DOMCTL_assign_device to handle not
> >> only iommu
> >> - add chainged handling of assigned DT devices to support
> >> access-controller functionality through SCI framework.
> >> Change was done in two parts:
> >>   - update iommu_do_dt_domctl() to check for dt_device_is_protected()
> >>   and not fail if DT device is not protected by IOMMU
> >>   -add chained call to sci_do_domctl() to do_domctl()
> >>
> >> Patch 9 - xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
> >> - added "scmi-secondary-agents" and "#scmi-secondary-agent-cells"
> >>    property to "xen,config" node in "chosen" to inform SCI SCMI
> >>    multi-agent driver about available agents and their
> >>    configuration. It defines <agent_id> to <smc-id,scmi_shm> map.
> >>    This option is Xen specific as Xen is the only one entry in the
> >>    system which need to know about SCMI multi-agent support and configuration.
> >> - each guest using SCMI should be configured with SCMI agent_id, so SCMI
> >>    FW can implement Agent-specific permission policy.
> >>    -- dom0: dom0_scmi_agent_id=<agent_id> in Xen command line option
> >>    -- toolstack: arm_sci = "type=scmi_smc_multiagent,agent_id=<agent_id>"
> >>    -- dom0less: "xen,sci_type", "xen,sci_agent_id" properties in
> >> "xen,domain" nodes.
> >> - factored out SCMI generic definitions (re-usable)
> >> - factored out SCMI shmem code (re-usable)
> >> - the SCMI passthrough configuration for guest domains is similar to any other
> >> HW passthrough cfg.
> >>
> >> Patch 10 - docs: arm: add SCI SCMI SMC multi-agent driver docs
> >> - add SCI SCMI SMC multi-agent driver documentation.
> >>
> >> Add separate SCMI DT node for Xen management agent under "xen,config"
> >> node under chosen.
> >>
> >> All Xen-specific configuration provided under "/chosen" node. This
> >> approach allows to isolate modifications to Host DT only under
> >> "/chosen" node.
> >>
> >> This approach provides the following device tree (DT)
> >> parameters (placed under xen,config node):
> >>
> >> - "scmi-secondary-agents": A Xen-specific parameter under the
> >>    "/chosen" node, which describes the SCMI agent configuration for
> >>    the domains.
> >> - the SCMI configuration for Xen (privileged agent) and the shared
> >>    memory configuration for all agents are provided under the "/chosen"
> >>    node and are used strictly by Xen for its initial configuration.
> >> - the scmi_shm and SCMI configuration for Dom0 are placed in the
> >>    "/firmware/scmi" node so that they can be moved to Dom0 without
> >>    any changes.
> >>
> >> This configuration allows the use of Xen-specific nodes to provide
> >> information strictly needed by Xen while using the default SCMI
> >> configuration for Dom0 and other domains. As a result, no additional
> >> bindings need to be introduced to the device tree.
> >> This simplifies the Xen SCMI multi-agent configuration and utilizes
> >> generic device tree bindings for the domains.
> >>
> >> NOTE: Haven't added RB tags for patch 1 and 2 because rebase and some
> >> minor changes were done.
> >>
> >> Code can be found at:
> >> https://github.com/oleksiimoisieiev/xen/tree/scmi_upstrv5
> >>
> >> [1] RFC v2:
> >> http://patchwork.kernel.org/project/xen-devel/cover/cover.1644341635.git.oleksii_moisieiev@epam.com/
> >> [2] RFC v3:
> >> https://patchwork.kernel.org/project/xen-devel/patch/20250311111618.1850927-1-grygorii_strashko@epam.com
> >> SCMI spec:
> >> https://developer.arm.com/documentation/den0056/e/?lang=en
> >>
> >> SCMI bindings:
> >> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
> >> https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml
> >>
> >> Reference EL3 FW:
> >> RPI5: https://github.com/xen-troops/arm-trusted-firmware/commits/rpi5_dev/
> >> Renesas v4h:
> >> https://github.com/GrygiriiS/arm-trusted-firmware/commits/rcar_gen4_v2.7_v4x-scmi_upd/
> >>
> >> base-commit: dbe60f244c (Update Xen to 4.21, 2025-02-21)
> >>
> >> Changes in v5:
> >> - update Maintainers file. Set role as a Reviewer
> >> - rebased on the latest master branch
> >> - Introduce arch_handle_passthrough_prop call to handle arm specific nodes
> >> - rename dom0_scmi_smc_passthrough to scmi_smc_passthrough
> >> - rename dom0_scmi_smc_passthrough in documentation
> >> - set error code to -ENXIO when iommu is disabled
> >> - return -EINVAL if mediator without assign_dt_device was provided
> >> - invert return code check for iommu_do_domctl in
> >> XEN_DOMCTL_assign_device domctl processing to make cleaner code
> >> - change -ENOTSUPP error code to -ENXIO in sci_do_domctl
> >> - handle -ENXIO return comde of iommu_do_domctl
> >> - leave !dt_device_is_protected check in iommu_do_dt_domctl to make
> >> code work the same way it's done in "handle_device" call while
> >> creating hwdom(dom0) and "handle_passthrough_prop" call for dom0less
> >> creation
> >> - drop return check from sci_assign_dt_device call as not needed
> >> - do not return EINVAL when addign_dt_device is not set. That is
> >> because this callback is optional and not implemented in single-agent driver
> >> - move memcpy_toio/fromio to the generic place
> >> - fix device-tree example format in booting.txt, added ";" after "}".
> >> - update define in scmi-proto.h
> >> - update define in scmi-shmem.h file
> >> - scmi_assign_device - do not ignore -EOPNOTSUPP return
> >> code of the do_smc_xfer
> >> - remove overwriting agent_channel->agent_id after
> >> SCMI_BASE_DISCOVER_AGENT call
> >> - add multi-agent files to the MAINTAINERS
> >> - add SCMI multi-agent description to the SUPPORT.md
> >> - handle ARM_SMCCC_INVALID_PARAMETER return code and return -EINVAL
> >> for smc call
> >> - updated collect_agents function. Set agent_id parameter as optional
> >> in scmi-secondary-agents device-tree property
> >> - introduce "#scmi-secondary-agents-cells" parameter to set if
> >> agent_id was provided
> >> - reanme xen,scmi-secondary-agents property to scmi-secondary-agents
> >> - move memcpu_toio/fromio for the generic place
> >> - update Xen to get management channel from /chosen/xen,config node
> >> - get hypervisor channnel from node instead of using hardcoded
> >> - update handling scmi and shmem nodes for the domain
> >> - Set multi-agent driver to support only Arm64
> >> - rework multi-agent driver to leave Host Device-tree unmodified
> >>
> >> Changes in v4:
> >> - fix SPDX-License
> >> - rename DEVICE_ARM_SCI DT device class to FIRMWARE_DEVICE
> >> - move XEN_DOMCTL_assign_device code in separate patch
> >> - Add documentation for SCI SCMI drivers
> >> - xl.cfg doc
> >> - fix comments from Stefano Stabellini
> >> - fix toolstack code as sugested by Anthony PERARD
> >>    - use MATCH_OPTION()
> >>    - move arm_sci struct and cfg params in "arch_arm"
> >> - add SCMI passthrough for dom0less case
> >> - toolstack comments from Anthony PERARD
> >> - added dom0less support
> >> - added doc for "xen,scmi-secondary-agents"
> >>
> >> Grygorii Strashko (5):
> >>    xen/arm: scmi-smc: update to be used under sci subsystem
> >>    xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent
> >>    docs: arm: add docs for SCMI over SMC calls forwarding driver
> >>    xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
> >>    docs: arm: add SCI SCMI SMC multi-agent driver docs
> >>
> >> Oleksii Moisieiev (5):
> >>    xen/arm: add generic SCI subsystem
> >>    drivers: iommu: change error code when iommu is disabled
> >>    xen: arm: smccc: add INVALID_PARAMETER error code
> >>    lib/arm: Add I/O memory copy helpers
> >>    xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
> >>
> >>   MAINTAINERS                                   |  10 +
> >>   SUPPORT.md                                    |  11 +
> >>   .../arm/firmware/arm-scmi.rst                 | 516 +++++++++++
> >>   docs/hypervisor-guide/arm/index.rst           |   9 +
> >>   docs/hypervisor-guide/index.rst               |   1 +
> >>   docs/man/xl.cfg.5.pod.in                      |  47 +
> >>   docs/misc/arm/device-tree/booting.txt         | 103 +++
> >>   docs/misc/xen-command-line.pandoc             |  18 +
> >>   tools/include/libxl.h                         |   5 +
> >>   tools/libs/light/libxl_arm.c                  |  18 +
> >>   tools/libs/light/libxl_types.idl              |  12 +
> >>   tools/xl/xl_parse.c                           |  48 ++
> >>   xen/arch/arm/device.c                         |   5 +
> >>   xen/arch/arm/dom0less-build.c                 |  51 ++
> >>   xen/arch/arm/domain.c                         |  12 +-
> >>   xen/arch/arm/domain_build.c                   |  11 +-
> >>   xen/arch/arm/firmware/Kconfig                 |  37 +-
> >>   xen/arch/arm/firmware/Makefile                |   2 +
> >>   xen/arch/arm/firmware/sci.c                   | 189 +++++
> >>   xen/arch/arm/firmware/scmi-proto.h            | 164 ++++
> >>   xen/arch/arm/firmware/scmi-shmem.c            | 112 +++
> >>   xen/arch/arm/firmware/scmi-shmem.h            |  45 +
> >>   xen/arch/arm/firmware/scmi-smc-multiagent.c   | 803 ++++++++++++++++++
> >>   xen/arch/arm/firmware/scmi-smc.c              | 191 ++++-
> >>   xen/arch/arm/include/asm/domain.h             |   5 +
> >>   xen/arch/arm/include/asm/firmware/sci.h       | 214 +++++
> >>   xen/arch/arm/include/asm/firmware/scmi-smc.h  |  41 -
> >>   xen/arch/arm/include/asm/smccc.h              |   1 +
> >>   xen/arch/arm/vsmc.c                           |   4 +-
> >>   xen/common/device-tree/dom0less-build.c       |   4 +
> >>   xen/common/domctl.c                           |  19 +
> >>   xen/drivers/passthrough/device_tree.c         |   6 +
> >>   xen/drivers/passthrough/iommu.c               |   2 +-
> >>   xen/include/asm-generic/device.h              |   1 +
> >>   xen/include/asm-generic/dom0less-build.h      |   9 +
> >>   xen/include/public/arch-arm.h                 |   8 +
> >>   xen/include/xen/lib/arm/io.h                  |  15 +
> >>   xen/lib/Makefile                              |   1 +
> >>   xen/lib/arm/Makefile                          |   1 +
> >>   xen/lib/arm/io.c                              |  80 ++
> >>   40 files changed, 2744 insertions(+), 87 deletions(-)
> >>   create mode 100644 docs/hypervisor-guide/arm/firmware/arm-scmi.rst
> >>   create mode 100644 docs/hypervisor-guide/arm/index.rst
> >>   create mode 100644 xen/arch/arm/firmware/sci.c
> >>   create mode 100644 xen/arch/arm/firmware/scmi-proto.h
> >>   create mode 100644 xen/arch/arm/firmware/scmi-shmem.c
> >>   create mode 100644 xen/arch/arm/firmware/scmi-shmem.h
> >>   create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c
> >>   create mode 100644 xen/arch/arm/include/asm/firmware/sci.h
> >>   delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
> >>   create mode 100644 xen/include/xen/lib/arm/io.h
> >>   create mode 100644 xen/lib/arm/Makefile
> >>   create mode 100644 xen/lib/arm/io.c
> >>
> >> --
> >> 2.34.1
> >>
> 


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver
  2025-07-22 11:41 ` [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Oleksii Moisieiev
                     ` (2 preceding siblings ...)
  2025-08-26  0:37   ` Stefano Stabellini
@ 2025-08-27 19:35   ` Oleksandr Tyshchenko
  3 siblings, 0 replies; 37+ messages in thread
From: Oleksandr Tyshchenko @ 2025-08-27 19:35 UTC (permalink / raw)
  To: Oleksii Moisieiev, xen-devel@lists.xenproject.org
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Jan Beulich,
	Juergen Gross, Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko



On 22.07.25 14:41, Oleksii Moisieiev wrote:

Hello Oleksii

[I will try to not repeat comments provided by Stefano in separate letter]


> This patch introduces SCI driver to support for ARM EL3 Trusted Firmware-A
> (TF-A) which provides SCMI interface with multi-agnet support, as shown
> below.
> 
>    +-----------------------------------------+
>    |                                         |
>    | EL3 TF-A SCMI                           |
>    +-------+--+-------+--+-------+--+-------++
>    |shmem1 |  |shmem0 |  |shmem2 |  |shmemX |
>    +-----+-+  +---+---+  +--+----+  +---+---+
> smc-id1 |        |         |           |
> agent1  |        |         |           |
>    +-----v--------+---------+-----------+----+
>    |              |         |           |    |
>    |              |         |           |    |
>    +--------------+---------+-----------+----+
>           smc-id0 |  smc-id2|    smc-idX|
>           agent0  |  agent2 |    agentX |
>                   |         |           |
>              +----v---+  +--v-----+  +--v-----+
>              |        |  |        |  |        |
>              | Dom0   |  | Dom1   |  | DomX   |
>              |        |  |        |  |        |
>              |        |  |        |  |        |
>              +--------+  +--------+  +--------+
> 
> The EL3 SCMI multi-agent firmware expected to provide SCMI SMC/HVC shared
> memory transport for every Agent in the system.
> 
> The SCMI Agent transport channel defined by pair:
>   - smc-id: SMC/HVC id used for Doorbell
>   - shmem: shared memory for messages transfer, Xen page
>   aligned. Shared memort is mapped with the following flags:
>   MT_DEVICE_nGnRE.
> 
> The follwoing SCMI Agents expected to be defined by SCMI FW to enable SCMI
> multi-agent functionality under Xen:
> - Xen manegement agent: trusted agents that accesses to the Base Protocol
> commands to configure agent specific permissions
> - OSPM VM agents: non-trusted agent, one for each Guest domain which is
>    allowed direct HW access. At least one OSPM VM agent has to be provided
>    by FW if HW is handled only by Dom0 or Driver Domain.
> 
> The EL3 SCMI FW expected to implement following Base protocol messages:
> - BASE_DISCOVER_AGENT (optional if agent_id was provided)
> - BASE_RESET_AGENT_CONFIGURATION (optional)
> - BASE_SET_DEVICE_PERMISSIONS (optional)
> 
> The SCI SCMI SMC multi-agent driver implements following
> functionality:
> - The driver is initialized based on the ``xen,config`` node under ``chosen``
>    (only one SCMI interface is supported), which describes the Xen management
>    agent SCMI interface.
> 
> scmi_shm_1: sram@47ff1000 {
>            compatible = "arm,scmi-shmem";
>            reg = <0x0 0x47ff1000 0x0 0x1000>;
> };
> scmi_xen: scmi {
>          compatible = "arm,scmi-smc";
>          arm,smc-id = <0x82000003>; <--- Xen manegement agent smc-id
>          #address-cells = < 1>;
>          #size-cells = < 0>;
>          #access-controller-cells = < 1>;
>          shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
> };
> 
> - The driver obtains Xen specific SCMI Agent's configuration from the Host DT, probes Agents and
>    builds SCMI Agents list. The Agents configuration is taken from "scmi-secondary-agents"
>    property where first item is "arm,smc-id", second - "arm,scmi-shmem" phandle and third is
>    optional "agent_id":
> 
> chosen {
>    ranges;
>    xen,config {
>      ranges;
>      scmi-secondary-agents = <
>                    0x82000003 &scmi_shm_0 0
>                    0x82000004 &scmi_shm_2 2
>                    0x82000005 &scmi_shm_3 3
>                    0x82000006 &scmi_shm_4 4>;
>      #scmi-secondary-agents-cells = <3>; <--- optional, default 3
> 
>      scmi_shm_0 : sram@47ff0000 {
>          compatible = "arm,scmi-shmem";
>          reg = <0x0 0x47ff0000 0x0 0x1000>;
>      };
> 
>      scmi_shm_2: sram@47ff2000 {
>              compatible = "arm,scmi-shmem";
>              reg = <0x0 0x47ff2000 0x0 0x1000>;
>      };
>      scmi_shm_3: sram@47ff3000 {
>              compatible = "arm,scmi-shmem";
>              reg = <0x0 0x47ff3000 0x0 0x1000>;
>      };
>      scmi_shm_4: sram@47ff4000 {
>              compatible = "arm,scmi-shmem";
>              reg = <0x0 0x47ff4000 0x0 0x1000>;
>      };
> 
>      // Xen SCMI management channel
>      scmi_shm_1: sram@47ff1000 {
>              compatible = "arm,scmi-shmem";
>              reg = <0x0 0x47ff1000 0x0 0x1000>;
>      };
> 
>      scmi_xen: scmi {
>          compatible = "arm,scmi-smc";
>          arm,smc-id = <0x82000002>; <--- Xen manegement agent smc-id
>          #address-cells = < 1>;
>          #size-cells = < 0>;
>          #access-controller-cells = < 1>;
>          shmem = <&scmi_shm_1>; <--- Xen manegement agent shmem
>      };
>    };
> };
> 
> /{
>      // Host SCMI OSPM channel - provided to the Dom0 as is if SCMI enabled for it
>      scmi_shm: sram@47ff0000 {
>              compatible = "arm,scmi-shmem";
>              reg = <0x0 0x47ff0000 0x0 0x1000>;
>      };
> 
>      firmware {
>          scmi: scmi {
>              compatible = "arm,scmi-smc";
>              arm,smc-id = <0x82000002>; <--- Host OSPM agent smc-id
>              #address-cells = < 1>;
>              #size-cells = < 0>;
>              shmem = <&scmi_shm>; <--- Host OSPM agent shmem
> 
>              protocol@X{
>              };
>          };
>      };
> };
> 
> This approach allows defining multiple SCMI Agents by adding Xen-specific properties under
> the ``/chosen`` node to the Host Device Tree, leaving the main part unchanged. The Host DT
> SCMI channel will be passed to Dom0.
> 
> The Xen management agent is described as a ``scmi_xen`` node under the ``/chosen`` node, which
> is used by Xen to control other SCMI Agents in the system.
> 
> All secondary agents' configurations are provided in the ``scmi-secondary-agents`` property with
> an optional ``agent_id`` field.
> 
> The ``agent_id`` from the ``scmi-secondary-agents`` property is used to identify the agent in the
> system and can be omitted by setting ``#scmi-secondary-agents-cells = <2>``, so the Secondary
> Agents configuration will look like this:
> 
> chosen {
>    xen,config {
>      scmi-secondary-agents = <
>                    0x82000003 &scmi_shm_0
>                    0x82000004 &scmi_shm_2
>                    0x82000005 &scmi_shm_3
>                    0x82000006 &scmi_shm_4>;
>      #scmi-secondary-agents-cells = <2>;
>    };
> }
> 
> In this case, Xen will use the ``SCMI_BASE_DISCOVER_AGENT`` call to discover the ``agent_id``
> for each secondary agent. Providing the ``agent_id`` in the ``scmi-secondary-agents`` property
> allows skipping the discovery call, which is useful when the secondary agent's shared memory is
> not accessible by Xen or when boot time is important because it allows skipping the agent
> discovery procedure.
> 
>    Note that Xen is the only one entry in the system which need to know
>    about SCMI multi-agent support.
> 
> - It implements the SCI subsystem interface required for configuring and
> enabling SCMI functionality for Dom0/hwdom and Guest domains. To enable
> SCMI functionality for domain it has to be configured with unique supported
> SCMI Agent_id and use corresponding SCMI SMC/HVC shared memory transport
> [smc-id, shmem] defined for this SCMI Agent_id.
> - Once Xen domain is configured it can communicate with EL3 SCMI FW:
>    -- zero-copy, the guest domain puts SCMI message in shmem;
>    -- the guest triggers SMC/HVC exception with smc-id (doorbell);
>    -- the Xen driver catches exception, do checks and synchronously forwards
>    it to EL3 FW.
> - the Xen driver sends BASE_RESET_AGENT_CONFIGURATION message to Xen
>    management agent channel on domain destroy event. This allows to reset
>    resources used by domain and so implement use-case like domain reboot.
> 
> Dom0 Enable SCMI SMC:
>   - pass dom0_scmi_agent_id=<agent_id> in Xen command line. if not provided
>     SCMI will be disabled for Dom0 and all SCMI nodes removed from Dom0 DT.
>     The driver updates Dom0 DT SCMI node "arm,smc-id" value and fix up shmem
>     node according to assigned agent_id.
> 
> Guest domains enable SCMI SMC:
>   - xl.cfg: add configuration option as below
> 
>     arm_sci = "type=scmi_smc_multiagent,agent_id=2"
> 
>   - xl.cfg: enable access to the "arm,scmi-shmem" which should correspond assigned agent_id for
>     the domain, for example:
> 
> iomem = [
>      "47ff2,1@22001",
> ]
> 
>   - DT: add SCMI nodes to the Driver domain partial device tree as in the
>   below example. The "arm,smc-id" should correspond assigned agent_id for the domain:
> 
> passthrough {
>     scmi_shm_0: sram@22001000 {
>         compatible = "arm,scmi-shmem";
>         reg = <0x0 0x22001000 0x0 0x1000>;
>     };
> 
>     firmware {
>          compatible = "simple-bus";
>              scmi: scmi {
>                  compatible = "arm,scmi-smc";
>                  arm,smc-id = <0x82000004>;
>                  shmem = <&scmi_shm_0>;
>                  ...
>              }
>      }
> }
> 
> SCMI "4.2.1.1 Device specific access control"
> 
> The XEN SCI SCMI SMC multi-agent driver performs "access-controller" provider function
> in case EL3 SCMI FW implements SCMI "4.2.1.1 Device specific access control" and provides the
> BASE_SET_DEVICE_PERMISSIONS command to configure the devices that an agents have access to.
> The DT SCMI node should "#access-controller-cells=<1>" property and DT devices should be bound
> to the Xen SCMI.
> 
> &i2c1 {
> 	access-controllers = <&scmi 0>;
> };
> 
> The Dom0 and dom0less domains DT devices will be processed automatically through
> sci_assign_dt_device() call, but to assign SCMI devices from toolstack the xl.cfg:"dtdev" property
> shell be used:
> 
> dtdev = [
>      "/soc/i2c@e6508000",
> ]
> 
> xl.cfg:dtdev will contain all nodes which are under SCMI management (not only those which are behind IOMMU).
> 
> [1] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/firmware/arm,scmi.yaml
> [2] https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/access-controllers/access-controllers.yaml
> 
> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
> ---
> 
> Changes in v5:
> - fix device-tree example format in booting.txt, added ";" after "}".
> - update define in scmi-proto.h
> - update define in scmi-shmem.h file
> - scmi_assign_device - do not ignore -EOPNOTSUPP return
> code of the do_smc_xfer
> - remove overwriting agent_channel->agent_id after
> SCMI_BASE_DISCOVER_AGENT call
> - add multi-agent files to the MAINTAINERS
> - add SCMI multi-agent description to the SUPPORT.md
> - handle ARM_SMCCC_INVALID_PARAMETER return code and return -EINVAL
> for smc call
> - updated collect_agents function. Set agent_id parameter as optional
> in scmi-secondary-agents device-tree property
> - introduce "#scmi-secondary-agents-cells" parameter to set if
> agent_id was provided
> - reanme xen,scmi-secondary-agents property to scmi-secondary-agents
> - move memcpu_toio/fromio for the generic place
> - update Xen to get management channel from /chosen/xen,config node
> - get hypervisor channnel from node instead of using hardcoded
> - update handling scmi and shmem nodes for the domain
> - Set multi-agent driver to support only Arm64
> 
> Changes in v4:
> - toolstack comments from Anthony PERARD
> - added dom0less support
> - added doc for "xen,scmi-secondary-agents"
> 
>   MAINTAINERS                                 |   4 +
>   SUPPORT.md                                  |  11 +
>   docs/man/xl.cfg.5.pod.in                    |  13 +
>   docs/misc/arm/device-tree/booting.txt       |  88 +++
>   docs/misc/xen-command-line.pandoc           |   9 +
>   tools/libs/light/libxl_arm.c                |   4 +
>   tools/libs/light/libxl_types.idl            |   4 +-
>   tools/xl/xl_parse.c                         |  12 +
>   xen/arch/arm/dom0less-build.c               |  11 +
>   xen/arch/arm/domain_build.c                 |   3 +-
>   xen/arch/arm/firmware/Kconfig               |  12 +
>   xen/arch/arm/firmware/Makefile              |   1 +
>   xen/arch/arm/firmware/scmi-proto.h          | 164 ++++
>   xen/arch/arm/firmware/scmi-shmem.c          | 112 +++
>   xen/arch/arm/firmware/scmi-shmem.h          |  45 ++
>   xen/arch/arm/firmware/scmi-smc-multiagent.c | 803 ++++++++++++++++++++
>   xen/include/public/arch-arm.h               |   3 +
>   17 files changed, 1297 insertions(+), 2 deletions(-)
>   create mode 100644 xen/arch/arm/firmware/scmi-proto.h
>   create mode 100644 xen/arch/arm/firmware/scmi-shmem.c
>   create mode 100644 xen/arch/arm/firmware/scmi-shmem.h
>   create mode 100644 xen/arch/arm/firmware/scmi-smc-multiagent.c
> 

[snip]

> diff --git a/tools/xl/xl_parse.c b/tools/xl/xl_parse.c
> index 68d2ebeb9f..4c05b20c06 100644
> --- a/tools/xl/xl_parse.c
> +++ b/tools/xl/xl_parse.c
> @@ -1306,6 +1306,18 @@ static int parse_arm_sci_config(XLU_Config *cfg, libxl_arm_sci *arm_sci,
>               }
>           }
>   
> +        if (MATCH_OPTION("agent_id", ptr, oparg)) {
> +            unsigned long val = parse_ulong(oparg);
> +
> +            if (!val || val > 255) {
> +                fprintf(stderr, "An invalid ARM_SCI agent_id specified (%lu). Valid range [1..255]\n",
> +                        val);
> +                ret = ERROR_INVAL;
> +                goto parse_error;
> +            }
> +            arm_sci->agent_id = val;
> +        }
> +
>           ptr = strtok(NULL, ",");
>       }
>   
> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
> index d28143f98b..6ca17b0ce6 100644
> --- a/xen/arch/arm/dom0less-build.c
> +++ b/xen/arch/arm/dom0less-build.c
> @@ -299,6 +299,17 @@ int __init domu_dt_sci_parse(struct dt_device_node *node,
>           d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
>       else if ( !strcmp(sci_type, "scmi_smc") )
>           d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC;
> +    else if ( !strcmp(sci_type, "scmi_smc_multiagent") )
> +    {
> +        uint32_t agent_id = 0;
> +
> +        if ( !dt_property_read_u32(node, "xen,sci_agent_id", &agent_id) ||
> +             !agent_id )
> +            return -EINVAL;

In toolstack you keep the check for agent_id to be in the range of 1 to 
255. Why do not check here as well?


> +
> +        d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC_MA;
> +        d_cfg->arch.arm_sci_agent_id = agent_id;
> +    }
>       else
>       {
>           printk(XENLOG_ERR "xen,sci_type in not valid (%s) for domain %s\n",


[snip]

> diff --git a/xen/arch/arm/firmware/scmi-proto.h b/xen/arch/arm/firmware/scmi-proto.h
> new file mode 100644
> index 0000000000..e290d6630d
> --- /dev/null
> +++ b/xen/arch/arm/firmware/scmi-proto.h
> @@ -0,0 +1,164 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Arm System Control and Management Interface definitions
> + * Version 3.0 (DEN0056C)
> + *
> + * Copyright (c) 2024 EPAM Systems

2025


[snip]


> diff --git a/xen/arch/arm/firmware/scmi-shmem.c b/xen/arch/arm/firmware/scmi-shmem.c
> new file mode 100644
> index 0000000000..8fc8ca356b
> --- /dev/null
> +++ b/xen/arch/arm/firmware/scmi-shmem.c
> @@ -0,0 +1,112 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * SCI SCMI multi-agent driver, using SMC/HVC shmem as transport.

NIT: Is this really a multi-agent driver?

(scmi-smc-multiagent.c has exact the same description).

> + *
> + * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> + * Copyright (c) 2025 EPAM Systems
> + */
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +#include <asm/io.h>
> +#include <xen/err.h>
> +#include <xen/lib/arm/io.h>

NIT: AFAIK, "asm" should be included after "xen"

> +
> +#include "scmi-proto.h"
> +#include "scmi-shmem.h"
> +

[snip]

> +
> +static struct scmi_channel *smc_create_channel(uint32_t agent_id,
> +                                               uint32_t func_id, uint64_t addr)
> +{
> +    struct scmi_channel *channel;
> +
> +    channel = get_channel_by_id(agent_id);
> +    if ( channel )
> +        return ERR_PTR(EEXIST);

missing "-" before EEXIST


> +
> +    channel = xmalloc(struct scmi_channel);
> +    if ( !channel )
> +        return ERR_PTR(ENOMEM);

missing "-" before ENOMEM

> +
> +    spin_lock_init(&channel->lock);
> +    channel->agent_id = agent_id;
> +    channel->func_id = func_id;
> +    channel->domain_id = DOMID_INVALID;
> +    channel->shmem = NULL;
> +    channel->paddr = addr;
> +    list_add_tail(&channel->list, &scmi_data.channel_list);
> +    return channel;
> +}
> +

[snip]

> +
> +static int scmi_dt_hyp_channel_read(struct dt_device_node *scmi_node, struct scmi_data *scmi_data,
> +                                    u64 *addr)

Missing __init?

> +{
> +    int ret;
> +    u64 size;
> +
> +    if ( !dt_property_read_u32(scmi_node, "arm,smc-id", &scmi_data->func_id) )
> +    {
> +        printk(XENLOG_ERR "scmi: unable to read smc-id from DT\n");
> +        return -ENOENT;
> +    }
> +
> +    ret = scmi_dt_read_hyp_channel_addr(scmi_node, addr, &size);
> +    if ( IS_ERR_VALUE(ret) )
> +        return -ENOENT;
> +
> +    if ( !IS_ALIGNED(size, SCMI_SHMEM_MAPPED_SIZE) )
> +    {
> +        printk(XENLOG_ERR "scmi: shmem memory is not aligned\n");
> +        return -EINVAL;
> +    }
> +
> +    return 0;
> +}
> +
> +static __init int scmi_probe(struct dt_device_node *scmi_node, const void *data)
> +{
> +    u64 addr;
> +    int ret;
> +    struct scmi_channel *channel;
> +    int n_agents;

unsigned int please if n_agents cannot be negative

> +    scmi_msg_header_t hdr;
> +    struct scmi_msg_base_attributes_p2a rx;
> +
> +    ASSERT(scmi_node != NULL);
> +
> +    INIT_LIST_HEAD(&scmi_data.channel_list);
> +    spin_lock_init(&scmi_data.channel_list_lock);
> +
> +    if ( !acpi_disabled )
> +    {
> +        printk(XENLOG_WARNING "scmi: is not supported when using ACPI\n");
> +        return -EINVAL;
> +    }
> +
> +    ret = scmi_check_smccc_ver();
> +    if ( ret )
> +        return ret;
> +
> +    ret = scmi_dt_hyp_channel_read(scmi_node, &scmi_data, &addr);
> +    if ( ret )
> +        return ret;
> +
> +    scmi_data.dt_dev = scmi_node;
> +
> +    channel = smc_create_channel(SCMI_BASE_AGENT_ID_OWN, scmi_data.func_id, addr);
> +    if ( IS_ERR(channel) )
> +        goto out;
> +
> +    /* Request agent id for Xen management channel  */
> +    ret = collect_agent_id(channel);
> +    if ( ret )
> +        return ret;

Why just ret? You seem to allocate memory in smc_create_channel() which
needs to be freed. I guess, free_channel_list() is needed.

> +
> +    /* Save the agent id for Xen management channel */
> +    scmi_data.hyp_channel_agent_id = channel->agent_id;
> +
> +    ret = map_channel_memory(channel);
> +    if ( ret )
> +        goto out;

The same question as above, as "goto out;" in your case is equivalent of 
"return ret;"

> +
> +    channel->domain_id = DOMID_XEN;
> +
> +    hdr.id = SCMI_BASE_PROTOCOL_ATTIBUTES;
> +    hdr.type = 0;
> +    hdr.protocol = SCMI_BASE_PROTOCOL;
> +
> +    ret = do_smc_xfer(channel, &hdr, NULL, 0, &rx, sizeof(rx));
> +    if ( ret )
> +        goto error;
> +
> +    n_agents = SCMI_FIELD_GET(SCMI_BASE_ATTR_NUM_AGENT, rx.attributes);
> +    printk(XENLOG_DEBUG "scmi: Got agent count %d\n", n_agents);
> +    ret = collect_agents(scmi_node);
> +    if ( ret )
> +        goto error;
> +
> +    ret = sci_register(&scmi_ops);
> +    if ( ret )
> +    {
> +        printk(XENLOG_ERR "SCMI: mediator already registered (ret = %d)\n",
> +               ret);
> +        return ret;
> +    }
> +
> +    scmi_data.initialized = true;
> +    goto out;
> +
> +error:
> +    unmap_channel_memory(channel);
> +    free_channel_list();
> +out:
> +    return ret;
> +}

[snip]




^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem
  2025-08-27  9:02     ` Oleksii Moisieiev
@ 2025-08-27 19:39       ` Stefano Stabellini
  2025-08-28 13:30         ` Oleksii Moisieiev
  0 siblings, 1 reply; 37+ messages in thread
From: Stefano Stabellini @ 2025-08-27 19:39 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Stefano Stabellini, xen-devel@lists.xenproject.org, Andrew Cooper,
	Anthony PERARD, Bertrand Marquis, Jan Beulich, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Volodymyr Babchuk, Grygorii Strashko

On Wed, 27 Aug 2025, Oleksii Moisieiev wrote:
> On 23/08/2025 03:26, Stefano Stabellini wrote:
> > On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
> >> From: Grygorii Strashko <grygorii_strashko@epam.com>
> >>
> >> The introduced SCI (System Control Interface) subsystem provides unified
> >> interface to integrate in Xen SCI drivers which adds support for ARM
> >> firmware (EL3, SCP) based software interfaces (like SCMI) that are used in
> >> system management. The SCI subsystem allows to add drivers for different FW
> >> interfaces or have different drivers for the same FW interface (for example,
> >> SCMI with different transports).
> >>
> >> This patch updates SCMI over SMC calls handling layer, introduced by
> >> commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls handling
> >> layer"), to be SCI driver:
> >> - convert to DT device;
> >> - convert to SCI Xen interface.
> >>
> >> There are no functional changes in general, the driver is just adopted
> >> to the SCI interface.
> >>
> >> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
> >> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
> >> ---
> >>
> >>
> >>
> >>   xen/arch/arm/firmware/Kconfig                | 13 ++-
> >>   xen/arch/arm/firmware/scmi-smc.c             | 93 +++++++++++---------
> >>   xen/arch/arm/include/asm/firmware/scmi-smc.h | 41 ---------
> >>   xen/arch/arm/vsmc.c                          |  5 +-
> >>   xen/include/public/arch-arm.h                |  1 +
> >>   5 files changed, 64 insertions(+), 89 deletions(-)
> >>   delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
> >>
> >> diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
> >> index fc7918c7fc..bbf88fbb9a 100644
> >> --- a/xen/arch/arm/firmware/Kconfig
> >> +++ b/xen/arch/arm/firmware/Kconfig
> >> @@ -8,9 +8,18 @@ config ARM_SCI
> >>   
> >>   menu "Firmware Drivers"
> >>   
> >> +choice
> >> +	prompt "ARM SCI driver type"
> >> +	default SCMI_SMC
> >> +	help
> >> +	Choose which ARM SCI driver to enable.
> >> +
> >> +config ARM_SCI_NONE
> >> +	bool "none"
> >> +
> >>   config SCMI_SMC
> >>   	bool "Forward SCMI over SMC calls from hwdom to EL3 firmware"
> >> -	default y
> >> +	select ARM_SCI
> >>   	help
> >>   	  This option enables basic awareness for SCMI calls using SMC as
> >>   	  doorbell mechanism and Shared Memory for transport ("arm,scmi-smc"
> >> @@ -18,4 +27,6 @@ config SCMI_SMC
> >>   	  firmware node is used to trap and forward corresponding SCMI SMCs
> >>   	  to firmware running at EL3, for calls coming from the hardware domain.
> >>   
> >> +endchoice
> >> +
> >>   endmenu
> >> diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c
> >> index 33473c04b1..13d1137592 100644
> >> --- a/xen/arch/arm/firmware/scmi-smc.c
> >> +++ b/xen/arch/arm/firmware/scmi-smc.c
> >> @@ -9,6 +9,7 @@
> >>    * Copyright 2024 NXP
> >>    */
> >>   
> >> +#include <asm/device.h>
> >>   #include <xen/acpi.h>
> >>   #include <xen/device_tree.h>
> >>   #include <xen/errno.h>
> >> @@ -16,12 +17,11 @@
> >>   #include <xen/sched.h>
> >>   #include <xen/types.h>
> >>   
> >> +#include <asm/firmware/sci.h>
> >>   #include <asm/smccc.h>
> >> -#include <asm/firmware/scmi-smc.h>
> >>   
> >>   #define SCMI_SMC_ID_PROP   "arm,smc-id"
> >>   
> >> -static bool __ro_after_init scmi_enabled;
> >>   static uint32_t __ro_after_init scmi_smc_id;
> >>   
> >>   /*
> >> @@ -41,14 +41,11 @@ static bool scmi_is_valid_smc_id(uint32_t fid)
> >>    *
> >>    * Returns true if SMC was handled (regardless of response), false otherwise.
> >>    */
> >> -bool scmi_handle_smc(struct cpu_user_regs *regs)
> >> +static bool scmi_handle_smc(struct cpu_user_regs *regs)
> >>   {
> >>       uint32_t fid = (uint32_t)get_user_reg(regs, 0);
> >>       struct arm_smccc_res res;
> >>   
> >> -    if ( !scmi_enabled )
> >> -        return false;
> >> -
> >>       if ( !scmi_is_valid_smc_id(fid) )
> >>           return false;
> >>   
> >> @@ -78,49 +75,45 @@ bool scmi_handle_smc(struct cpu_user_regs *regs)
> >>       return true;
> >>   }
> >>   
> >> -static int __init scmi_check_smccc_ver(void)
> >> +static int scmi_smc_domain_init(struct domain *d,
> >> +                                struct xen_domctl_createdomain *config)
> >>   {
> >> -    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
> >> -    {
> >> -        printk(XENLOG_WARNING
> >> -               "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
> >> -        return -ENOSYS;
> >> -    }
> >> +    if ( !is_hardware_domain(d) )
> >> +        return 0;
> > Should we also check for config->arch.sci_type ==
> > XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC ?
> >
> Current changes assume that only SCMI_SMC is present. This check was 
> added in the subsequent patch when multiagent was introduced.

In theory ARM_SCI_NONE is possible?



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
  2025-07-22 12:34   ` Jan Beulich
@ 2025-08-28  5:48     ` Oleksii Moisieiev
  2025-08-28  6:40       ` Jan Beulich
  0 siblings, 1 reply; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-08-28  5:48 UTC (permalink / raw)
  To: Jan Beulich
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org



On 22/07/2025 15:34, Jan Beulich wrote:
> On 22.07.2025 13:41, Oleksii Moisieiev wrote:
>> @@ -859,7 +860,25 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>>       case XEN_DOMCTL_test_assign_device:
>>       case XEN_DOMCTL_deassign_device:
>>       case XEN_DOMCTL_get_device_group:
>> +        int ret1;
>> +
>>           ret = iommu_do_domctl(op, d, u_domctl);
>> +        if ( ret < 0 && ret != -ENXIO )
>> +            return ret;
> If this is where you want the ENXIO for that the previous patch switched to,
> then I see no reason for that earlier change at all. Inside the hypervisor
> you can simply figure out what the right thing to do is; you could avoid
> calling iommu_do_domctl() altogether and call ...

My point was to leave the decision making to the calls themselves.
So iommu_do_domctl will make a decision whether to process the node or 
not, same for the scmi call.
I can figure out if there is a need to call iommu_do_domctl or 
sci_do_domctl here but this means moving
part of the logic from specific calls to the common code.
>> +        /*
>> +         * Add chained handling of assigned DT devices to support
>> +         * access-controller functionality through SCI framework, so
>> +         * DT device assign request can be passed to FW for processing and
>> +         * enabling VM access to requested device.
>> +         * The access-controller DT device processing is chained after IOMMU
>> +         * processing and expected to be executed for any DT device
>> +         * regardless if DT device is protected by IOMMU or not (or IOMMU
>> +         * is disabled).
>> +         */
>> +        ret1 = sci_do_domctl(op, d, u_domctl);
> ... this one right away, for example. (Which of course doesn't eliminate the
> question towards the overloading done here, which iirc was raised before.)
>
> Jan

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu
  2025-08-28  5:48     ` Oleksii Moisieiev
@ 2025-08-28  6:40       ` Jan Beulich
  0 siblings, 0 replies; 37+ messages in thread
From: Jan Beulich @ 2025-08-28  6:40 UTC (permalink / raw)
  To: Oleksii Moisieiev
  Cc: Andrew Cooper, Anthony PERARD, Bertrand Marquis, Juergen Gross,
	Julien Grall, Michal Orzel, Roger Pau Monné,
	Stefano Stabellini, Volodymyr Babchuk, Grygorii Strashko,
	xen-devel@lists.xenproject.org

On 28.08.2025 07:48, Oleksii Moisieiev wrote:
> 
> 
> On 22/07/2025 15:34, Jan Beulich wrote:
>> On 22.07.2025 13:41, Oleksii Moisieiev wrote:
>>> @@ -859,7 +860,25 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
>>>       case XEN_DOMCTL_test_assign_device:
>>>       case XEN_DOMCTL_deassign_device:
>>>       case XEN_DOMCTL_get_device_group:
>>> +        int ret1;
>>> +
>>>           ret = iommu_do_domctl(op, d, u_domctl);
>>> +        if ( ret < 0 && ret != -ENXIO )
>>> +            return ret;
>> If this is where you want the ENXIO for that the previous patch switched to,
>> then I see no reason for that earlier change at all. Inside the hypervisor
>> you can simply figure out what the right thing to do is; you could avoid
>> calling iommu_do_domctl() altogether and call ...
> 
> My point was to leave the decision making to the calls themselves.
> So iommu_do_domctl will make a decision whether to process the node or 
> not, same for the scmi call.
> I can figure out if there is a need to call iommu_do_domctl or 
> sci_do_domctl here but this means moving
> part of the logic from specific calls to the common code.

To avoid that, maybe it needs doing the other way around? I.e. try ...

>>> +        /*
>>> +         * Add chained handling of assigned DT devices to support
>>> +         * access-controller functionality through SCI framework, so
>>> +         * DT device assign request can be passed to FW for processing and
>>> +         * enabling VM access to requested device.
>>> +         * The access-controller DT device processing is chained after IOMMU
>>> +         * processing and expected to be executed for any DT device
>>> +         * regardless if DT device is protected by IOMMU or not (or IOMMU
>>> +         * is disabled).
>>> +         */
>>> +        ret1 = sci_do_domctl(op, d, u_domctl);

... this first?

Jan


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem
  2025-08-27 19:39       ` Stefano Stabellini
@ 2025-08-28 13:30         ` Oleksii Moisieiev
  0 siblings, 0 replies; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-08-28 13:30 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Volodymyr Babchuk,
	Grygorii Strashko



On 27/08/2025 22:39, Stefano Stabellini wrote:
> On Wed, 27 Aug 2025, Oleksii Moisieiev wrote:
>> On 23/08/2025 03:26, Stefano Stabellini wrote:
>>> On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
>>>> From: Grygorii Strashko <grygorii_strashko@epam.com>
>>>>
>>>> The introduced SCI (System Control Interface) subsystem provides unified
>>>> interface to integrate in Xen SCI drivers which adds support for ARM
>>>> firmware (EL3, SCP) based software interfaces (like SCMI) that are used in
>>>> system management. The SCI subsystem allows to add drivers for different FW
>>>> interfaces or have different drivers for the same FW interface (for example,
>>>> SCMI with different transports).
>>>>
>>>> This patch updates SCMI over SMC calls handling layer, introduced by
>>>> commit 3e322bef8bc0 ("xen/arm: firmware: Add SCMI over SMC calls handling
>>>> layer"), to be SCI driver:
>>>> - convert to DT device;
>>>> - convert to SCI Xen interface.
>>>>
>>>> There are no functional changes in general, the driver is just adopted
>>>> to the SCI interface.
>>>>
>>>> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
>>>> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>>>> ---
>>>>
>>>>
>>>>
>>>>    xen/arch/arm/firmware/Kconfig                | 13 ++-
>>>>    xen/arch/arm/firmware/scmi-smc.c             | 93 +++++++++++---------
>>>>    xen/arch/arm/include/asm/firmware/scmi-smc.h | 41 ---------
>>>>    xen/arch/arm/vsmc.c                          |  5 +-
>>>>    xen/include/public/arch-arm.h                |  1 +
>>>>    5 files changed, 64 insertions(+), 89 deletions(-)
>>>>    delete mode 100644 xen/arch/arm/include/asm/firmware/scmi-smc.h
>>>>
>>>> diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
>>>> index fc7918c7fc..bbf88fbb9a 100644
>>>> --- a/xen/arch/arm/firmware/Kconfig
>>>> +++ b/xen/arch/arm/firmware/Kconfig
>>>> @@ -8,9 +8,18 @@ config ARM_SCI
>>>>    
>>>>    menu "Firmware Drivers"
>>>>    
>>>> +choice
>>>> +	prompt "ARM SCI driver type"
>>>> +	default SCMI_SMC
>>>> +	help
>>>> +	Choose which ARM SCI driver to enable.
>>>> +
>>>> +config ARM_SCI_NONE
>>>> +	bool "none"
>>>> +
>>>>    config SCMI_SMC
>>>>    	bool "Forward SCMI over SMC calls from hwdom to EL3 firmware"
>>>> -	default y
>>>> +	select ARM_SCI
>>>>    	help
>>>>    	  This option enables basic awareness for SCMI calls using SMC as
>>>>    	  doorbell mechanism and Shared Memory for transport ("arm,scmi-smc"
>>>> @@ -18,4 +27,6 @@ config SCMI_SMC
>>>>    	  firmware node is used to trap and forward corresponding SCMI SMCs
>>>>    	  to firmware running at EL3, for calls coming from the hardware domain.
>>>>    
>>>> +endchoice
>>>> +
>>>>    endmenu
>>>> diff --git a/xen/arch/arm/firmware/scmi-smc.c b/xen/arch/arm/firmware/scmi-smc.c
>>>> index 33473c04b1..13d1137592 100644
>>>> --- a/xen/arch/arm/firmware/scmi-smc.c
>>>> +++ b/xen/arch/arm/firmware/scmi-smc.c
>>>> @@ -9,6 +9,7 @@
>>>>     * Copyright 2024 NXP
>>>>     */
>>>>    
>>>> +#include <asm/device.h>
>>>>    #include <xen/acpi.h>
>>>>    #include <xen/device_tree.h>
>>>>    #include <xen/errno.h>
>>>> @@ -16,12 +17,11 @@
>>>>    #include <xen/sched.h>
>>>>    #include <xen/types.h>
>>>>    
>>>> +#include <asm/firmware/sci.h>
>>>>    #include <asm/smccc.h>
>>>> -#include <asm/firmware/scmi-smc.h>
>>>>    
>>>>    #define SCMI_SMC_ID_PROP   "arm,smc-id"
>>>>    
>>>> -static bool __ro_after_init scmi_enabled;
>>>>    static uint32_t __ro_after_init scmi_smc_id;
>>>>    
>>>>    /*
>>>> @@ -41,14 +41,11 @@ static bool scmi_is_valid_smc_id(uint32_t fid)
>>>>     *
>>>>     * Returns true if SMC was handled (regardless of response), false otherwise.
>>>>     */
>>>> -bool scmi_handle_smc(struct cpu_user_regs *regs)
>>>> +static bool scmi_handle_smc(struct cpu_user_regs *regs)
>>>>    {
>>>>        uint32_t fid = (uint32_t)get_user_reg(regs, 0);
>>>>        struct arm_smccc_res res;
>>>>    
>>>> -    if ( !scmi_enabled )
>>>> -        return false;
>>>> -
>>>>        if ( !scmi_is_valid_smc_id(fid) )
>>>>            return false;
>>>>    
>>>> @@ -78,49 +75,45 @@ bool scmi_handle_smc(struct cpu_user_regs *regs)
>>>>        return true;
>>>>    }
>>>>    
>>>> -static int __init scmi_check_smccc_ver(void)
>>>> +static int scmi_smc_domain_init(struct domain *d,
>>>> +                                struct xen_domctl_createdomain *config)
>>>>    {
>>>> -    if ( smccc_ver < ARM_SMCCC_VERSION_1_1 )
>>>> -    {
>>>> -        printk(XENLOG_WARNING
>>>> -               "SCMI: No SMCCC 1.1 support, SCMI calls forwarding disabled\n");
>>>> -        return -ENOSYS;
>>>> -    }
>>>> +    if ( !is_hardware_domain(d) )
>>>> +        return 0;
>>> Should we also check for config->arch.sci_type ==
>>> XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC ?
>>>
>> Current changes assume that only SCMI_SMC is present. This check was
>> added in the subsequent patch when multiagent was introduced.
> In theory ARM_SCI_NONE is possible?
>
It is. When "scmi-smc-passthrough" parameter was provided then xen will 
skip "firmware/scmi" node for the dom0.

--
Oleksii

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [RFC PATCH v5 01/10] xen/arm: add generic SCI subsystem
  2025-08-23  0:26   ` Stefano Stabellini
@ 2025-08-28 13:46     ` Oleksii Moisieiev
  0 siblings, 0 replies; 37+ messages in thread
From: Oleksii Moisieiev @ 2025-08-28 13:46 UTC (permalink / raw)
  To: Stefano Stabellini
  Cc: xen-devel@lists.xenproject.org, Andrew Cooper, Anthony PERARD,
	Bertrand Marquis, Jan Beulich, Juergen Gross, Julien Grall,
	Michal Orzel, Roger Pau Monné, Volodymyr Babchuk,
	Grygorii Strashko



On 23/08/2025 03:26, Stefano Stabellini wrote:
> On Tue, 22 Jul 2025, Oleksii Moisieiev wrote:
>> This patch adds the basic framework for ARM SCI mediator. SCI is System
>> Control Interface, which is designed to redirect requests from the Domains
>> to ARM specific Firmware (for example SCMI). This will allow the devices,
>> passed-through to the different Domains, to access to the System resources
>> (such as clocks/resets etc) by sending requests to the firmware.
>>
>> ARM SCI subsystem allows to implement different SCI drivers to handle
>> specific ARM firmware interfaces (like ARM SCMI) and mediate requests
>> -between the Domains and the Firmware. Also it allows SCI drivers to perform
>> proper action during Domain creation/destruction which is vital for
>> handling use cases like Domain reboot.
>>
>> This patch introduces new DEVICE_FIRMWARE device subclass for probing SCI
>> drivers basing on device tree, SCI drivers register itself with
>> DT_DEVICE_START/END macro. On init - the SCI drivers should register its
>> SCI ops with sci_register(). Only one SCI driver can be supported.
>>
>> At run-time, the following SCI API calls are introduced:
>>
>> - sci_domain_sanitise_config() called from arch_sanitise_domain_config()
>> - sci_domain_init() called from arch_domain_create()
>> - sci_relinquish_resources() called from domain_relinquish_resources()
>> - sci_domain_destroy() called from arch_domain_destroy()
>> - sci_handle_call() called from vsmccc_handle_call()
>> - sci_dt_handle_node()
>> - sci_dt_finalize() called from handle_node() (Dom0 DT)
>>
>> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>> Signed-off-by: Grygorii Strashko <grygorii_strashko@epam.com>
> The patch needs rebasing
>
>
>> ---
>>
>> Changes in v5:
>> - update Maintainers file. Set role as a Reviewer
>> - rebased on the latest master branch
>> - Introduce arch_handle_passthrough_prop call to handle arm specific nodes
>>
>> Changes in v4:
>> - fix SPDX-License
>> - rename DEVICE_ARM_SCI DT device class to FIRMWARE_DEVICE
>> - move XEN_DOMCTL_assign_device code in separate patch
>> - Add documentation for SCI SCMI drivers
>>
>>   MAINTAINERS                              |   6 +
>>   xen/arch/arm/device.c                    |   5 +
>>   xen/arch/arm/dom0less-build.c            |   8 +
>>   xen/arch/arm/domain.c                    |  12 +-
>>   xen/arch/arm/domain_build.c              |   8 +
>>   xen/arch/arm/firmware/Kconfig            |   8 +
>>   xen/arch/arm/firmware/Makefile           |   1 +
>>   xen/arch/arm/firmware/sci.c              | 154 +++++++++++++++++
>>   xen/arch/arm/include/asm/domain.h        |   5 +
>>   xen/arch/arm/include/asm/firmware/sci.h  | 200 +++++++++++++++++++++++
>>   xen/arch/arm/vsmc.c                      |   3 +
>>   xen/common/device-tree/dom0less-build.c  |   4 +
>>   xen/include/asm-generic/device.h         |   1 +
>>   xen/include/asm-generic/dom0less-build.h |   9 +
>>   xen/include/public/arch-arm.h            |   4 +
>>   15 files changed, 427 insertions(+), 1 deletion(-)
>>   create mode 100644 xen/arch/arm/firmware/sci.c
>>   create mode 100644 xen/arch/arm/include/asm/firmware/sci.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index c4886c1159..31dbba54bb 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -509,6 +509,12 @@ R:	George Dunlap <gwd@xenproject.org>
>>   S:	Supported
>>   F:	xen/common/sched/
>>   
>> +SCI MEDIATORS
>> +R:	Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>> +S:	Supported
>> +F:	xen/arch/arm/firmware/sci.c
>> +F:	xen/arch/arm/include/asm/firmware/sci.h
>> +
>>   SEABIOS UPSTREAM
>>   M:	Wei Liu <wl@xen.org>
>>   S:	Supported
>> diff --git a/xen/arch/arm/device.c b/xen/arch/arm/device.c
>> index 11523750ae..74b54cad34 100644
>> --- a/xen/arch/arm/device.c
>> +++ b/xen/arch/arm/device.c
>> @@ -13,6 +13,7 @@
>>   #include <xen/iocap.h>
>>   #include <xen/lib.h>
>>   
>> +#include <asm/firmware/sci.h>
>>   #include <asm/setup.h>
>>   
>>   int map_irq_to_domain(struct domain *d, unsigned int irq,
>> @@ -303,6 +304,10 @@ int handle_device(struct domain *d, struct dt_device_node *dev, p2m_type_t p2mt,
>>                   return res;
>>               }
>>           }
>> +
>> +        res = sci_assign_dt_device(d, dev);
>> +        if ( res )
>> +            return res;
>>       }
>>   
>>       res = map_device_irqs_to_domain(d, dev, own_device, irq_ranges);
>> diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
>> index 4b285cff5e..2a0bf817ba 100644
>> --- a/xen/arch/arm/dom0less-build.c
>> +++ b/xen/arch/arm/dom0less-build.c
>> @@ -22,6 +22,7 @@
>>   #include <asm/arm64/sve.h>
>>   #include <asm/dom0less-build.h>
>>   #include <asm/domain_build.h>
>> +#include <asm/firmware/sci.h>
>>   #include <asm/grant_table.h>
>>   #include <asm/setup.h>
>>   
>> @@ -272,6 +273,12 @@ int __init init_vuart(struct domain *d, struct kernel_info *kinfo,
>>       return rc;
>>   }
>>   
>> +int __init arch_handle_passthrough_prop(struct kernel_info *kinfo,
>> +                                        struct dt_device_node *node)
>> +{
>> +    return sci_assign_dt_device(kinfo->d, node);
>> +}
>> +
>>   void __init arch_create_domUs(struct dt_device_node *node,
>>                          struct xen_domctl_createdomain *d_cfg,
>>                          unsigned int flags)
>> @@ -280,6 +287,7 @@ void __init arch_create_domUs(struct dt_device_node *node,
>>   
>>       d_cfg->arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
>>       d_cfg->flags |= XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap;
>> +    d_cfg->arch.arm_sci_type = XEN_DOMCTL_CONFIG_ARM_SCI_NONE;
>>   
>>       if ( !dt_property_read_u32(node, "nr_spis", &d_cfg->arch.nr_spis) )
>>       {
>> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
>> index 79a144e61b..d0146da5da 100644
>> --- a/xen/arch/arm/domain.c
>> +++ b/xen/arch/arm/domain.c
>> @@ -24,6 +24,7 @@
>>   #include <asm/platform.h>
>>   #include <asm/procinfo.h>
>>   #include <asm/regs.h>
>> +#include <asm/firmware/sci.h>
>>   #include <asm/tee/tee.h>
>>   #include <asm/vfp.h>
>>   #include <asm/vgic.h>
>> @@ -699,7 +700,7 @@ int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
>>           return -EINVAL;
>>       }
>>   
>> -    return 0;
>> +    return sci_domain_sanitise_config(config);
>>   }
>>   
>>   int arch_domain_create(struct domain *d,
>> @@ -791,6 +792,9 @@ int arch_domain_create(struct domain *d,
>>       d->arch.sve_vl = config->arch.sve_vl;
>>   #endif
>>   
>> +    if ( (rc = sci_domain_init(d, config)) != 0 )
>> +        goto fail;
>> +
>>       return 0;
>>   
>>   fail:
>> @@ -851,6 +855,7 @@ void arch_domain_destroy(struct domain *d)
>>       domain_vgic_free(d);
>>       domain_vuart_free(d);
>>       free_xenheap_page(d->shared_info);
>> +    sci_domain_destroy(d);
>>   #ifdef CONFIG_ACPI
>>       free_xenheap_pages(d->arch.efi_acpi_table,
>>                          get_order_from_bytes(d->arch.efi_acpi_len));
>> @@ -1044,6 +1049,7 @@ enum {
>>       PROG_p2m_root,
>>       PROG_p2m,
>>       PROG_p2m_pool,
>> +    PROG_sci,
>>       PROG_done,
>>   };
>>   
>> @@ -1103,6 +1109,10 @@ int domain_relinquish_resources(struct domain *d)
>>           ret = relinquish_p2m_mapping(d);
>>           if ( ret )
>>               return ret;
>> +    PROGRESS(sci):
>> +        ret = sci_relinquish_resources(d);
>> +        if ( ret )
>> +            return ret;
>>   
>>       PROGRESS(p2m_root):
>>           /*
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index ed668bd61c..92039cf213 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -26,6 +26,7 @@
>>   #include <asm/setup.h>
>>   #include <asm/tee/tee.h>
>>   #include <asm/pci.h>
>> +#include <asm/firmware/sci.h>
>>   #include <asm/platform.h>
>>   #include <asm/psci.h>
>>   #include <asm/setup.h>
>> @@ -1639,6 +1640,9 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>>           return 0;
>>       }
>>   
>> +    if ( sci_dt_handle_node(d, node) )
>> +        return 0;
>> +
>>       /*
>>        * The vGIC does not support routing hardware PPIs to guest. So
>>        * we need to skip any node using PPIs.
>> @@ -1739,6 +1743,10 @@ static int __init handle_node(struct domain *d, struct kernel_info *kinfo,
>>           if ( res )
>>               return res;
>>   
>> +        res = sci_dt_finalize(d, kinfo->fdt);
>> +        if ( res )
>> +            return res;
>> +
>>           /*
>>            * Create a second memory node to store the ranges covering
>>            * reserved-memory regions.
>> diff --git a/xen/arch/arm/firmware/Kconfig b/xen/arch/arm/firmware/Kconfig
>> index 817da745fd..fc7918c7fc 100644
>> --- a/xen/arch/arm/firmware/Kconfig
>> +++ b/xen/arch/arm/firmware/Kconfig
>> @@ -1,3 +1,11 @@
>> +config ARM_SCI
>> +	bool
>> +	depends on ARM
>> +	help
>> +	  This option enables generic Arm SCI (System Control Interface) mediators
>> +	  support. It allows domains to control system resources via one of
>> +	  Arm SCI mediators drivers implemented in XEN, like SCMI.
>> +
>>   menu "Firmware Drivers"
>>   
>>   config SCMI_SMC
>> diff --git a/xen/arch/arm/firmware/Makefile b/xen/arch/arm/firmware/Makefile
>> index a5e4542666..71bdefc24a 100644
>> --- a/xen/arch/arm/firmware/Makefile
>> +++ b/xen/arch/arm/firmware/Makefile
>> @@ -1 +1,2 @@
>> +obj-$(CONFIG_ARM_SCI) += sci.o
>>   obj-$(CONFIG_SCMI_SMC) += scmi-smc.o
>> diff --git a/xen/arch/arm/firmware/sci.c b/xen/arch/arm/firmware/sci.c
>> new file mode 100644
>> index 0000000000..e1522e10e2
>> --- /dev/null
>> +++ b/xen/arch/arm/firmware/sci.c
>> @@ -0,0 +1,154 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Generic part of the SCI (System Control Interface) subsystem.
>> + *
>> + * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>> + * Copyright (c) 2025 EPAM Systems
>> + */
>> +
>> +#include <xen/acpi.h>
>> +#include <xen/errno.h>
>> +#include <xen/init.h>
>> +#include <xen/sched.h>
>> +#include <xen/types.h>
>> +
>> +#include <asm/firmware/sci.h>
>> +
>> +static const struct sci_mediator_ops __read_mostly *cur_mediator;
>> +
>> +int sci_register(const struct sci_mediator_ops *ops)
>> +{
>> +    if ( cur_mediator )
>> +        return -EEXIST;
>> +
>> +    if ( !ops->domain_init || !ops->domain_destroy || !ops->handle_call )
>> +        return -EINVAL;
>> +
>> +    cur_mediator = ops;
>> +
>> +    return 0;
>> +};
>> +
>> +bool sci_handle_call(struct cpu_user_regs *args)
>> +{
>> +    if ( unlikely(!cur_mediator) )
>> +        return false;
> should we check that sci_domain_is_enabled ?
>
I think there is no need to do this check here and give ability to 
driver itself to decide what actions should be done. For example 
domain_init call for SCMI-SMC single domain will remove /firmware/scmi 
node from Dom0 device tree when "scmi-smc-passthrough" was provided.
>> +    return cur_mediator->handle_call(args);
>> +}
>> +
>> +int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config)
>> +{
>> +    if ( !cur_mediator )
>> +        return 0;
>> +
>> +    return cur_mediator->domain_init(d, config);
>> +}
>> +
>> +int sci_domain_sanitise_config(struct xen_domctl_createdomain *config)
>> +{
>> +    if ( !cur_mediator )
>> +        return 0;
>> +
>> +    if ( !cur_mediator->domain_sanitise_config )
>> +        return 0;
>> +
>> +    return cur_mediator->domain_sanitise_config(config);
>> +}
>> +
>> +void sci_domain_destroy(struct domain *d)
>> +{
>> +    if ( !cur_mediator )
>> +        return;
>> +
>> +    cur_mediator->domain_destroy(d);
>> +}
>> +
>> +int sci_relinquish_resources(struct domain *d)
>> +{
>> +    if ( !cur_mediator )
>> +        return 0;
>> +
>> +    if ( !cur_mediator->relinquish_resources )
>> +        return 0;
>> +
>> +    return cur_mediator->relinquish_resources(d);
>> +}
>> +
>> +bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node)
>> +{
>> +    if ( !cur_mediator )
>> +        return 0;
>> +
>> +    if ( !cur_mediator->dom0_dt_handle_node )
>> +        return 0;
>> +
>> +    return cur_mediator->dom0_dt_handle_node(d, node);
>> +}
>> +
>> +int sci_dt_finalize(struct domain *d, void *fdt)
>> +{
>> +    if ( !cur_mediator )
>> +        return 0;
>> +
>> +    if ( !cur_mediator->dom0_dt_finalize )
>> +        return 0;
>> +
>> +    return cur_mediator->dom0_dt_finalize(d, fdt);
>> +}
>> +
>> +int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev)
>> +{
>> +    struct dt_phandle_args ac_spec;
>> +    int index = 0;
>> +    int ret;
>> +
>> +    if ( !cur_mediator )
>> +        return 0;
>> +
>> +    if ( !cur_mediator->assign_dt_device )
>> +        return 0;
>> +
>> +    while ( !dt_parse_phandle_with_args(dev, "access-controllers",
>> +                                        "#access-controller-cells", index,
>> +                                        &ac_spec) )
>> +    {
>> +        printk(XENLOG_DEBUG "sci: assign device %s to %pd\n",
>> +               dt_node_full_name(dev), d);
>> +
>> +        ret = cur_mediator->assign_dt_device(d, &ac_spec);
>> +        if ( ret )
>> +            return ret;
>> +
>> +        index++;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +static int __init sci_init(void)
>> +{
>> +    struct dt_device_node *np;
>> +    unsigned int num_sci = 0;
>> +    int rc;
>> +
>> +    dt_for_each_device_node(dt_host, np)
>> +    {
>> +        rc = device_init(np, DEVICE_FIRMWARE, NULL);
>> +        if ( !rc && num_sci )
>> +        {
>> +            printk(XENLOG_ERR
>> +                   "SCMI: Only one SCI controller is supported. found second %s\n",
>> +                   np->name);
>> +            return -EOPNOTSUPP;
>> +        }
>> +        else if ( !rc )
>> +            num_sci++;
>> +        else if ( rc != -EBADF && rc != -ENODEV )
>> +            return rc;
>> +    }
>> +
>> +    return 0;
>> +}
>> +
>> +__initcall(sci_init);
>> diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
>> index a3487ca713..af3e168374 100644
>> --- a/xen/arch/arm/include/asm/domain.h
>> +++ b/xen/arch/arm/include/asm/domain.h
>> @@ -120,6 +120,11 @@ struct arch_domain
>>   #ifdef CONFIG_TEE
>>       void *tee;
>>   #endif
>> +#ifdef CONFIG_ARM_SCI
>> +    bool sci_enabled;
>> +    /* ARM SCI driver's specific data */
>> +    void *sci_data;
>> +#endif
>>   
>>   }  __cacheline_aligned;
>>   
>> diff --git a/xen/arch/arm/include/asm/firmware/sci.h b/xen/arch/arm/include/asm/firmware/sci.h
>> new file mode 100644
>> index 0000000000..71fb54852e
>> --- /dev/null
>> +++ b/xen/arch/arm/include/asm/firmware/sci.h
>> @@ -0,0 +1,200 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +/*
>> + * Generic ARM SCI (System Control Interface) subsystem.
>> + *
>> + * Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>> + * Copyright (c) 2025 EPAM Systems
>> + */
>> +
>> +#ifndef __ASM_ARM_SCI_H
>> +#define __ASM_ARM_SCI_H
>> +
>> +#include <xen/lib.h>
>> +#include <xen/types.h>
>> +#include <xen/device_tree.h>
>> +#include <xen/errno.h>
>> +#include <xen/sched.h>
>> +
>> +#ifdef CONFIG_ARM_SCI
>> +
>> +struct sci_mediator_ops {
>> +    /*
>> +     * Called during domain construction. If it is requested to enable
>> +     * SCI support, so SCI driver can create own structures for the new domain
>> +     * and inform firmware about new domain (if required).
>> +     * Mandatory.
>> +     */
>> +    int (*domain_init)(struct domain *d,
>> +                       struct xen_domctl_createdomain *config);
>> +
>> +    /*
>> +     * Called during domain construction. The SCI driver uses
>> +     * it to sanitize domain SCI configuration parameters.
>> +     * Optional.
>> +     */
>> +    int (*domain_sanitise_config)(struct xen_domctl_createdomain *config);
>> +
>> +    /*
>> +     * Called during domain destruction, releases all resources, that
>> +     * were allocated for domain.
>> +     * Mandatory.
>> +     */
>> +    void (*domain_destroy)(struct domain *d);
>> +
>> +    /*
>> +     * Called during domain destruction to relinquish resources used
>> +     * by SCI driver itself and request resources releasing from firmware.
>> +     * Optional.
>> +     */
>> +    int (*relinquish_resources)(struct domain *d);
>> +
>> +    /* SMC/HVC Handle callback */
>> +    bool (*handle_call)(struct cpu_user_regs *regs);
>> +
>> +    /*
>> +     * Dom0 DT nodes handling callback so SCI driver can detect DT nodes it
>> +     * need to handle and decide if those nodes need to be provided to Dom0.
>> +     * Optional.
>> +     */
>> +    bool (*dom0_dt_handle_node)(struct domain *d, struct dt_device_node *node);
>> +
>> +    /*
>> +     * SCI driver callback called at the end of Dom0 DT generation, so
>> +     * it can perform steps to modify DT to enable/disable SCI
>> +     * functionality for Dom0.
>> +     */
>> +    int (*dom0_dt_finalize)(struct domain *d, void *fdt);
>> +
>> +    /*
>> +     * SCI driver callback called when DT device is passed through to guest,
>> +     * so SCI driver can enable device access to the domain if SCI FW provides
>> +     * Device specific access control functionality.
>> +     * Optional.
>> +     */
>> +    int (*assign_dt_device)(struct domain *d, struct dt_phandle_args *ac_spec);
>> +};
>> +
>> +
>> +static inline bool sci_domain_is_enabled(struct domain *d)
>> +{
>> +    return d->arch.sci_enabled;
>> +}
>> +
>> +/*
>> + * Register SCI subsystem ops.
>> + *
>> + * Register SCI drivers operation and so enable SCI functionality.
>> + * Only one SCI driver is supported.
>> + */
>> +int sci_register(const struct sci_mediator_ops *ops);
>> +
>> +/*
>> + * Initialize SCI functionality for domain if configured.
>> + *
>> + * Initialization routine to enable SCI functionality for the domain.
>> + * The SCI configuration data and decision about enabling SCI functionality
>> + * for the domain is SCI driver specific.
>> + */
>> +int sci_domain_init(struct domain *d, struct xen_domctl_createdomain *config);
>> +
>> +/*
>> + * Sanitise domain configuration parameters.
>> + *
>> + */
>> +int sci_domain_sanitise_config(struct xen_domctl_createdomain *config);
>> +
>> +/*
>> + * Destroy SCI domain instance.
>> + */
>> +void sci_domain_destroy(struct domain *d);
>> +
>> +/*
>> + * Free resources assigned to the certain domain.
>> + */
>> +int sci_relinquish_resources(struct domain *d);
>> +
>> +/*
>> + * SMC/HVC Handle callback.
>> + *
>> + * SCI driver acts as SMC/HVC server for the registered domains and
>> + * does redirection of the domain calls to the SCI firmware,
>> + * such as ARM TF-A or similar.
>> + */
>> +bool sci_handle_call(struct cpu_user_regs *regs);
>> +
>> +/*
>> + * Dom0 DT nodes handling function.
>> + *
>> + * Allows SCI driver to detect DT nodes it need to handle and decide if
>> + * those nodes need to be provided to Dom0.
>> + */
>> +bool sci_dt_handle_node(struct domain *d, struct dt_device_node *node);
>> +
>> +/*
>> + * Dom0 DT generation finalize.
>> + *
>> + * Called at the end of Dom0 DT generation, so SCI driver can perform steps
>> + * to modify DT to enable/disable SCI functionality for Dom0.
>> + */
>> +int sci_dt_finalize(struct domain *d, void *fdt);
>> +
>> +/*
>> + * Assign DT device to domain.
>> + *
>> + * Called when DT device is passed through to guest, so SCI driver can enable
>> + * device access to the domain if SCI FW provides "Device specific access
>> + * control" functionality.
>> + */
>> +int sci_assign_dt_device(struct domain *d, struct dt_device_node *dev);
>> +#else
>> +
>> +static inline bool sci_domain_is_enabled(struct domain *d)
>> +{
>> +    return false;
>> +}
>> +
>> +static inline int sci_domain_init(struct domain *d,
>> +                                  struct xen_domctl_createdomain *config)
>> +{
>> +    return 0;
>> +}
>> +
>> +static inline int
>> +sci_domain_sanitise_config(struct xen_domctl_createdomain *config)
>> +{
>> +    return 0;
>> +}
>> +
>> +static inline void sci_domain_destroy(struct domain *d)
>> +{}
>> +
>> +static inline int sci_relinquish_resources(struct domain *d)
>> +{
>> +    return 0;
>> +}
>> +
>> +static inline bool sci_handle_call(struct cpu_user_regs *args)
>> +{
>> +    return false;
>> +}
>> +
>> +static inline bool sci_dt_handle_node(struct domain *d,
>> +                                      struct dt_device_node *node)
>> +{
>> +    return false;
>> +}
>> +
>> +static inline int sci_dt_finalize(struct domain *d, void *fdt)
>> +{
>> +    return false;
> should return int, not bool
>
>
>> +}
>> +
>> +static inline int sci_assign_dt_device(struct domain *d,
>> +                                       struct dt_device_node *dev)
>> +{
>> +    return 0;
>> +}
>> +
>> +#endif /* CONFIG_ARM_SCI */
>> +
>> +#endif /* __ASM_ARM_SCI_H */
>> diff --git a/xen/arch/arm/vsmc.c b/xen/arch/arm/vsmc.c
>> index 6081f14ed0..2469738fcc 100644
>> --- a/xen/arch/arm/vsmc.c
>> +++ b/xen/arch/arm/vsmc.c
>> @@ -12,6 +12,7 @@
>>   #include <public/arch-arm/smccc.h>
>>   #include <asm/cpuerrata.h>
>>   #include <asm/cpufeature.h>
>> +#include <asm/firmware/sci.h>
>>   #include <asm/monitor.h>
>>   #include <asm/regs.h>
>>   #include <asm/smccc.h>
>> @@ -300,6 +301,8 @@ static bool vsmccc_handle_call(struct cpu_user_regs *regs)
>>               break;
>>           case ARM_SMCCC_OWNER_SIP:
>>               handled = handle_sip(regs);
>> +            if ( !handled )
>> +                handled = sci_handle_call(regs);
>>               break;
>>           case ARM_SMCCC_OWNER_TRUSTED_APP ... ARM_SMCCC_OWNER_TRUSTED_APP_END:
>>           case ARM_SMCCC_OWNER_TRUSTED_OS ... ARM_SMCCC_OWNER_TRUSTED_OS_END:
>> diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c
>> index 0012046574..f29656a27e 100644
>> --- a/xen/common/device-tree/dom0less-build.c
>> +++ b/xen/common/device-tree/dom0less-build.c
>> @@ -228,6 +228,10 @@ static int __init handle_passthrough_prop(struct kernel_info *kinfo,
>>       if ( res < 0 )
>>           return res;
>>   
>> +    res = arch_handle_passthrough_prop(kinfo, node);
>> +    if ( res )
>> +        return res;
>> +
>>       /* If xen_force, we allow assignment of devices without IOMMU protection. */
>>       if ( xen_force && !dt_device_is_protected(node) )
>>           return 0;
>> diff --git a/xen/include/asm-generic/device.h b/xen/include/asm-generic/device.h
>> index 1acd1ba1d8..e96c5558c2 100644
>> --- a/xen/include/asm-generic/device.h
>> +++ b/xen/include/asm-generic/device.h
>> @@ -18,6 +18,7 @@ enum device_class
>>       DEVICE_IOMMU,
>>       DEVICE_INTERRUPT_CONTROLLER,
>>       DEVICE_PCI_HOSTBRIDGE,
>> +    DEVICE_FIRMWARE,
>>       /* Use for error */
>>       DEVICE_UNKNOWN,
>>   };
>> diff --git a/xen/include/asm-generic/dom0less-build.h b/xen/include/asm-generic/dom0less-build.h
>> index e0ad0429ec..1c56441c33 100644
>> --- a/xen/include/asm-generic/dom0less-build.h
>> +++ b/xen/include/asm-generic/dom0less-build.h
>> @@ -61,6 +61,9 @@ void set_domain_type(struct domain *d, struct kernel_info *kinfo);
>>   int init_intc_phandle(struct kernel_info *kinfo, const char *name,
>>                         const int node_next, const void *pfdt);
>>   
>> +int arch_handle_passthrough_prop(struct kernel_info *kinfo,
>> +                                 struct dt_device_node *node);
>> +
>>   #else /* !CONFIG_DOM0LESS_BOOT */
>>   
>>   static inline void create_domUs(void) {}
>> @@ -70,6 +73,12 @@ static inline bool is_dom0less_mode(void)
>>   }
>>   static inline void set_xs_domain(struct domain *d) {}
>>   
>> +static inline int arch_handle_passthrough_prop(struct kernel_info *kinfo,
>> +                                               struct dt_device_node *node)
>> +{
>> +    return 0;
>> +}
>> +
>>   #endif /* CONFIG_DOM0LESS_BOOT */
>>   
>>   #endif /* __ASM_GENERIC_DOM0LESS_BUILD_H__ */
>> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
>> index 24840eeaa6..55eed9992c 100644
>> --- a/xen/include/public/arch-arm.h
>> +++ b/xen/include/public/arch-arm.h
>> @@ -327,6 +327,8 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
>>   #define XEN_DOMCTL_CONFIG_TEE_OPTEE     1
>>   #define XEN_DOMCTL_CONFIG_TEE_FFA       2
>>   
>> +#define XEN_DOMCTL_CONFIG_ARM_SCI_NONE      0
>> +
>>   struct xen_arch_domainconfig {
>>       /* IN/OUT */
>>       uint8_t gic_version;
>> @@ -350,6 +352,8 @@ struct xen_arch_domainconfig {
>>        *
>>        */
>>       uint32_t clock_frequency;
>> +    /* IN */
>> +    uint8_t arm_sci_type;
>>   };
>>   #endif /* __XEN__ || __XEN_TOOLS__ */
>>   
>> -- 
>> 2.34.1
>>

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2025-08-28 13:46 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-22 11:41 [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Oleksii Moisieiev
2025-07-22 11:41 ` [RFC PATCH v5 02/10] xen/arm: scmi-smc: update to be used under sci subsystem Oleksii Moisieiev
2025-08-23  0:26   ` Stefano Stabellini
2025-08-27  9:02     ` Oleksii Moisieiev
2025-08-27 19:39       ` Stefano Stabellini
2025-08-28 13:30         ` Oleksii Moisieiev
2025-07-22 11:41 ` [RFC PATCH v5 01/10] xen/arm: add generic SCI subsystem Oleksii Moisieiev
2025-08-23  0:26   ` Stefano Stabellini
2025-08-28 13:46     ` Oleksii Moisieiev
2025-07-22 11:41 ` [RFC PATCH v5 04/10] docs: arm: add docs for SCMI over SMC calls forwarding driver Oleksii Moisieiev
2025-08-23  0:30   ` Stefano Stabellini
2025-07-22 11:41 ` [RFC PATCH v5 03/10] xen/arm: scmi-smc: passthrough SCMI SMC to domain, single agent Oleksii Moisieiev
2025-07-22 12:21   ` Jan Beulich
2025-07-22 15:09     ` Oleksii Moisieiev
2025-07-30 13:19   ` Anthony PERARD
2025-08-23  0:22   ` Stefano Stabellini
2025-07-22 11:41 ` [RFC PATCH v5 05/10] drivers: iommu: change error code when iommu is disabled Oleksii Moisieiev
2025-07-22 12:29   ` Jan Beulich
2025-07-22 11:41 ` [RFC PATCH v5 07/10] xen: arm: smccc: add INVALID_PARAMETER error code Oleksii Moisieiev
2025-08-23  0:33   ` Stefano Stabellini
2025-07-22 11:41 ` [RFC PATCH v5 06/10] xen/domctl: extend XEN_DOMCTL_assign_device to handle not only iommu Oleksii Moisieiev
2025-07-22 12:34   ` Jan Beulich
2025-08-28  5:48     ` Oleksii Moisieiev
2025-08-28  6:40       ` Jan Beulich
2025-07-22 11:41 ` [RFC PATCH v5 09/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent driver Oleksii Moisieiev
2025-07-22 12:46   ` Jan Beulich
2025-07-30 13:29   ` Anthony PERARD
2025-08-26  0:37   ` Stefano Stabellini
2025-08-27 19:35   ` Oleksandr Tyshchenko
2025-07-22 11:41 ` [RFC PATCH v5 08/10] lib/arm: Add I/O memory copy helpers Oleksii Moisieiev
2025-07-22 12:43   ` Jan Beulich
2025-08-23  0:40   ` Stefano Stabellini
2025-07-22 11:41 ` [RFC PATCH v5 10/10] docs: arm: add SCI SCMI SMC multi-agent driver docs Oleksii Moisieiev
2025-08-26  0:44   ` Stefano Stabellini
2025-08-23  0:34 ` [RFC PATCH v5 00/10] xen/arm: scmi: introduce SCI SCMI SMC multi-agent support Stefano Stabellini
2025-08-27  9:10   ` Oleksii Moisieiev
2025-08-27 15:37     ` Stefano Stabellini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.