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

[RFC PATCH v1 03/26] xen/arm/cca: add RMI v2.0 lifecycle wrappers


  • To: xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Koichiro Den <den@xxxxxxxxxxxxx>
  • Date: Fri, 15 May 2026 13:07:49 +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=vAyjwFNK4w1A5HZVai7iWdh30Be5cNwrdAR6jGy2XIc=; b=Z50oCDTnpGtzwpC1QfdNgCWghQZ38YhxL632nerZXi5VVrelPgxgue0yYENBy5APj9uU3lh/ogQ+K/wa5i4M5kGFoA0jhUjnw59OJk+SEG1p7cUQXwiW0IswV/Kd5D9c9/0puZoU3aBxfnTZwtXh41+/P8Meuj7V4zULop0WW8J/LAHbpfvxAOiqRnKqdZ+wL+McGJqeYmKw+4Ona4pRdXpgQTavmcYOACt/mVrl69P3wy6hE+p6uyveaVmt9tRB9xe95hsGbcv5Jdw0c9eOyiVitid/JLf/h79cXB+mrsGbsg7iDA8LcsrkQjJhn9bNa2lpYdcWXVOARLL3UjBoBw==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=mxT8Nm01DxQ+CSw70GAGjBHeQDZxXsxCXvUdjgAcAGQFDrnjRvIPb0v5dR82AbK4mU/ZmxiImCppKI9kVkSdm2au34w1ivelCkTrvbhmPJvBmSU0el0AmtUExCSChoQW5mLQ2B5+r0bPWP1TomeGQ2t7VYQZbnRjZS8S2nTq8tluAhk7TndDOCgFkPm0tNVEbG6yT9Pi4pR1vL1fivWKEPNGC/VcaE3AZou/2LMVGkq/I9aoXGZkZG5vtfzKdnEYVkdepvS8Se+cbZ8ccDhD7ppyQ3dPc/6dgxYpT8SSf+iBhTk+Q/BNwY9Xq4UUUeJTKqenVRfmwLgbPDCA/Px6/w==
  • 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>

Wrap the Realm, REC, RTT, SRO and PSCI calls used by Xen. Keep the
stateful completion rules close to the raw RMI call boundary and avoid
code duplication.

Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
 xen/arch/arm/cca/rmi.c | 271 +++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/cca/rmi.h |  88 +++++++++++++
 2 files changed, 359 insertions(+)

diff --git a/xen/arch/arm/cca/rmi.c b/xen/arch/arm/cca/rmi.c
index d37f1226f834..5661d35e30da 100644
--- a/xen/arch/arm/cca/rmi.c
+++ b/xen/arch/arm/cca/rmi.c
@@ -56,6 +56,46 @@ static int arm_cca_rmi_initiate_sro(unsigned long fid,
         cpu_relax();
     }
 }
+
+static int arm_cca_rmi_complete_no_mem_transfer(struct arm_smccc_res *res)
+{
+    unsigned long handle;
+    uint64_t result = arm_cca_rmi_result(res);
+
+    if ( !arm_cca_rmi_status_is(result, ARM_CCA_RMI_INCOMPLETE) )
+        return arm_cca_rmi_result_to_errno(result);
+
+    /*
+     * The initiating command returns the SRO handle in X1.  Once
+     * the operation is continued, X1 is not a stable handle output:
+     * completion returns the initiating command's output registers.
+     *
+     * See DEN0137 2.0-bet1 - B4.3.2 and B4.3.2.1
+     */
+    handle = res->a1;
+
+    while ( arm_cca_rmi_status_is(result, ARM_CCA_RMI_INCOMPLETE) ||
+            arm_cca_rmi_status_is(result, ARM_CCA_RMI_BUSY) )
+    {
+        if ( arm_cca_rmi_status_is(result, ARM_CCA_RMI_INCOMPLETE) )
+        {
+            /*
+             * This helper is only for commands specified as stateful but not
+             * memory-transferring.  Callers with donate/reclaim flows handle 
SROs
+             * themselves because they must own the backing-page lifetime.
+             */
+            if ( arm_cca_rmi_sro_mem_req(result) !=
+                 ARM_CCA_RMI_OP_MEM_REQ_NONE )
+                return -EOPNOTSUPP;
+        }
+
+        arm_cca_rmi_op_continue(handle, ARM_CCA_RMI_CONTINUE_KEEP_GOING, res);
+        result = arm_cca_rmi_result(res);
+    }
+
+    return arm_cca_rmi_result_to_errno(result);
+}
+
 int arm_cca_rmi_version(unsigned long requested_revision,
                         unsigned long *revision_lower,
                         unsigned long *revision_higher)
