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 <[email protected]>
---
 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


Reply via email to