diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-04-02 13:05:59 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2007-04-02 13:05:59 +0100 |
commit | cabcde1f1c0b3793179f16089320a1dc0d936518 (patch) | |
tree | 48b9c480c4b40731970ad345041e92f7140343d0 | |
parent | 011623229a3113e12f6fcaf61a720d266368c1e7 (diff) | |
download | xen-cabcde1f1c0b3793179f16089320a1dc0d936518.tar.gz xen-cabcde1f1c0b3793179f16089320a1dc0d936518.tar.bz2 xen-cabcde1f1c0b3793179f16089320a1dc0d936518.zip |
hvm hap: P2M page table cleanup and bug fix.
Force P2M top-level page table to be allocated below 4GB
memory space when Xen is running under PAE mode. Also remove
hap.p2m_freelists because hap mode does not have P2M batch
allocation. The backpointer parameter of hap_alloc() function is
removed since this parameter is unused.
Signed-off-by: Wei Huang <wei.huang2@amd.com>
-rw-r--r-- | xen/arch/x86/mm/hap/hap.c | 66 | ||||
-rw-r--r-- | xen/include/asm-x86/domain.h | 1 |
2 files changed, 33 insertions, 34 deletions
diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index ac4df6ec70..6a832990d2 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -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 smfn) 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; + +#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; } - entry = d->arch.paging.hap.p2m_freelist.next; - list_del(entry); - + 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, struct page_info *pg) 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 *v) #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 *v) 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 *v) { 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 --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index bdc2f16f12..7d9b0bc2f4 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -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 */ |