aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-04-02 13:05:59 +0100
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>2007-04-02 13:05:59 +0100
commitcabcde1f1c0b3793179f16089320a1dc0d936518 (patch)
tree48b9c480c4b40731970ad345041e92f7140343d0
parent011623229a3113e12f6fcaf61a720d266368c1e7 (diff)
downloadxen-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.c66
-rw-r--r--xen/include/asm-x86/domain.h1
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 */