diff -r c160d5183bdc xen/arch/x86/mm/hap/hap.c --- a/xen/arch/x86/mm/hap/hap.c Sat Mar 31 16:11:37 2007 -0600 +++ b/xen/arch/x86/mm/hap/hap.c Sun Apr 01 16:31:43 2007 -0500 @@ -52,7 +52,7 @@ /************************************************/ /* HAP SUPPORT FUNCTIONS */ /************************************************/ -mfn_t hap_alloc(struct domain *d, unsigned long backpointer) +mfn_t hap_alloc(struct domain *d) { struct page_info *sp = NULL; void *p; @@ -82,43 +82,43 @@ void hap_free(struct domain *d, mfn_t sm list_add_tail(&sp->list, &d->arch.paging.hap.freelists); } -static int hap_alloc_p2m_pages(struct domain *d) -{ - struct page_info *pg; - - ASSERT(hap_locked_by_me(d)); - - pg = mfn_to_page(hap_alloc(d, 0)); - d->arch.paging.hap.p2m_pages += 1; - d->arch.paging.hap.total_pages -= 1; - - page_set_owner(pg, d); - pg->count_info = 1; - list_add_tail(&pg->list, &d->arch.paging.hap.p2m_freelist); - - return 1; -} - struct page_info * hap_alloc_p2m_page(struct domain *d) { - struct list_head *entry; struct page_info *pg; mfn_t mfn; void *p; hap_lock(d); - - if ( list_empty(&d->arch.paging.hap.p2m_freelist) && - !hap_alloc_p2m_pages(d) ) { - hap_unlock(d); - return NULL; - } - entry = d->arch.paging.hap.p2m_freelist.next; - list_del(entry); - + +#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. This page will be de-allocated in + * hap_free_p2m_page(), like other P2M pages. + */ + if ( d->arch.paging.hap.p2m_pages == 0 ) + { + pg = alloc_domheap_pages(NULL, 0, MEMF_bits(32)); + d->arch.paging.hap.p2m_pages += 1; + } + else +#endif + { + pg = mfn_to_page(hap_alloc(d)); + + d->arch.paging.hap.p2m_pages += 1; + d->arch.paging.hap.total_pages -= 1; + } + + if ( pg == NULL ) { + hap_unlock(d); + return NULL; + } + hap_unlock(d); - pg = list_entry(entry, struct page_info, list); + page_set_owner(pg, d); + pg->count_info = 1; mfn = page_to_mfn(pg); p = hap_map_domain_page(mfn); clear_page(p); @@ -141,6 +141,7 @@ void hap_free_p2m_page(struct domain *d, page_set_owner(pg, NULL); free_domheap_pages(pg, 0); d->arch.paging.hap.p2m_pages--; + ASSERT( d->arch.paging.hap.p2m_pages >= 0 ); } /* Return the size of the pool, rounded up to the nearest MB */ @@ -320,7 +321,7 @@ mfn_t hap_make_monitor_table(struct vcpu #if CONFIG_PAGING_LEVELS == 4 { mfn_t m4mfn; - m4mfn = hap_alloc(d, 0); + m4mfn = hap_alloc(d); hap_install_xen_entries_in_l4(v, m4mfn, m4mfn); return m4mfn; } @@ -331,12 +332,12 @@ mfn_t hap_make_monitor_table(struct vcpu l2_pgentry_t *l2e; int i; - m3mfn = hap_alloc(d, 0); + m3mfn = hap_alloc(d); /* Install a monitor l2 table in slot 3 of the l3 table. * This is used for all Xen entries, including linear maps */ - m2mfn = hap_alloc(d, 0); + m2mfn = hap_alloc(d); l3e = hap_map_domain_page(m3mfn); l3e[3] = l3e_from_pfn(mfn_x(m2mfn), _PAGE_PRESENT); hap_install_xen_entries_in_l2h(v, m2mfn); @@ -357,7 +358,7 @@ mfn_t hap_make_monitor_table(struct vcpu { mfn_t m2mfn; - m2mfn = hap_alloc(d, 0); + m2mfn = hap_alloc(d); hap_install_xen_entries_in_l2(v, m2mfn, m2mfn); return m2mfn; @@ -390,7 +391,6 @@ void hap_domain_init(struct domain *d) { hap_lock_init(d); INIT_LIST_HEAD(&d->arch.paging.hap.freelists); - INIT_LIST_HEAD(&d->arch.paging.hap.p2m_freelist); } /* return 0 for success, -errno for failure */ diff -r c160d5183bdc xen/include/asm-x86/domain.h --- a/xen/include/asm-x86/domain.h Sat Mar 31 16:11:37 2007 -0600 +++ b/xen/include/asm-x86/domain.h Sun Apr 01 05:46:41 2007 -0500 @@ -115,7 +115,6 @@ struct hap_domain { const char *locker_function; struct list_head freelists; - struct list_head p2m_freelist; unsigned int total_pages; /* number of pages allocated */ unsigned int free_pages; /* number of pages on freelists */ unsigned int p2m_pages; /* number of pages allocates to p2m */