void share_xen_page_with_guest( struct page_info *page, struct domain *d, int readonly) { if ( page_get_owner(page) == d ) return; /* this causes us to leak pages in the Domain and reuslts in * Zombie domains, I think we are missing a piece, until we find * it we disable the following code */ set_gpfn_from_mfn(page_to_mfn(page), INVALID_M2P_ENTRY); spin_lock(&d->page_alloc_lock); /* The incremented type count pins as writable or read-only. */ page->u.inuse.type_info = (readonly ? PGT_none : PGT_writable_page); page->u.inuse.type_info |= PGT_validated | 1; page_set_owner(page, d); wmb(); /* install valid domain ptr before updating refcnt. */ ASSERT(page->count_info == 0); /* Only add to the allocation list if the domain isn't dying. */ if ( !d->is_dying ) { page->count_info |= PGC_allocated | 1; if ( unlikely(d->xenheap_pages++ == 0) ) get_knownalive_domain(d); list_add_tail(&page->list, &d->xenpage_list); } spin_unlock(&d->page_alloc_lock); }
void share_xen_page_with_guest(struct page_info *page, struct domain *d, int readonly) { if ( page_get_owner(page) == d ) return; spin_lock(&d->page_alloc_lock); /* The incremented type count pins as writable or read-only. */ page->u.inuse.type_info = (readonly ? PGT_none : PGT_writable_page); page->u.inuse.type_info |= PGT_validated | 1; page_set_owner(page, d); wmb(); /* install valid domain ptr before updating refcnt. */ ASSERT((page->count_info & ~PGC_xen_heap) == 0); /* Only add to the allocation list if the domain isn't dying. */ if ( !d->is_dying ) { page->count_info |= PGC_allocated | 1; if ( unlikely(d->xenheap_pages++ == 0) ) get_knownalive_domain(d); page_list_add_tail(page, &d->xenpage_list); } spin_unlock(&d->page_alloc_lock); }
void hap_free_p2m_page(struct domain *d, struct page_info *pg) { hap_lock(d); ASSERT(page_get_owner(pg) == d); /* Should have just the one ref we gave it in alloc_p2m_page() */ if ( (pg->count_info & PGC_count_mask) != 1 ) HAP_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n", pg->count_info, pg->u.inuse.type_info); pg->count_info = 0; /* Free should not decrement domain's total allocation, since * these pages were allocated without an owner. */ page_set_owner(pg, NULL); free_domheap_page(pg); d->arch.paging.hap.p2m_pages--; ASSERT(d->arch.paging.hap.p2m_pages >= 0); hap_unlock(d); }
static int share_xenoprof_page_with_guest(struct domain *d, unsigned long mfn, int npages) { int i; /* Check if previous page owner has released the page. */ for ( i = 0; i < npages; i++ ) { struct page_info *page = mfn_to_page(mfn + i); if ( (page->count_info & (PGC_allocated|PGC_count_mask)) != 0 ) { gdprintk(XENLOG_INFO, "mfn 0x%lx page->count_info 0x%lx\n", mfn + i, (unsigned long)page->count_info); return -EBUSY; } page_set_owner(page, NULL); } for ( i = 0; i < npages; i++ ) share_xen_page_with_guest(mfn_to_page(mfn + i), d, XENSHARE_writable); return 0; }
static struct page_info *hap_alloc_p2m_page(struct domain *d) { struct page_info *pg; hap_lock(d); pg = hap_alloc(d); #if CONFIG_PAGING_LEVELS == 3 /* Under PAE mode, top-level P2M table should be allocated below 4GB space * because the size of h_cr3 is only 32-bit. We use alloc_domheap_pages to * force this requirement, and exchange the guaranteed 32-bit-clean * page for the one we just hap_alloc()ed. */ if ( d->arch.paging.hap.p2m_pages == 0 && mfn_x(page_to_mfn(pg)) >= (1UL << (32 - PAGE_SHIFT)) ) { free_domheap_page(pg); pg = alloc_domheap_pages(NULL, 0, MEMF_bits(32)); if ( likely(pg != NULL) ) { void *p = hap_map_domain_page(page_to_mfn(pg)); clear_page(p); hap_unmap_domain_page(p); } } #endif if ( likely(pg != NULL) ) { d->arch.paging.hap.total_pages--; d->arch.paging.hap.p2m_pages++; page_set_owner(pg, d); pg->count_info = 1; } hap_unlock(d); return pg; }