static struct page_info * __init alloc_chunk( struct domain *d, unsigned long max_pages) { static unsigned int __initdata last_order = MAX_ORDER; static unsigned int __initdata memflags = MEMF_no_dma; struct page_info *page; unsigned int order = get_order_from_pages(max_pages), free_order; if ( order > last_order ) order = last_order; else if ( max_pages & (max_pages - 1) ) --order; while ( (page = alloc_domheap_pages(d, order, memflags)) == NULL ) if ( order-- == 0 ) break; if ( page ) last_order = order; else if ( memflags ) { /* * Allocate up to 2MB at a time: It prevents allocating very large * chunks from DMA pools before the >4GB pool is fully depleted. */ last_order = 21 - PAGE_SHIFT; memflags = 0; return alloc_chunk(d, max_pages); } /* * Make a reasonable attempt at finding a smaller chunk at a higher * address, to avoid allocating from low memory as much as possible. */ for ( free_order = order; !memflags && page && order--; ) { struct page_info *pg2; if ( d->tot_pages + (1 << order) > d->max_pages ) continue; pg2 = alloc_domheap_pages(d, order, 0); if ( pg2 > page ) { free_domheap_pages(page, free_order); page = pg2; free_order = order; } else if ( pg2 ) free_domheap_pages(pg2, order); } return page; }
void p2m_teardown(struct domain *d) { struct p2m_domain *p2m = &d->arch.p2m; struct page_info *pg; spin_lock(&p2m->lock); while ( (pg = page_list_remove_head(&p2m->pages)) ) free_domheap_page(pg); free_domheap_pages(p2m->first_level, P2M_FIRST_ORDER); p2m->first_level = NULL; p2m_free_vmid(d); spin_unlock(&p2m->lock); }