diff -r 4ac8bc60c000 xen/common/page_alloc.c --- a/xen/common/page_alloc.c Tue Feb 10 05:51:00 2009 +0000 +++ b/xen/common/page_alloc.c Thu Feb 12 20:32:15 2009 -0700 @@ -931,6 +934,53 @@ void free_domheap_pages(struct page_info put_domain(d); } +struct page_info *reassign_domheap_pages(struct domain *new, + struct page_info *pg, unsigned int order) +{ + struct domain *old = page_get_owner(pg); + struct domain *lock = (old != NULL) ? old : new; + int npages = 1 << order; + int i; + + ASSERT(!in_irq()); + ASSERT(!is_xen_heap_page(pg)); + ASSERT((old != NULL) || (new != NULL)); + if ( (new != NULL) && (new->tot_pages + npages > new->max_pages) ) + return NULL; + spin_lock_recursive(&lock->page_alloc_lock); + if ( old != NULL ) + { + ASSERT(old->tot_pages > npages); + old->tot_pages -= 1 << order; + } + if ( new != NULL ) + { + ASSERT(new->tot_pages != 0); + new->tot_pages += npages; + } + for ( i = 0; i < (1 << order); i++ ) + { + if ( old != NULL ) + { + ASSERT(page_get_owner(&pg[i])==old); + ASSERT(pg[i].count_info & (PGC_allocated | 1)); + pg[i].count_info &= ~(PGC_allocated | 1); + page_list_del(&pg[i], &old->page_list); + } + page_set_owner(&pg[i], new); + wmb(); /* Domain pointer must be visible before updating refcnt. */ + if ( new != NULL ) + { + ASSERT(page_get_owner(&pg[i])==NULL); + ASSERT((pg[i].count_info & ~(PGC_allocated | 1)) == 0); + pg[i].count_info = PGC_allocated | 1; + page_list_add_tail(&pg[i], &new->page_list); + } + } + spin_unlock_recursive(&lock->page_alloc_lock); + return pg; +} + unsigned long avail_domheap_pages_region( unsigned int node, unsigned int min_width, unsigned int max_width) {