@@ -168,3 +208,234 @@ int arm_cca_rmi_gpt_l1_create(paddr_t base)
 
     return arm_cca_rmi_res_to_errno(&res);
 }
+
+int arm_cca_rmi_granule_range_delegate(paddr_t base, paddr_t top,
+                                       paddr_t *out_top)
+{
+    struct arm_smccc_res res;
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_GRANULE_RANGE_DELEGATE_FID,
+                                  base, top, 0, 0, 0, &res);
+    if ( rc != 0 )
+        return rc;
+
+    rc = arm_cca_rmi_complete_no_mem_transfer(&res);
+    if ( rc == 0 && out_top != NULL )
+        *out_top = res.a1;
+
+    return rc;
+}
+
+int arm_cca_rmi_granule_range_undelegate(paddr_t base, paddr_t top,
+                                         paddr_t *out_top)
+{
+    struct arm_smccc_res res;
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_GRANULE_RANGE_UNDELEGATE_FID,
+                                  base, top, 0, 0, 0, &res);
+    if ( rc != 0 )
+        return rc;
+
+    rc = arm_cca_rmi_complete_no_mem_transfer(&res);
+    if ( rc == 0 && out_top != NULL )
+        *out_top = res.a1;
+
+    return rc;
+}
+
+int arm_cca_rmi_realm_create(paddr_t rd, paddr_t params_ptr,
+                             struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_REALM_CREATE_FID,
+                                  rd, params_ptr, 0, 0, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_realm_activate(paddr_t rd, struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_REALM_ACTIVATE_FID, rd, 0, 0, 0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_realm_terminate(paddr_t rd, struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_REALM_TERMINATE_FID,
+                                  rd, 0, 0, 0, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    rc = arm_cca_rmi_res_to_errno(res);
+
+    if ( !arm_cca_rmi_status_is(arm_cca_rmi_result(res),
+                                ARM_CCA_RMI_INCOMPLETE) )
+        return rc;
+
+    return arm_cca_rmi_complete_no_mem_transfer(res);
+}
+
+int arm_cca_rmi_realm_destroy(paddr_t rd, struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_REALM_DESTROY_FID,
+                                  rd, 0, 0, 0, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_rec_create(paddr_t rd, paddr_t rec, paddr_t params_ptr,
+                           struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_REC_CREATE_FID,
+                                  rd, rec, params_ptr, 0, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_rec_destroy(paddr_t rec, struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_REC_DESTROY_FID,
+                                  rec, 0, 0, 0, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_rec_enter(paddr_t rec, paddr_t run, struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_REC_ENTER_FID, rec, run, 0, 0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_op_continue(unsigned long handle, unsigned long flags,
+                            struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_OP_CONTINUE_FID,
+                       handle, flags, 0, 0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_op_cancel(unsigned long handle, struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_OP_CANCEL_FID, handle, 0, 0, 0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_op_mem_donate(unsigned long handle, paddr_t list,
+                              unsigned long list_count,
+                              struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_OP_MEM_DONATE_FID,
+                       handle, list, list_count, 0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_op_mem_reclaim(unsigned long handle, paddr_t list,
+                               unsigned long list_count,
+                               struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_OP_MEM_RECLAIM_FID,
+                       handle, list, list_count, 0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
+
+int arm_cca_rmi_rtt_create(paddr_t rd, paddr_t rtt, paddr_t ipa,
+                           unsigned long level, struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_RTT_CREATE_FID,
+                                  rd, rtt, ipa, level, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_complete_no_mem_transfer(res);
+}
+
+int arm_cca_rmi_rtt_destroy(paddr_t rd, paddr_t ipa, unsigned long level,
+                            struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_RTT_DESTROY_FID,
+                                  rd, ipa, level, 0, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_complete_no_mem_transfer(res);
+}
+
+int arm_cca_rmi_rtt_set_ripas(paddr_t rd, paddr_t rec, paddr_t base,
+                              paddr_t top, struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_RTT_SET_RIPAS_FID,
+                                  rd, rec, base, top, 0, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_complete_no_mem_transfer(res);
+}
+
+int arm_cca_rmi_rtt_data_map_init(paddr_t rd, paddr_t data, paddr_t ipa,
+                                  paddr_t src, unsigned long flags,
+                                  struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_RTT_DATA_MAP_INIT_FID,
+                                  rd, data, ipa, src, flags, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_complete_no_mem_transfer(res);
+}
+
+int arm_cca_rmi_rtt_data_unmap(paddr_t rd, paddr_t base, paddr_t top,
+                               unsigned long flags, unsigned long oaddr,
+                               struct arm_smccc_res *res)
+{
+    int rc;
+
+    rc = arm_cca_rmi_initiate_sro(ARM_CCA_RMI_RTT_DATA_UNMAP_FID,
+                                  rd, base, top, flags, oaddr, res);
+    if ( rc != 0 )
+        return rc;
+
+    return arm_cca_rmi_complete_no_mem_transfer(res);
+}
+
+int arm_cca_rmi_psci_complete(paddr_t calling_rec, paddr_t target_rec,
+                              int64_t status, struct arm_smccc_res *res)
+{
+    arm_cca_rmi_invoke(ARM_CCA_RMI_PSCI_COMPLETE_FID,
+                       calling_rec, target_rec, (unsigned long)status,
+                       0, 0, res);
+
+    return arm_cca_rmi_res_to_errno(res);
+}
diff --git a/xen/arch/arm/cca/rmi.h b/xen/arch/arm/cca/rmi.h
index 4cd0bc64ccf5..589c12b24e79 100644
--- a/xen/arch/arm/cca/rmi.h
+++ b/xen/arch/arm/cca/rmi.h
@@ -110,6 +110,51 @@ 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));
 }
+
+static inline unsigned long arm_cca_rmi_sro_mem_req(uint64_t result)
+{
+    uint64_t incomplete_data = arm_cca_rmi_result_data(result);
+
+    return arm_cca_rmi_field_get(
+        incomplete_data, ARM_CCA_RMI_RESULT_INCOMPLETE_MEM_SHIFT,
+        ARM_CCA_RMI_RESULT_INCOMPLETE_MEM_WIDTH);
+}
+
+static inline bool arm_cca_rmi_sro_can_cancel(uint64_t result)
+{
+    uint64_t incomplete_data = arm_cca_rmi_result_data(result);
+
+    return arm_cca_rmi_field_get(
+        incomplete_data, ARM_CCA_RMI_RESULT_INCOMPLETE_CAN_CANCEL_SHIFT,
+        ARM_CCA_RMI_RESULT_INCOMPLETE_CAN_CANCEL_WIDTH) ==
+           ARM_CCA_RMI_OP_CAN_CANCEL;
+}
+
+static inline paddr_t arm_cca_rmi_addr_desc_4k_pa(uint64_t desc)
+{
+    return arm_cca_rmi_field_get(desc, ARM_CCA_RMI_ADDR_DESC_4K_ADDR_SHIFT,
+                                 ARM_CCA_RMI_ADDR_DESC_4K_ADDR_WIDTH)
+           << PAGE_SHIFT;
+}
+
+static inline unsigned long arm_cca_rmi_addr_desc_4k_size(uint64_t desc)
+{
+    return arm_cca_rmi_field_get(desc, ARM_CCA_RMI_ADDR_DESC_4K_SZ_SHIFT,
+                                 ARM_CCA_RMI_ADDR_DESC_4K_SZ_WIDTH);
+}
+
+static inline unsigned long arm_cca_rmi_addr_desc_4k_count(uint64_t desc)
+{
+    return arm_cca_rmi_field_get(desc, ARM_CCA_RMI_ADDR_DESC_4K_CNT_SHIFT,
+                                 ARM_CCA_RMI_ADDR_DESC_4K_CNT_WIDTH);
+}
+
+static inline unsigned long arm_cca_rmi_addr_desc_4k_state(uint64_t desc)
+{
+    return arm_cca_rmi_field_get(desc, ARM_CCA_RMI_ADDR_DESC_4K_ST_SHIFT,
+                                 ARM_CCA_RMI_ADDR_DESC_4K_ST_WIDTH);
+}
+
 int arm_cca_rmi_version(unsigned long requested_revision,
                         unsigned long *revision_lower,
                         unsigned long *revision_higher);
@@ -123,4 +168,47 @@ int arm_cca_rmi_granule_tracking_get(paddr_t base, paddr_t 
top,
                                      unsigned long *state, paddr_t *out_top);
 int arm_cca_rmi_gpt_l1_create(paddr_t base);
 
+int arm_cca_rmi_granule_range_delegate(paddr_t base, paddr_t top,
+                                       paddr_t *out_top);
+int arm_cca_rmi_granule_range_undelegate(paddr_t base, paddr_t top,
+                                         paddr_t *out_top);
+
+int arm_cca_rmi_realm_create(paddr_t rd, paddr_t params_ptr,
+                             struct arm_smccc_res *res);
+int arm_cca_rmi_realm_activate(paddr_t rd, struct arm_smccc_res *res);
+int arm_cca_rmi_realm_terminate(paddr_t rd, struct arm_smccc_res *res);
+int arm_cca_rmi_realm_destroy(paddr_t rd, struct arm_smccc_res *res);
+
+int arm_cca_rmi_rec_create(paddr_t rd, paddr_t rec, paddr_t params_ptr,
+                           struct arm_smccc_res *res);
+int arm_cca_rmi_rec_destroy(paddr_t rec, struct arm_smccc_res *res);
+int arm_cca_rmi_rec_enter(paddr_t rec, paddr_t run, struct arm_smccc_res *res);
+
+int arm_cca_rmi_op_continue(unsigned long handle, unsigned long flags,
+                            struct arm_smccc_res *res);
+int arm_cca_rmi_op_cancel(unsigned long handle, struct arm_smccc_res *res);
+int arm_cca_rmi_op_mem_donate(unsigned long handle, paddr_t list,
+                              unsigned long list_count,
+                              struct arm_smccc_res *res);
+int arm_cca_rmi_op_mem_reclaim(unsigned long handle, paddr_t list,
+                               unsigned long list_count,
+                               struct arm_smccc_res *res);
+
+int arm_cca_rmi_rtt_create(paddr_t rd, paddr_t rtt, paddr_t ipa,
+                           unsigned long level, struct arm_smccc_res *res);
+int arm_cca_rmi_rtt_destroy(paddr_t rd, paddr_t ipa, unsigned long level,
+                            struct arm_smccc_res *res);
+int arm_cca_rmi_rtt_set_ripas(paddr_t rd, paddr_t rec, paddr_t base,
+                              paddr_t top, struct arm_smccc_res *res);
+
+int arm_cca_rmi_rtt_data_map_init(paddr_t rd, paddr_t data, paddr_t ipa,
+                                  paddr_t src, unsigned long flags,
+                                  struct arm_smccc_res *res);
+int arm_cca_rmi_rtt_data_unmap(paddr_t rd, paddr_t base, paddr_t top,
+                               unsigned long flags, unsigned long oaddr,
+                               struct arm_smccc_res *res);
+
+int arm_cca_rmi_psci_complete(paddr_t calling_rec, paddr_t target_rec,
+                              int64_t status, struct arm_smccc_res *res);
+
 #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®.