[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v1 02/26] xen/arm/cca: add RMI v2.0 SMCCC core wrappers


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Fri, 15 May 2026 13:07:48 +0900
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=P+LWGLET1pPPxjg9pYTqsoCrj/kofsydU9ywUKvFgV0=; b=WzF2LBA7mlelkQLIqFzGBJkUXWmw0FoRCrijYvapMbsZ5tsY37dBrs0GI7TYZLIaslVib9DO3McvX7UWv8JbFfGKr9I18Uziy/pqIN02iF73pFWbFPCOQGs5rE03ClgQlrII0CUkiD4UM0GrSPHz/PsPEGNWikjG+Dq36ZLD6oXt3kyy5Sp1F/g3Qotb/iigvA8yOmIsB4abBFxfJOqPukGzM/Vd0j1pYyKMbUxUvTYayEomoeEtKBObveIFg4AUCJ8kkHiuGsLwYpr7nboNOCSm7tfwEmLKoLxV7A/9MJREAWsqPss1Q6uTsQVB55hr6tLiWEha9j0cwyBAyTE1ag==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=fsBNMxPdzUGbCqyDTUfE0JdM1ndGTEDEJAhNShKaXKWqiWyEzkRN4HarF6XjiFzuv0mDoKty6Aarw8jAdG5HBO76Y+Pow+qBUTzno0yE7JraKuXG/mre4VCu7VpzuIeOejIqFFeS40K8prRER3ha+j3TuSspJ+UQ6YIu85T3YtfZ3NwM0vpJD//oHdtO7qN73lOsUStGtnvEAvMsYV27/JjzNAlKlWfm0KUQrCzLtUFophM2CyhsbeWiz8vdelx4ulIy5ymZaq7V5P4oqPt+zfXcbRfafnqxKBQjitKgwIiW46VYrzVDNHIRpauUphHloZm3xerewlv0K7zD5/SjyA==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=valinux.co.jp header.i="@valinux.co.jp" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp;
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Anthony PERARD <anthony.perard@xxxxxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Julien Grall <julien@xxxxxxx>, Roger Pau Monné <roger.pau@xxxxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, "Daniel P. Smith" <dpsmith@xxxxxxxxxxxxxxxxxxxx>, Juergen Gross <jgross@xxxxxxxx>, Bertrand Marquis <bertrand.marquis@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
  • Delivery-date: Fri, 15 May 2026 04:08:38 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

Add the common SMC path and the early RMI calls used to probe and
configure the RMM. The rest of the series can build on typed helpers
rather than spelling out registers each time.

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 xen/arch/arm/Kconfig      |  14 ++++
 xen/arch/arm/Makefile     |   1 +
 xen/arch/arm/cca/Makefile |   1 +
 xen/arch/arm/cca/rmi.c    | 170 ++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/cca/rmi.h    | 126 ++++++++++++++++++++++++++++
 5 files changed, 312 insertions(+)
 create mode 100644 xen/arch/arm/cca/Makefile
 create mode 100644 xen/arch/arm/cca/rmi.c
 create mode 100644 xen/arch/arm/cca/rmi.h

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 79622b46a10d..dc99020c96de 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -118,6 +118,20 @@ config ARM_EFI
          UEFI firmware. A UEFI stub is provided to allow Xen to
          be booted as an EFI application.
 
+config ARM_CCA
+       bool "Arm Confidential Compute Architecture support (UNSUPPORTED)" if 
UNSUPPORTED
+       depends on ARM_64 && MMU
+       default n
+       help
+         Build Xen's Arm CCA / RMM support for Arm Realm guests on
+         Armv9 platforms.
+
+         This enables the NS hypervisor-side Realm creation and execution
+         paths, including the RMI ABI wrappers, Realm build/finalize
+         flows and REC run loop.
+
+         This support is experimental. If unsure, say N.
+
 config GICV2
        bool "GICv2 driver"
        default y
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 982c6c396a05..953dcbbe6626 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -8,6 +8,7 @@ ifneq ($(CONFIG_NO_PLAT),y)
 obj-y += platforms/
 endif
 obj-y += firmware/
+obj-$(CONFIG_ARM_CCA) += cca/
 obj-$(CONFIG_TEE) += tee/
 obj-$(CONFIG_HAS_VPCI) += vpci.o
 
diff --git a/xen/arch/arm/cca/Makefile b/xen/arch/arm/cca/Makefile
new file mode 100644
index 000000000000..9c351f901dfd
--- /dev/null
+++ b/xen/arch/arm/cca/Makefile
@@ -0,0 +1 @@
+obj-y += rmi.o
diff --git a/xen/arch/arm/cca/rmi.c b/xen/arch/arm/cca/rmi.c
new file mode 100644
index 000000000000..d37f1226f834
--- /dev/null
+++ b/xen/arch/arm/cca/rmi.c
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Internal Xen RMI command wrappers for DEN0137 2.0-bet1 / RMI v2.0.
+ */
+
+#include <xen/errno.h>
+
+#include <asm/processor.h>
+#include <asm/smccc.h>
+
+#include "rmi.h"
+
+#define ARM_CCA_RMI_INITIATE_SRO_BUSY_RETRIES 1000000U
+
+static void arm_cca_rmi_invoke(unsigned long fid,
+                               unsigned long arg0,
+                               unsigned long arg1,
+                               unsigned long arg2,
+                               unsigned long arg3,
+                               unsigned long arg4,
+                               struct arm_smccc_res *res)
+{
+    arm_smccc_1_0_smc(fid, arg0, arg1, arg2, arg3, arg4, 0, 0, res);
+}
+
+static int arm_cca_rmi_initiate_sro(unsigned long fid,
+                                    unsigned long arg0,
+                                    unsigned long arg1,
+                                    unsigned long arg2,
+                                    unsigned long arg3,
+                                    unsigned long arg4,
+                                    struct arm_smccc_res *res)
+{
+    unsigned int retries = 0;
+
+    /*
+     * Conform to DEN0137 2.0-bet1 B4.3.2.5 Programming model for an SRO:
+     * retry the initiating command while it returns RMI_BUSY.  Once a handle
+     * is returned, progress is driven through RMI_OP_CONTINUE.
+     *
+     * Initial RMI_BUSY is expected to be transient.  Keep the retry loop
+     * finite so a broken RMM cannot spin Xen forever.
+     */
+    while ( true )
+    {
+        arm_cca_rmi_invoke(fid, arg0, arg1, arg2, arg3, arg4, res);
+
+        if ( !arm_cca_rmi_status_is(arm_cca_rmi_result(res),
+                                    ARM_CCA_RMI_BUSY) )
+            return 0;
+
+        if ( retries == ARM_CCA_RMI_INITIATE_SRO_BUSY_RETRIES )
+            return -EBUSY;
+        retries++;
+
+        cpu_relax();
+    }
+}
+int arm_cca_rmi_version(unsigned long requested_revision,
+                        unsigned long *revision_lower,
+                        unsigned long *revision_higher)
+{
+    struct arm_smccc_res res;
+    int rc;
+
+    arm_cca_rmi_invoke(ARM_CCA_RMI_VERSION_FID,
+                       requested_revision, 0, 0, 0, 0, &res);
+
+    rc = arm_cca_rmi_res_to_errno(&res);
+
+    if ( revision_lower != NULL )
+        *revision_lower = res.a1;
+
+    if ( revision_higher != NULL )
+        *revision_higher = res.a2;
+
+    return rc;
+}
+
+unsigned long arm_cca_rmi_features(unsigned long index)
+{
+    struct arm_smccc_res res;
+
+    arm_cca_rmi_invoke(ARM_CCA_RMI_FEATURES_FID, index, 0, 0, 0, 0, &res);
+
+    return arm_cca_rmi_res_to_errno(&res) ? 0 : res.a1;
+}
+
+int arm_cca_rmi_rmm_config_get(paddr_t cfg_ptr, struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_RMM_CONFIG_GET_FID,
+                       cfg_ptr, 0, 0, 0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_rmm_config_set(paddr_t cfg_ptr)
+{
+    struct arm_smccc_res res;
+
+    arm_cca_rmi_invoke(ARM_CCA_RMI_RMM_CONFIG_SET_FID,
+                       cfg_ptr, 0, 0, 0, 0, &res);
+
+    return arm_cca_rmi_res_to_errno(&res);
+}
+
+int arm_cca_rmi_rmm_activate(struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_RMM_ACTIVATE_FID,
+                                  0, 0, 0, 0, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_granule_tracking_get(paddr_t base, paddr_t top,
+                                     unsigned long *category,
+                                     unsigned long *state, paddr_t *out_top)
+{
+    struct arm_smccc_res res;
+    int rc;
+
+    arm_cca_rmi_invoke(ARM_CCA_RMI_GRANULE_TRACKING_GET_FID,
+                       base, top, 0, 0, 0, &res);
+
+    rc = arm_cca_rmi_res_to_errno(&res);
+    if ( rc != 0 )
+        return rc;
+
+    /*
+     * Note that X3 is not defined by DEN0137 2.0-bet1 B4.5.10.1.3.  The
+     * tested TF-RMM v2.0 PoC branch, also followed by the KVM host series,
+     * returns range progress there.
+     */
+    *category = res.a1;
+    *state = res.a2;
+    *out_top = res.a3;
+
+    return 0;
+}
+
+int arm_cca_rmi_gpt_l1_create(paddr_t base)
+{
+    struct arm_smccc_res res;
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_GPT_L1_CREATE_FID,
+                                  base, 0, 0, 0, 0, &res);
+    if ( rc != 0 )
+        return rc;
+
+    if ( arm_cca_rmi_is_success(&res) ||
+         arm_cca_rmi_status_is(arm_cca_rmi_result(&res),
+                               ARM_CCA_RMI_ERROR_GPT) )
+        return 0;
+
+    /*
+     * Xen CCA supports immediate GPT L1 creation, or an existing GPT L1
+     * reported as RMI_ERROR_GPT.  If creation needs a memory-transferring
+     * SRO, leave CCA unavailable for now.
+     */
+    if ( arm_cca_rmi_status_is(arm_cca_rmi_result(&res),
+                               ARM_CCA_RMI_INCOMPLETE) )
+        return -EOPNOTSUPP;
+
+    return arm_cca_rmi_res_to_errno(&res);
+}
diff --git a/xen/arch/arm/cca/rmi.h b/xen/arch/arm/cca/rmi.h
new file mode 100644
index 000000000000..4cd0bc64ccf5
--- /dev/null
+++ b/xen/arch/arm/cca/rmi.h
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Internal Xen RMI command API.
+ *
+ * This header exposes typed wrappers and helpers for the subset of RMI
+ * commands used by Xen. Raw ABI constants live in rmi-abi.h.
+ */
+#ifndef ARM_CCA_RMI_H
+#define ARM_CCA_RMI_H
+
+#include <xen/bitops.h>
+#include <xen/bug.h>
+#include <xen/errno.h>
+#include <xen/page-size.h>
+
+#include <asm/smccc.h>
+
+#include "rmi-abi.h"
+
+static inline uint64_t arm_cca_rmi_field_get(uint64_t value,
+                                             unsigned int shift,
+                                             unsigned int width)
+{
+    ASSERT(width != 0 && shift < 64U && width <= 64U - shift);
+
+    return (value & GENMASK_ULL(shift + width - 1, shift)) >> shift;
+}
+
+static inline uint64_t arm_cca_rmi_result(const struct arm_smccc_res *res)
+{
+    return res->a0;
+}
+
+static inline bool arm_cca_rmi_is_success(const struct arm_smccc_res *res)
+{
+    return arm_cca_rmi_result(res) == ARM_CCA_RMI_SUCCESS;
+}
+
+static inline bool arm_cca_rmi_result_is_smccc_unknown(uint64_t result)
+{
+    return result == (uint64_t)ARM_SMCCC_ERR_UNKNOWN_FUNCTION;
+}
+
+static inline unsigned int arm_cca_rmi_status_code(uint64_t result)
+{
+    return arm_cca_rmi_field_get(result, ARM_CCA_RMI_RESULT_STATUS_SHIFT,
+                                 ARM_CCA_RMI_RESULT_STATUS_WIDTH);
+}
+
+static inline uint64_t arm_cca_rmi_result_data(uint64_t result)
+{
+    return result >> ARM_CCA_RMI_RESULT_DATA_SHIFT;
+}
+
+static inline bool arm_cca_rmi_status_is(uint64_t result, unsigned int status)
+{
+    return arm_cca_rmi_status_code(result) == status;
+}
+
+static inline bool arm_cca_rmi_status_is_error(uint64_t result)
+{
+    unsigned int status;
+
+    if ( arm_cca_rmi_result_is_smccc_unknown(result) )
+        return false;
+
+    status = arm_cca_rmi_status_code(result);
+
+    switch ( status )
+    {
+    case ARM_CCA_RMI_ERROR_INPUT:
+    case ARM_CCA_RMI_ERROR_REALM:
+    case ARM_CCA_RMI_ERROR_REC:
+    case ARM_CCA_RMI_ERROR_RTT:
+    case ARM_CCA_RMI_ERROR_NOT_SUPPORTED:
+    case ARM_CCA_RMI_ERROR_DEVICE:
+    case ARM_CCA_RMI_ERROR_RTT_AUX:
+    case ARM_CCA_RMI_ERROR_PSMMU_ST:
+    case ARM_CCA_RMI_ERROR_DPT:
+    case ARM_CCA_RMI_ERROR_GLOBAL:
+    case ARM_CCA_RMI_ERROR_TRACKING:
+    case ARM_CCA_RMI_ERROR_GPT:
+    case ARM_CCA_RMI_ERROR_GRANULE:
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+static inline int arm_cca_rmi_result_to_errno(uint64_t result)
+{
+    /*
+     * SRO progress states are not errno failures.  The SRO helpers keep
+     * inspecting the raw result in X0 through struct arm_smccc_res.
+     */
+    if ( result == ARM_CCA_RMI_SUCCESS ||
+         arm_cca_rmi_status_is(result, ARM_CCA_RMI_INCOMPLETE) ||
+         arm_cca_rmi_status_is(result, ARM_CCA_RMI_BUSY) )
+        return 0;
+
+    if ( arm_cca_rmi_result_is_smccc_unknown(result) ||
+         arm_cca_rmi_status_is(result, ARM_CCA_RMI_ERROR_NOT_SUPPORTED) )
+        return -EOPNOTSUPP;
+
+    return -EIO;
+}
+
+static inline int arm_cca_rmi_res_to_errno(const struct arm_smccc_res *res)
+{
+    return arm_cca_rmi_result_to_errno(arm_cca_rmi_result(res));
+}
+int arm_cca_rmi_version(unsigned long requested_revision,
+                        unsigned long *revision_lower,
+                        unsigned long *revision_higher);
+unsigned long arm_cca_rmi_features(unsigned long index);
+int arm_cca_rmi_rmm_config_get(paddr_t cfg_ptr, struct arm_smccc_res *res);
+int arm_cca_rmi_rmm_config_set(paddr_t cfg_ptr);
+int arm_cca_rmi_rmm_activate(struct arm_smccc_res *res);
+
+int arm_cca_rmi_granule_tracking_get(paddr_t base, paddr_t top,
+                                     unsigned long *category,
+                                     unsigned long *state, paddr_t *out_top);
+int arm_cca_rmi_gpt_l1_create(paddr_t base);
+
+#endif /* ARM_CCA_RMI_H */
-- 
2.51.0




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.