# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 71f2d19cd3a5142c9e060913ad95cdd7e03ecbb4
# Parent 1980e01346a73e98ae889f760718b9f6f6f1b1f9
Clean up p2m functions.
1) set_p2m_entry/alloc_p2m_table call domain_crash instead of
domain_crash_synchronous when map_p2m_entry return with failure, or dom0
will crash.
2) free_p2m_table now uses domain as parameter instead of vcpu.
3) add AP p2m initialization logic for VMX domain.
And some coding style cleanups.
Signed-off-by: Xin Li <xin.b.li@xxxxxxxxx>
diff -r 1980e01346a7 -r 71f2d19cd3a5 xen/arch/x86/shadow32.c
--- a/xen/arch/x86/shadow32.c Fri Feb 24 16:25:41 2006
+++ b/xen/arch/x86/shadow32.c Fri Feb 24 16:32:19 2006
@@ -43,7 +43,8 @@
static void mark_shadows_as_reflecting_snapshot(struct domain *d, unsigned
long gpfn);
#endif
-static void free_p2m_table(struct vcpu *v);
+static int alloc_p2m_table(struct domain *d);
+static void free_p2m_table(struct domain *d);
/********
@@ -739,7 +740,7 @@
mpl2e = (l2_pgentry_t *)map_domain_page_global(mmfn);
memset(mpl2e, 0, PAGE_SIZE);
- memcpy(&mpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
+ memcpy(&mpl2e[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
&idle_pg_table[DOMAIN_ENTRIES_PER_L2_PAGETABLE],
HYPERVISOR_ENTRIES_PER_L2_PAGETABLE * sizeof(l2_pgentry_t));
@@ -760,6 +761,23 @@
if ( v->vcpu_id == 0 )
alloc_p2m_table(d);
+ else
+ {
+ unsigned long mfn;
+
+ mfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+ if ( mfn )
+ {
+ l2_pgentry_t *l2tab;
+
+ l2tab = map_domain_page(mfn);
+
+ mpl2e[l2_table_offset(RO_MPT_VIRT_START)] =
+ l2tab[l2_table_offset(RO_MPT_VIRT_START)];
+
+ unmap_domain_page(l2tab);
+ }
+ }
}
/*
@@ -771,7 +789,7 @@
unsigned long mfn;
ASSERT( pagetable_get_paddr(v->arch.monitor_table) );
-
+
mpl2e = v->arch.monitor_vtable;
/*
@@ -794,7 +812,7 @@
}
if ( v->vcpu_id == 0 )
- free_p2m_table(v);
+ free_p2m_table(v->domain);
/*
* Then free monitor_table.
@@ -808,8 +826,8 @@
}
static int
-map_p2m_entry(
- l1_pgentry_t *l1tab, unsigned long va, unsigned long gpa, unsigned long
mfn)
+map_p2m_entry(l1_pgentry_t *l1tab, unsigned long va,
+ unsigned long gpa, unsigned long mfn)
{
unsigned long *l0tab = NULL;
l1_pgentry_t l1e = { 0 };
@@ -820,27 +838,22 @@
{
page = alloc_domheap_page(NULL);
if ( !page )
- goto fail;
-
- if ( l0tab )
- unmap_domain_page(l0tab);
+ return 0;
+
l0tab = map_domain_page(page_to_mfn(page));
- memset(l0tab, 0, PAGE_SIZE );
+ memset(l0tab, 0, PAGE_SIZE);
+
l1e = l1tab[l1_table_offset(va)] =
l1e_from_page(page, __PAGE_HYPERVISOR);
}
- else if ( l0tab == NULL)
+ else
l0tab = map_domain_page(l1e_get_pfn(l1e));
- l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
-
- if ( l0tab )
- unmap_domain_page(l0tab);
+ l0tab[gpa & ((PAGE_SIZE / sizeof(mfn)) - 1)] = mfn;
+
+ unmap_domain_page(l0tab);
return 1;
-
-fail:
- return 0;
}
int
@@ -853,7 +866,6 @@
l1_pgentry_t *l1;
struct page_info *l1page;
unsigned long va = pfn << PAGE_SHIFT;
- int error;
if ( shadow_mode_external(d) )
{
@@ -877,6 +889,7 @@
if ( shadow_mode_external(d) )
{
+ int error;
l1_pgentry_t *l1tab = NULL;
l2_pgentry_t l2e;
@@ -885,14 +898,13 @@
ASSERT( l2e_get_flags(l2e) & _PAGE_PRESENT );
l1tab = map_domain_page(l2e_get_pfn(l2e));
- error = map_p2m_entry(l1tab, va, pfn, mfn);
- if ( !error )
- domain_crash_synchronous();
+ if ( !(error = map_p2m_entry(l1tab, va, pfn, mfn)) )
+ domain_crash(d);
unmap_domain_page(l1tab);
unmap_domain_page_with_cache(l2, l2cache);
- return 1;
+ return error;
}
/*
@@ -926,7 +938,7 @@
return 1;
}
-int
+static int
alloc_p2m_table(struct domain *d)
{
struct list_head *list_ent;
@@ -937,7 +949,7 @@
l2_pgentry_t l2e = { 0 };
struct page_info *page;
unsigned long gpfn, mfn;
- int error;
+ int error = 0;
if ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) )
{
@@ -955,6 +967,9 @@
}
else
l1tab = map_domain_page(l2e_get_pfn(l2e));
+
+ if ( l2tab )
+ unmap_domain_page(l2tab);
}
else
{
@@ -972,23 +987,23 @@
page = list_entry(list_ent, struct page_info, list);
mfn = page_to_mfn(page);
- error = map_p2m_entry(l1tab, va, gpfn, mfn);
- if ( !error )
- domain_crash_synchronous();
+ if ( !(error = map_p2m_entry(l1tab, va, gpfn, mfn)) )
+ {
+ domain_crash(d);
+ break;
+ }
list_ent = frame_table[mfn].list.next;
va += sizeof(mfn);
}
- if (l2tab)
- unmap_domain_page(l2tab);
unmap_domain_page(l1tab);
- return 1;
-}
-
-static void
-free_p2m_table(struct vcpu *v)
+ return error;
+}
+
+static void
+free_p2m_table(struct domain *d)
{
unsigned long va;
l2_pgentry_t *l2tab;
@@ -996,10 +1011,10 @@
l2_pgentry_t l2e;
l1_pgentry_t l1e;
- ASSERT ( pagetable_get_pfn(v->arch.monitor_table) );
+ ASSERT( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) );
l2tab = map_domain_page(
- pagetable_get_pfn(v->arch.monitor_table));
+ pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
for ( va = RO_MPT_VIRT_START; va < RO_MPT_VIRT_END; )
{
@@ -1015,11 +1030,13 @@
if ( l1e_get_flags(l1e) & _PAGE_PRESENT )
free_domheap_page(mfn_to_page(l1e_get_pfn(l1e)));
- va += PAGE_SIZE;
+ va += PAGE_SIZE;
}
unmap_domain_page(l1tab);
free_domheap_page(mfn_to_page(l2e_get_pfn(l2e)));
}
+ else
+ va += PAGE_SIZE * L1_PAGETABLE_ENTRIES;
}
unmap_domain_page(l2tab);
}
@@ -1246,7 +1263,7 @@
if ( shadow_mode_refcounts(d) )
{
- struct list_head *list_ent;
+ struct list_head *list_ent;
struct page_info *page;
/*
diff -r 1980e01346a7 -r 71f2d19cd3a5 xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c Fri Feb 24 16:25:41 2006
+++ b/xen/arch/x86/shadow_public.c Fri Feb 24 16:32:19 2006
@@ -31,7 +31,8 @@
#include <xen/trace.h>
#include <asm/shadow_64.h>
-static void free_p2m_table(struct vcpu *v);
+static int alloc_p2m_table(struct domain *d);
+static void free_p2m_table(struct domain *d);
#define SHADOW_MAX_GUEST32(_encoded) ((L1_PAGETABLE_ENTRIES_32 - 1) -
((_encoded) >> 16))
@@ -328,6 +329,23 @@
if ( v->vcpu_id == 0 )
alloc_p2m_table(d);
+ else
+ {
+ unsigned long mfn;
+
+ mfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+ if ( mfn )
+ {
+ l4_pgentry_t *l4tab;
+
+ l4tab = map_domain_page(mfn);
+
+ mpl4e[l4_table_offset(RO_MPT_VIRT_START)] =
+ l4tab[l4_table_offset(RO_MPT_VIRT_START)];
+
+ unmap_domain_page(l4tab);
+ }
+ }
}
void free_monitor_pagetable(struct vcpu *v)
@@ -338,7 +356,7 @@
* free monitor_table.
*/
if ( v->vcpu_id == 0 )
- free_p2m_table(v);
+ free_p2m_table(v->domain);
/*
* Then free monitor_table.
@@ -397,13 +415,49 @@
l2e_empty();
mpl2e[l2_table_offset(RO_MPT_VIRT_START)] = l2e_empty();
- unmap_domain_page(mpl2e);
-
v->arch.monitor_table = mk_pagetable(m3mfn << PAGE_SHIFT); /* < 4GB */
v->arch.monitor_vtable = (l2_pgentry_t *) mpl3e;
if ( v->vcpu_id == 0 )
alloc_p2m_table(d);
+ else
+ {
+ unsigned long mfn;
+
+ mfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+ if ( mfn )
+ {
+ l3_pgentry_t *l3tab, l3e;
+ l2_pgentry_t *l2tab;
+
+ l3tab = map_domain_page(mfn);
+ l3e = l3tab[l3_table_offset(RO_MPT_VIRT_START)];
+
+ /*
+ * NB: when CONFIG_PAGING_LEVELS == 3,
+ * (entry_get_flags(l3e) & _PAGE_PRESENT) is always true here.
+ * alloc_monitor_pagetable should guarantee this.
+ */
+ if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+ BUG();
+
+ l2tab = map_domain_page(l3e_get_pfn(l3e));
+
+ /*
+ * Just one l2 slot is used here, so at most 2M for p2m table:
+ * ((4K * 512)/sizeof(unsigned long)) * 4K = 2G
+ * should be OK on PAE xen, since Qemu DM can only map 1.5G VMX
+ * guest memory.
+ */
+ mpl2e[l2_table_offset(RO_MPT_VIRT_START)] =
+ l2tab[l2_table_offset(RO_MPT_VIRT_START)];
+
+ unmap_domain_page(l2tab);
+ unmap_domain_page(l3tab);
+ }
+ }
+
+ unmap_domain_page(mpl2e);
}
void free_monitor_pagetable(struct vcpu *v)
@@ -413,7 +467,7 @@
* free monitor_table.
*/
if ( v->vcpu_id == 0 )
- free_p2m_table(v);
+ free_p2m_table(v->domain);
m3mfn = pagetable_get_pfn(v->arch.monitor_table);
m2mfn = l2e_get_pfn(v->arch.monitor_vtable[L3_PAGETABLE_ENTRIES - 1]);
@@ -1348,14 +1402,14 @@
}
static int
-map_p2m_entry(
- pgentry_64_t *top_tab, unsigned long va, unsigned long gpa, unsigned long
mfn)
+map_p2m_entry(pgentry_64_t *top_tab, unsigned long va,
+ unsigned long gpfn, unsigned long mfn)
{
#if CONFIG_PAGING_LEVELS >= 4
pgentry_64_t l4e = { 0 };
+ pgentry_64_t *l3tab = NULL;
#endif
#if CONFIG_PAGING_LEVELS >= 3
- pgentry_64_t *l3tab = NULL;
pgentry_64_t l3e = { 0 };
#endif
l2_pgentry_t *l2tab = NULL;
@@ -1367,7 +1421,7 @@
#if CONFIG_PAGING_LEVELS >= 4
l4e = top_tab[l4_table_offset(va)];
- if ( !(entry_get_flags(l4e) & _PAGE_PRESENT) )
+ if ( !(entry_get_flags(l4e) & _PAGE_PRESENT) )
{
page = alloc_domheap_page(NULL);
if ( !page )
@@ -1375,17 +1429,14 @@
l3tab = map_domain_page(page_to_mfn(page));
memset(l3tab, 0, PAGE_SIZE);
- l4e = top_tab[l4_table_offset(va)] =
+ l4e = top_tab[l4_table_offset(va)] =
entry_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l3tab == NULL)
+ }
+ else
l3tab = map_domain_page(entry_get_pfn(l4e));
l3e = l3tab[l3_table_offset(va)];
-#else
- l3e = top_tab[l3_table_offset(va)];
-#endif
- if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) )
+ if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) )
{
page = alloc_domheap_page(NULL);
if ( !page )
@@ -1393,14 +1444,29 @@
l2tab = map_domain_page(page_to_mfn(page));
memset(l2tab, 0, PAGE_SIZE);
- l3e = l3tab[l3_table_offset(va)] =
+ l3e = l3tab[l3_table_offset(va)] =
entry_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l2tab == NULL)
+ }
+ else
l2tab = map_domain_page(entry_get_pfn(l3e));
+ unmap_domain_page(l3tab);
+#else
+ l3e = top_tab[l3_table_offset(va)];
+
+ /*
+ * NB: when CONFIG_PAGING_LEVELS == 3,
+ * (entry_get_flags(l3e) & _PAGE_PRESENT) is always true here.
+ * alloc_monitor_pagetable should guarantee this.
+ */
+ if ( !(entry_get_flags(l3e) & _PAGE_PRESENT) )
+ BUG();
+
+ l2tab = map_domain_page(entry_get_pfn(l3e));
+#endif
+
l2e = l2tab[l2_table_offset(va)];
- if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+ if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
{
page = alloc_domheap_page(NULL);
if ( !page )
@@ -1408,14 +1474,16 @@
l1tab = map_domain_page(page_to_mfn(page));
memset(l1tab, 0, PAGE_SIZE);
- l2e = l2tab[l2_table_offset(va)] =
+ l2e = l2tab[l2_table_offset(va)] =
l2e_from_page(page, __PAGE_HYPERVISOR);
- }
- else if ( l1tab == NULL)
+ }
+ else
l1tab = map_domain_page(l2e_get_pfn(l2e));
+ unmap_domain_page(l2tab);
+
l1e = l1tab[l1_table_offset(va)];
- if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
+ if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
{
page = alloc_domheap_page(NULL);
if ( !page )
@@ -1423,96 +1491,88 @@
l0tab = map_domain_page(page_to_mfn(page));
memset(l0tab, 0, PAGE_SIZE);
- l1e = l1tab[l1_table_offset(va)] =
+ l1e = l1tab[l1_table_offset(va)] =
l1e_from_page(page, __PAGE_HYPERVISOR);
}
- else if ( l0tab == NULL)
+ else
l0tab = map_domain_page(l1e_get_pfn(l1e));
- l0tab[gpa & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
-
- if ( l2tab )
- {
- unmap_domain_page(l2tab);
- l2tab = NULL;
- }
- if ( l1tab )
- {
- unmap_domain_page(l1tab);
- l1tab = NULL;
- }
- if ( l0tab )
- {
- unmap_domain_page(l0tab);
- l0tab = NULL;
- }
+ unmap_domain_page(l1tab);
+
+ l0tab[gpfn & ((PAGE_SIZE / sizeof (mfn)) - 1) ] = mfn;
+
+ unmap_domain_page(l0tab);
return 1;
nomem:
-
return 0;
}
int
-set_p2m_entry(struct domain *d, unsigned long pfn, unsigned long mfn,
+set_p2m_entry(struct domain *d, unsigned long gpfn, unsigned long mfn,
struct domain_mmap_cache *l2cache,
struct domain_mmap_cache *l1cache)
{
- unsigned long tabpfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
- pgentry_64_t *top;
- unsigned long va = RO_MPT_VIRT_START + (pfn * sizeof (unsigned long));
+ unsigned long tabmfn = pagetable_get_pfn(d->vcpu[0]->arch.monitor_table);
+ unsigned long va = RO_MPT_VIRT_START + (gpfn * sizeof(unsigned long));
+ pgentry_64_t *top_tab;
int error;
- ASSERT(tabpfn != 0);
+ ASSERT(tabmfn != 0);
ASSERT(shadow_lock_is_acquired(d));
- top = map_domain_page_with_cache(tabpfn, l2cache);
- error = map_p2m_entry(top, va, pfn, mfn);
- unmap_domain_page_with_cache(top, l2cache);
-
- if ( !error )
- domain_crash_synchronous();
-
- return 1;
-}
-
-int
+ top_tab = map_domain_page_with_cache(tabmfn, l2cache);
+
+ if ( !(error = map_p2m_entry(top_tab, va, gpfn, mfn)) )
+ domain_crash(d);
+
+ unmap_domain_page_with_cache(top_tab, l2cache);
+
+ return error;
+}
+
+static int
alloc_p2m_table(struct domain *d)
{
struct list_head *list_ent;
unsigned long va = RO_MPT_VIRT_START; /* phys_to_machine_mapping */
pgentry_64_t *top_tab = NULL;
unsigned long mfn;
- int gpa;
-
- ASSERT ( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) );
+ int gpfn, error = 0;
+
+ ASSERT( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) );
top_tab = map_domain_page(
pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
-
list_ent = d->page_list.next;
- for ( gpa = 0; list_ent != &d->page_list; gpa++ )
+ for ( gpfn = 0; list_ent != &d->page_list; gpfn++ )
{
struct page_info *page;
+
page = list_entry(list_ent, struct page_info, list);
mfn = page_to_mfn(page);
- map_p2m_entry(top_tab, va, gpa, mfn);
+ if ( !(error = map_p2m_entry(top_tab, va, gpfn, mfn)) )
+ {
+ domain_crash(d);
+ break;
+ }
+
list_ent = frame_table[mfn].list.next;
va += sizeof(mfn);
}
unmap_domain_page(top_tab);
- return 1;
+ return error;
}
#if CONFIG_PAGING_LEVELS >= 3
static void
-free_p2m_table(struct vcpu *v)
+free_p2m_table(struct domain *d)
{
unsigned long va;
l1_pgentry_t *l1tab;
@@ -1520,27 +1580,35 @@
l2_pgentry_t *l2tab;
l2_pgentry_t l2e;
#if CONFIG_PAGING_LEVELS >= 3
- l3_pgentry_t *l3tab;
+ l3_pgentry_t *l3tab;
l3_pgentry_t l3e;
#endif
#if CONFIG_PAGING_LEVELS == 4
int i3;
- l4_pgentry_t *l4tab;
+ l4_pgentry_t *l4tab;
l4_pgentry_t l4e;
#endif
- ASSERT ( pagetable_get_pfn(v->arch.monitor_table) );
+ ASSERT( pagetable_get_pfn(d->vcpu[0]->arch.monitor_table) );
#if CONFIG_PAGING_LEVELS == 4
l4tab = map_domain_page(
- pagetable_get_pfn(v->arch.monitor_table));
+ pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
#endif
#if CONFIG_PAGING_LEVELS == 3
l3tab = map_domain_page(
- pagetable_get_pfn(v->arch.monitor_table));
-
- va = RO_MPT_VIRT_START;
- l3e = l3tab[l3_table_offset(va)];
+ pagetable_get_pfn(d->vcpu[0]->arch.monitor_table));
+
+ l3e = l3tab[l3_table_offset(RO_MPT_VIRT_START)];
+
+ /*
+ * NB: when CONFIG_PAGING_LEVELS == 3,
+ * (entry_get_flags(l3e) & _PAGE_PRESENT) is always true here.
+ * alloc_monitor_pagetable should guarantee this.
+ */
+ if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+ BUG();
+
l2tab = map_domain_page(l3e_get_pfn(l3e));
#endif
@@ -1555,8 +1623,8 @@
for ( i3 = 0; i3 < L3_PAGETABLE_ENTRIES; i3++ )
{
-
l3e = l3tab[l3_table_offset(va)];
+
if ( l3e_get_flags(l3e) & _PAGE_PRESENT )
{
int i2;
@@ -1567,12 +1635,13 @@
{
#endif
l2e = l2tab[l2_table_offset(va)];
+
if ( l2e_get_flags(l2e) & _PAGE_PRESENT )
{
int i1;
l1tab = map_domain_page(l2e_get_pfn(l2e));
-
+
/*
* unsigned long phys_to_machine_mapping[]
*/
@@ -1591,7 +1660,7 @@
else
va += PAGE_SIZE * L1_PAGETABLE_ENTRIES;
-#if CONFIG_PAGING_LEVELS == 4
+#if CONFIG_PAGING_LEVELS == 4
}
unmap_domain_page(l2tab);
free_domheap_page(mfn_to_page(l3e_get_pfn(l3e)));
@@ -1603,7 +1672,7 @@
free_domheap_page(mfn_to_page(l4e_get_pfn(l4e)));
}
else
- va += PAGE_SIZE *
+ va += PAGE_SIZE *
L1_PAGETABLE_ENTRIES * L2_PAGETABLE_ENTRIES *
L3_PAGETABLE_ENTRIES;
#endif
}
@@ -1622,7 +1691,7 @@
paddr_t pa, l1_pgentry_t gpte,
struct domain_mmap_cache *cache)
{
- unsigned long sl1mfn;
+ unsigned long sl1mfn;
l1_pgentry_t *spl1e, spte;
shadow_lock(d);
diff -r 1980e01346a7 -r 71f2d19cd3a5 xen/include/asm-x86/shadow_public.h
--- a/xen/include/asm-x86/shadow_public.h Fri Feb 24 16:25:41 2006
+++ b/xen/include/asm-x86/shadow_public.h Fri Feb 24 16:32:19 2006
@@ -21,8 +21,6 @@
#ifndef _XEN_SHADOW_PUBLIC_H
#define _XEN_SHADOW_PUBLIC_H
-
-extern int alloc_p2m_table(struct domain *d);
#if CONFIG_PAGING_LEVELS >= 3
#define MFN_PINNED(_x) (mfn_to_page(_x)->u.inuse.type_info & PGT_pinned)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|