|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH v1 16/26] xen/arm/cca: build Realm RTTs
Build the initial RTT tree in restartable chunks, recording each table
so Realm destruction can walk the reverse path later.
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
xen/arch/arm/cca/build.c | 139 +++++++++++++++++++++++++++++++++++++++
1 file changed, 139 insertions(+)
diff --git a/xen/arch/arm/cca/build.c b/xen/arch/arm/cca/build.c
index 66d9c88da161..10f61b5038ef 100644
--- a/xen/arch/arm/cca/build.c
+++ b/xen/arch/arm/cca/build.c
@@ -525,3 +525,142 @@ out:
return rc;
}
+
+static int arm_cca_create_rtt_table(struct domain *d, paddr_t ipa,
+ unsigned int level,
+ uint64_t *rmi_result)
+{
+ struct page_info *pg;
+ struct arm_smccc_res res;
+ int rc;
+ unsigned int idx = d->arch.cca.nr_rtts;
+
+ pg = arm_cca_alloc_host_page();
+ if ( !pg )
+ return -ENOMEM;
+
+ rc = arm_cca_delegate_granule(page_to_maddr(pg));
+ if ( rc != 0 )
+ goto err_free_page;
+
+ rc = arm_cca_rmi_rtt_create(d->arch.cca.rd, page_to_maddr(pg), ipa,
+ level, &res);
+ rc = arm_cca_build_record_rmi_failure(rmi_result, rc, &res);
+ if ( rc != 0 )
+ goto err_undelegate;
+
+ d->arch.cca.rtts[idx].ipa = ipa;
+ d->arch.cca.rtts[idx].pa = page_to_maddr(pg);
+ d->arch.cca.rtts[idx].level = level;
+ d->arch.cca.nr_rtts++;
+
+ return 0;
+
+err_undelegate:
+ arm_cca_free_or_abandon_build_page(d, pg, true);
+ return rc;
+err_free_page:
+ free_domheap_page(pg);
+ return rc;
+}
+
+static paddr_t arm_cca_rtt_span(unsigned int level)
+{
+ switch ( level )
+ {
+ case 1:
+ return ARM_CCA_L0_TABLE_SPAN;
+ case 2:
+ return ARM_CCA_L1_TABLE_SPAN;
+ case 3:
+ return ARM_CCA_L2_TABLE_SPAN;
+ default:
+ return 0;
+ }
+}
+
+static paddr_t arm_cca_rtt_start(paddr_t base, unsigned int level)
+{
+ return ROUNDDOWN(base, arm_cca_rtt_span(level));
+}
+
+static unsigned int arm_cca_count_rtt_tables(paddr_t base, paddr_t end)
+{
+ unsigned int level, nr_tables = 0;
+
+ for ( level = 1; level <= 3; level++ )
+ {
+ paddr_t span = arm_cca_rtt_span(level);
+
+ nr_tables += (unsigned int)((ROUNDUP(end, span) -
+ ROUNDDOWN(base, span)) / span);
+ }
+
+ return nr_tables;
+}
+
+static bool arm_cca_build_should_preempt(unsigned long work,
+ unsigned long soft_limit,
+ unsigned long hard_limit)
+{
+ if ( work < soft_limit )
+ return false;
+
+ return hypercall_preempt_check() || work >= hard_limit;
+}
+
+/*
+ * DEN0137 2.0-bet1 - D1.2.2 Realm Translation Table creation flow.
+ */
+static int arm_cca_build_rtts(struct domain *d, paddr_t base,
+ unsigned long nr_pages,
+ uint64_t *rmi_result)
+{
+ paddr_t end = base + nr_pages * PAGE_SIZE;
+ unsigned long work = 0;
+ int rc;
+
+ if ( !d->arch.cca.rtts )
+ {
+ unsigned int nr_tables = arm_cca_count_rtt_tables(base, end);
+
+ d->arch.cca.rtts = xzalloc_array(struct arm_cca_rtt_record, nr_tables);
+ if ( !d->arch.cca.rtts )
+ return -ENOMEM;
+
+ d->arch.cca.build_rtt_level = 1;
+ d->arch.cca.build_next_ipa = arm_cca_rtt_start(base, 1);
+ }
+
+ while ( d->arch.cca.build_rtt_level <= 3 )
+ {
+ unsigned int level = d->arch.cca.build_rtt_level;
+ paddr_t span = arm_cca_rtt_span(level);
+ paddr_t ipa = d->arch.cca.build_next_ipa;
+
+ if ( ipa >= end )
+ {
+ level++;
+ d->arch.cca.build_rtt_level = level;
+ if ( level <= 3 )
+ d->arch.cca.build_next_ipa = arm_cca_rtt_start(base, level);
+ continue;
+ }
+
+ rc = arm_cca_create_rtt_table(d, ipa, level, rmi_result);
+ if ( rc != 0 )
+ return rc;
+
+ d->arch.cca.build_next_ipa = ipa + span;
+
+ if ( arm_cca_build_should_preempt(++work,
+ ARM_CCA_BUILD_PREEMPT_TABLES,
+ ARM_CCA_BUILD_FORCE_PREEMPT_TABLES) )
+ return -ERESTART;
+ }
+
+ d->arch.cca.build_next_ipa = INVALID_PADDR;
+ d->arch.cca.build_rtt_level = 0;
+
+ return 0;
+}
--
2.51.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |