Index: xen-3.2.1-testing/xen/arch/x86/domain.c =================================================================== --- xen-3.2.1-testing.orig/xen/arch/x86/domain.c +++ xen-3.2.1-testing/xen/arch/x86/domain.c @@ -1709,6 +1709,23 @@ static int relinquish_memory( if ( test_and_clear_bit(_PGC_allocated, &page->count_info) ) put_page(page); + y = page->u.inuse.type_info; + + /* + * Forcibly drop reference counts of page tables above top most (which + * were skipped to prevent long latencies due to deep recursion - see + * the special treatment in free_lX_table()). + */ + if ( type < PGT_root_page_table && + unlikely(((y + PGT_type_mask) & + (PGT_type_mask|PGT_validated)) == type) ) { + BUG_ON((y & PGT_count_mask) >= (page->count_info & PGC_count_mask)); + while ( y & PGT_count_mask ) { + put_page_and_type(page); + y = page->u.inuse.type_info; + } + } + /* * Forcibly invalidate top-most, still valid page tables at this point * to break circular 'linear page table' references. This is okay @@ -1716,7 +1733,6 @@ static int relinquish_memory( * is now dead. Thus top-most valid tables are not in use so a non-zero * count means circular reference. */ - y = page->u.inuse.type_info; for ( ; ; ) { x = y; @@ -1880,6 +1896,9 @@ int domain_relinquish_resources(struct d /* fallthrough */ case RELMEM_done: + ret = relinquish_memory(d, &d->page_list, PGT_l1_page_table); + if ( ret ) + return ret; break; default: Index: xen-3.2.1-testing/xen/arch/x86/mm.c =================================================================== --- xen-3.2.1-testing.orig/xen/arch/x86/mm.c +++ xen-3.2.1-testing/xen/arch/x86/mm.c @@ -1305,6 +1305,9 @@ static void free_l3_table(struct page_in l3_pgentry_t *pl3e; int i; + if(d->arch.relmem == RELMEM_dom_l3) + return; + pl3e = map_domain_page(pfn); for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) @@ -1328,6 +1331,9 @@ static void free_l4_table(struct page_in l4_pgentry_t *pl4e = page_to_virt(page); int i; + if(d->arch.relmem == RELMEM_dom_l4) + return; + for ( i = 0; i < L4_PAGETABLE_ENTRIES; i++ ) if ( is_guest_l4_slot(d, i) ) put_page_from_l4e(pl4e[i], pfn);