|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [RFC PATCH v1 12/26] xen/arm/cca: tear down Realm DATA and RTT granules
Tear down mapped DATA granules and the RTT hierarchy before returning
the backing pages to Xen.
Signed-off-by: Koichiro Den <den@xxxxxxxxxxxxx>
---
xen/arch/arm/cca/state.c | 151 +++++++++++++++++++++++++++++++++
xen/arch/arm/include/asm/cca.h | 1 +
2 files changed, 152 insertions(+)
diff --git a/xen/arch/arm/cca/state.c b/xen/arch/arm/cca/state.c
index e58e261265f3..c85ef56a1297 100644
--- a/xen/arch/arm/cca/state.c
+++ b/xen/arch/arm/cca/state.c
@@ -1,15 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#include <xen/errno.h>
#include <xen/lib.h>
#include <xen/mm.h>
#include <xen/sched.h>
#include <xen/xmalloc.h>
#include <asm/cca.h>
+#include <asm/event.h>
#include "rmi.h"
#include "sro.h"
+#define ARM_CCA_RTT_DATA_UNMAP_BATCH 1024UL
+
static void arm_cca_reset_domain_state(struct domain *d)
{
unsigned int i;
@@ -26,6 +30,7 @@ static void arm_cca_reset_domain_state(struct domain *d)
d->arch.cca.nr_rtts = 0;
d->arch.cca.data_pages = NULL;
d->arch.cca.nr_data_pages = 0;
+ d->arch.cca.relinquish_data_idx = 0;
d->arch.cca.realm_terminate_done = false;
for ( i = 0; i < ARRAY_SIZE(d->arch.cca.realm_sro_pages); ++i )
@@ -51,6 +56,37 @@ void arm_cca_domain_init(struct domain *d)
arm_cca_reset_domain_state(d);
}
+static int
+arm_cca_rtt_data_unmap_4k(paddr_t rd,
+ const struct arm_cca_data_page_record *rec)
+{
+ struct arm_smccc_res res;
+ paddr_t top = rec->ipa + PAGE_SIZE;
+ uint64_t desc;
+ int rc;
+
+ /*
+ * DEN0137 2.0-bet1 marks SINGLE oaddr as SBZ, and TF-RMM does not use it,
+ * so keep X5 zero here.
+ */
+ rc = arm_cca_rmi_rtt_data_unmap(rd, rec->ipa, top,
+ ARM_CCA_RMI_ADDR_TYPE_SINGLE, 0, &res);
+ if ( rc != 0 )
+ return rc;
+
+ desc = res.a2;
+
+ if ( res.a1 != top ||
+ arm_cca_rmi_addr_desc_4k_pa(desc) != rec->pa ||
+ arm_cca_rmi_addr_desc_4k_size(desc) != ARM_CCA_RMI_PAGE_L3 ||
+ arm_cca_rmi_addr_desc_4k_count(desc) != 1 ||
+ arm_cca_rmi_addr_desc_4k_state(desc) !=
+ ARM_CCA_RMI_OP_MEM_DELEGATED )
+ return -EIO;
+
+ return 0;
+}
+
static void arm_cca_domain_free_metadata(struct domain *d)
{
xfree(d->arch.cca.data_pages);
@@ -104,6 +140,68 @@ static int arm_cca_rmi_realm_destroy_complete(struct
domain *d)
return rc;
}
+static int arm_cca_teardown_data_pages(struct domain *d)
+{
+ unsigned long i;
+ int rc;
+
+ if ( !d->arch.cca.data_pages )
+ return 0;
+
+ for ( i = d->arch.cca.relinquish_data_idx;
+ i < d->arch.cca.nr_data_pages; ++i )
+ {
+ struct arm_cca_data_page_record *rec = &d->arch.cca.data_pages[i];
+
+ if ( rec->pa == INVALID_PADDR )
+ continue;
+
+ if ( rec->ipa != INVALID_PADDR )
+ {
+ if ( d->arch.cca.rd == INVALID_PADDR )
+ return -EIO;
+
+ rc = arm_cca_rtt_data_unmap_4k(d->arch.cca.rd, rec);
+ if ( rc != 0 )
+ {
+ d->arch.cca.relinquish_data_idx = i;
+ return rc;
+ }
+
+ /*
+ * The RTTE no longer owns this DATA granule. Keep rec->pa so a
+ * later retry can finish the host-side undelegation.
+ */
+ rec->ipa = INVALID_PADDR;
+ }
+
+ rc = arm_cca_undelegate_granule(rec->pa);
+ if ( rc != 0 )
+ {
+ d->arch.cca.relinquish_data_idx = i;
+ return rc;
+ }
+
+ /*
+ * The page remains owned by the domain and on d->page_list so the
+ * generic relinquish path can free it later.
+ */
+ rec->pa = INVALID_PADDR;
+
+ if ( ((i + 1) % ARM_CCA_RTT_DATA_UNMAP_BATCH) == 0 &&
+ hypercall_preempt_check() )
+ {
+ d->arch.cca.relinquish_data_idx = i + 1;
+ return -ERESTART;
+ }
+ }
+
+ d->arch.cca.nr_data_pages = 0;
+ d->arch.cca.relinquish_data_idx = 0;
+
+ return 0;
+}
+
static int arm_cca_terminate_realm(struct domain *d)
{
struct arm_smccc_res res;
@@ -126,6 +224,51 @@ static int arm_cca_terminate_realm(struct domain *d)
return 0;
}
+static int arm_cca_teardown_rtts(struct domain *d)
+{
+ struct arm_smccc_res res;
+ int rc;
+
+ while ( d->arch.cca.nr_rtts != 0 )
+ {
+ struct arm_cca_rtt_record *rec =
+ &d->arch.cca.rtts[d->arch.cca.nr_rtts - 1];
+
+ if ( rec->pa == INVALID_PADDR )
+ {
+ d->arch.cca.nr_rtts--;
+ continue;
+ }
+
+ if ( rec->ipa != INVALID_PADDR )
+ {
+ if ( d->arch.cca.rd == INVALID_PADDR )
+ return -EIO;
+
+ rc = arm_cca_rmi_rtt_destroy(d->arch.cca.rd, rec->ipa,
+ rec->level, &res);
+ if ( rc != 0 )
+ return rc;
+
+ /*
+ * The RMM object is gone. Keep rec->pa so a later retry can
+ * finish the host-side undelegation.
+ */
+ rec->ipa = INVALID_PADDR;
+ }
+
+ rc = arm_cca_undelegate_granule(rec->pa);
+ if ( rc != 0 )
+ return rc;
+
+ free_domheap_page(maddr_to_page(rec->pa));
+ rec->pa = INVALID_PADDR;
+ d->arch.cca.nr_rtts--;
+ }
+
+ return 0;
+}
+
static int arm_cca_destroy_realm(struct domain *d)
{
int rc;
@@ -179,6 +322,14 @@ int arm_cca_domain_relinquish_resources(struct domain *d)
if ( rc != 0 )
return rc;
+ rc = arm_cca_teardown_data_pages(d);
+ if ( rc != 0 )
+ return rc;
+
+ rc = arm_cca_teardown_rtts(d);
+ if ( rc != 0 )
+ return rc;
+
rc = arm_cca_destroy_realm(d);
if ( rc != 0 )
return rc;
diff --git a/xen/arch/arm/include/asm/cca.h b/xen/arch/arm/include/asm/cca.h
index b135dd176751..d69e95a10010 100644
--- a/xen/arch/arm/include/asm/cca.h
+++ b/xen/arch/arm/include/asm/cca.h
@@ -68,6 +68,7 @@ struct arm_cca_domain_state {
unsigned long nr_data_pages;
/* Realm destruction state for domain_relinquish_resources(). */
+ unsigned long relinquish_data_idx;
bool realm_terminate_done;
};
--
2.51.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |