@@ -959,6 +959,7 @@ enum {
PROG_xen,
PROG_page,
PROG_mapping,
+ PROG_p2m_root,
PROG_p2m,
PROG_p2m_pool,
PROG_done,
@@ -1021,6 +1022,13 @@ int domain_relinquish_resources(struct domain *d)
if ( ret )
return ret;
+ PROGRESS(p2m_root):
+ /*
+ * We are about to free the intermediate page-tables, so clear the
+ * root to prevent any walk to use them.
+ */
+ p2m_clear_root_pages(&d->arch.p2m);
+
PROGRESS(p2m):
ret = p2m_teardown(d, true);
if ( ret )
@@ -281,6 +281,7 @@ int p2m_set_entry(struct p2m_domain *p2m,
bool p2m_resolve_translation_fault(struct domain *d, gfn_t gfn);
+void p2m_clear_root_pages(struct p2m_domain *p2m);
void p2m_invalidate_root(struct p2m_domain *p2m);
/*
@@ -1314,6 +1314,26 @@ static void p2m_invalidate_table(struct p2m_domain *p2m, mfn_t mfn)
p2m->need_flush = true;
}
+/*
+ * The domain will not be scheduled anymore, so in theory we should
+ * not need to flush the TLBs. Do it for safety purpose.
+ * Note that all the devices have already been de-assigned. So we don't
+ * need to flush the IOMMU TLB here.
+ */
+void p2m_clear_root_pages(struct p2m_domain *p2m)
+{
+ unsigned int i;
+
+ p2m_write_lock(p2m);
+
+ for ( i = 0; i < P2M_ROOT_PAGES; i++ )
+ clear_and_clean_page(p2m->root + i);
+
+ p2m_force_tlb_flush_sync(p2m);
+
+ p2m_write_unlock(p2m);
+}
+
/*
* Invalidate all entries in the root page-tables. This is
* useful to get fault on entry and do an action.
@@ -1698,30 +1718,10 @@ int p2m_teardown(struct domain *d, bool allow_preemption)
struct p2m_domain *p2m = p2m_get_hostp2m(d);
unsigned long count = 0;
struct page_info *pg;
- unsigned int i;
int rc = 0;
- if ( page_list_empty(&p2m->pages) )
- return 0;
-
p2m_write_lock(p2m);
- /*
- * We are about to free the intermediate page-tables, so clear the
- * root to prevent any walk to use them.
- */
- for ( i = 0; i < P2M_ROOT_PAGES; i++ )
- clear_and_clean_page(p2m->root + i);
-
- /*
- * The domain will not be scheduled anymore, so in theory we should
- * not need to flush the TLBs. Do it for safety purpose.
- *
- * Note that all the devices have already been de-assigned. So we don't
- * need to flush the IOMMU TLB here.
- */
- p2m_force_tlb_flush_sync(p2m);
-
while ( (pg = page_list_remove_head(&p2m->pages)) )
{
p2m_free_page(p2m->domain, pg);