Destroy each REC, reclaim its auxiliary pages through SRO, then release the REC granule after the RMM has returned it.
Signed-off-by: Koichiro Den <[email protected]> --- xen/arch/arm/cca/state.c | 81 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/xen/arch/arm/cca/state.c b/xen/arch/arm/cca/state.c index c85ef56a1297..72dbb83841d7 100644 --- a/xen/arch/arm/cca/state.c +++ b/xen/arch/arm/cca/state.c @@ -122,6 +122,22 @@ static int arm_cca_relinquish_abandoned_pages(struct domain *d) return 0; } +static int arm_cca_rmi_rec_destroy_complete(struct vcpu *v) +{ + struct arm_cca_sro_mem_xfer xfer = { + .pages = v->arch.cca.aux_pages, + .nr_pages = &v->arch.cca.nr_aux, + .abandoned_pages = &v->domain->arch.cca.abandoned_pages, + }; + struct arm_smccc_res res; + int rc; + + rc = arm_cca_rmi_rec_destroy(v->arch.cca.rec, &res); + rc = arm_cca_sro_complete_mem_transfer(rc, &res, &xfer); + + return rc; +} + static int arm_cca_rmi_realm_destroy_complete(struct domain *d) { struct arm_cca_sro_mem_xfer xfer = { @@ -269,6 +285,67 @@ static int arm_cca_teardown_rtts(struct domain *d) return 0; } +static int arm_cca_vcpu_free_rec_page(struct vcpu *v) +{ + int rc; + + if ( !v->arch.cca.rec_page ) + return 0; + + rc = arm_cca_undelegate_granule(page_to_maddr(v->arch.cca.rec_page)); + if ( rc != 0 ) + return rc; + + free_domheap_page(v->arch.cca.rec_page); + v->arch.cca.rec_page = NULL; + + return 0; +} + +static int arm_cca_vcpu_relinquish_resources(struct vcpu *v) +{ + int rc; + + if ( v->arch.cca.rec != INVALID_PADDR ) + { + rc = arm_cca_rmi_rec_destroy_complete(v); + if ( rc != 0 ) + return rc; + + v->arch.cca.rec = INVALID_PADDR; + } + + /* + * arm_cca_sro_complete_mem_transfer() consumes REC_DESTROY reclaim + * requests. Remaining REC auxiliary pages would mean Xen cannot prove + * that the granules have been returned by the RMM. + */ + if ( v->arch.cca.nr_aux != 0 ) + return -EIO; + + return arm_cca_vcpu_free_rec_page(v); +} + +static int arm_cca_teardown_recs(struct domain *d) +{ + unsigned int i; + int rc; + + for ( i = 0; i < d->max_vcpus; ++i ) + { + struct vcpu *v = d->vcpu[i]; + + if ( v == NULL ) + continue; + + rc = arm_cca_vcpu_relinquish_resources(v); + if ( rc != 0 ) + return rc; + } + + return 0; +} + static int arm_cca_destroy_realm(struct domain *d) { int rc; @@ -330,6 +407,10 @@ int arm_cca_domain_relinquish_resources(struct domain *d) if ( rc != 0 ) return rc; + rc = arm_cca_teardown_recs(d); + if ( rc != 0 ) + return rc; + rc = arm_cca_destroy_realm(d); if ( rc != 0 ) return rc; -- 2.51.0
