|
[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
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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |