aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Deegan <Tim.Deegan@citrix.com>2011-06-02 13:16:52 +0100
committerTim Deegan <Tim.Deegan@citrix.com>2011-06-02 13:16:52 +0100
commit58923a7203f930f585f5d1d58ffc9f6bb0598ad7 (patch)
treedfda3c8bbcb488c2abe8b9d048c6beee3503d4ea
parentd5ce4dacf003caa6326c3dcd69481543afdd7432 (diff)
downloadxen-58923a7203f930f585f5d1d58ffc9f6bb0598ad7.tar.gz
xen-58923a7203f930f585f5d1d58ffc9f6bb0598ad7.tar.bz2
xen-58923a7203f930f585f5d1d58ffc9f6bb0598ad7.zip
x86/mm/p2m: little fixes and tidying up
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
-rw-r--r--xen/arch/x86/mm/p2m-pod.c13
-rw-r--r--xen/arch/x86/mm/p2m-pt.c26
-rw-r--r--xen/arch/x86/mm/p2m.c43
-rw-r--r--xen/include/asm-x86/p2m.h160
-rw-r--r--xen/include/asm-x86/x86_32/page.h1
-rw-r--r--xen/include/asm-x86/x86_64/page.h1
6 files changed, 123 insertions, 121 deletions
diff --git a/xen/arch/x86/mm/p2m-pod.c b/xen/arch/x86/mm/p2m-pod.c
index 2e2dfbf18d..fca5caa21b 100644
--- a/xen/arch/x86/mm/p2m-pod.c
+++ b/xen/arch/x86/mm/p2m-pod.c
@@ -42,7 +42,6 @@
#undef page_to_mfn
#define page_to_mfn(_pg) _mfn(__page_to_mfn(_pg))
-#define SUPERPAGE_PAGES (1UL << 9)
#define superpage_aligned(_x) (((_x)&(SUPERPAGE_PAGES-1))==0)
/*
@@ -688,8 +687,7 @@ p2m_pod_zero_check_superpage(struct p2m_domain *p2m, unsigned long gfn)
}
/* Try to remove the page, restoring old mapping if it fails. */
- set_p2m_entry(p2m, gfn,
- _mfn(POPULATE_ON_DEMAND_MFN), 9,
+ set_p2m_entry(p2m, gfn, _mfn(0), 9,
p2m_populate_on_demand, p2m->default_access);
/* Make none of the MFNs are used elsewhere... for example, mapped
@@ -801,8 +799,7 @@ p2m_pod_zero_check(struct p2m_domain *p2m, unsigned long *gfns, int count)
}
/* Try to remove the page, restoring old mapping if it fails. */
- set_p2m_entry(p2m, gfns[i],
- _mfn(POPULATE_ON_DEMAND_MFN), 0,
+ set_p2m_entry(p2m, gfns[i], _mfn(0), 0,
p2m_populate_on_demand, p2m->default_access);
/* See if the page was successfully unmapped. (Allow one refcount
@@ -966,7 +963,7 @@ p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
* set_p2m_entry() should automatically shatter the 1GB page into
* 512 2MB pages. The rest of 511 calls are unnecessary.
*/
- set_p2m_entry(p2m, gfn_aligned, _mfn(POPULATE_ON_DEMAND_MFN), 9,
+ set_p2m_entry(p2m, gfn_aligned, _mfn(0), 9,
p2m_populate_on_demand, p2m->default_access);
audit_p2m(p2m, 1);
p2m_unlock(p2m);
@@ -1054,7 +1051,7 @@ remap_and_retry:
/* Remap this 2-meg region in singleton chunks */
gfn_aligned = (gfn>>order)<<order;
for(i=0; i<(1<<order); i++)
- set_p2m_entry(p2m, gfn_aligned+i, _mfn(POPULATE_ON_DEMAND_MFN), 0,
+ set_p2m_entry(p2m, gfn_aligned+i, _mfn(0), 0,
p2m_populate_on_demand, p2m->default_access);
if ( tb_init_done )
{
@@ -1114,7 +1111,7 @@ guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
}
/* Now, actually do the two-way mapping */
- if ( !set_p2m_entry(p2m, gfn, _mfn(POPULATE_ON_DEMAND_MFN), order,
+ if ( !set_p2m_entry(p2m, gfn, _mfn(0), order,
p2m_populate_on_demand, p2m->default_access) )
rc = -EINVAL;
else
diff --git a/xen/arch/x86/mm/p2m-pt.c b/xen/arch/x86/mm/p2m-pt.c
index c664bf3c6f..229d79d02c 100644
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -51,9 +51,6 @@
#define P2M_BASE_FLAGS \
(_PAGE_PRESENT | _PAGE_USER | _PAGE_DIRTY | _PAGE_ACCESSED)
-#define SUPERPAGE_PAGES (1UL << 9)
-#define superpage_aligned(_x) (((_x)&(SUPERPAGE_PAGES-1))==0)
-
static unsigned long p2m_type_to_flags(p2m_type_t t, mfn_t mfn)
{
unsigned long flags;
@@ -67,32 +64,31 @@ static unsigned long p2m_type_to_flags(p2m_type_t t, mfn_t mfn)
#else
flags = (t & 0x7UL) << 9;
#endif
-#ifndef HAVE_GRANT_MAP_P2M
- BUG_ON(p2m_is_grant(t));
+
+#ifndef __x86_64__
+ /* 32-bit builds don't support a lot of the p2m types */
+ BUG_ON(t > p2m_populate_on_demand);
#endif
+
switch(t)
{
case p2m_invalid:
+ case p2m_mmio_dm:
+ case p2m_populate_on_demand:
default:
return flags;
- case p2m_ram_rw:
- case p2m_grant_map_rw:
- return flags | P2M_BASE_FLAGS | _PAGE_RW;
- case p2m_ram_logdirty:
- return flags | P2M_BASE_FLAGS;
case p2m_ram_ro:
case p2m_grant_map_ro:
- return flags | P2M_BASE_FLAGS;
+ case p2m_ram_logdirty:
case p2m_ram_shared:
return flags | P2M_BASE_FLAGS;
- case p2m_mmio_dm:
- return flags;
+ case p2m_ram_rw:
+ case p2m_grant_map_rw:
+ return flags | P2M_BASE_FLAGS | _PAGE_RW;
case p2m_mmio_direct:
if ( !rangeset_contains_singleton(mmio_ro_ranges, mfn_x(mfn)) )
flags |= _PAGE_RW;
return flags | P2M_BASE_FLAGS | _PAGE_PCD;
- case p2m_populate_on_demand:
- return flags;
}
}
diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c
index 618aa132af..14cb2227c3 100644
--- a/xen/arch/x86/mm/p2m.c
+++ b/xen/arch/x86/mm/p2m.c
@@ -243,31 +243,30 @@ int p2m_alloc_table(struct p2m_domain *p2m)
p2m_invalid, p2m->default_access) )
goto error;
- if (p2m_is_nestedp2m(p2m))
- goto nesteddone;
-
- /* Copy all existing mappings from the page list and m2p */
- spin_lock(&p2m->domain->page_alloc_lock);
- page_list_for_each(page, &p2m->domain->page_list)
+ if ( !p2m_is_nestedp2m(p2m) )
{
- mfn = page_to_mfn(page);
- gfn = get_gpfn_from_mfn(mfn_x(mfn));
- /* Pages should not be shared that early */
- ASSERT(gfn != SHARED_M2P_ENTRY);
- page_count++;
- if (
+ /* Copy all existing mappings from the page list and m2p */
+ spin_lock(&p2m->domain->page_alloc_lock);
+ page_list_for_each(page, &p2m->domain->page_list)
+ {
+ mfn = page_to_mfn(page);
+ gfn = get_gpfn_from_mfn(mfn_x(mfn));
+ /* Pages should not be shared that early */
+ ASSERT(gfn != SHARED_M2P_ENTRY);
+ page_count++;
+ if (
#ifdef __x86_64__
- (gfn != 0x5555555555555555L)
+ (gfn != 0x5555555555555555L)
#else
- (gfn != 0x55555555L)
+ (gfn != 0x55555555L)
#endif
- && gfn != INVALID_M2P_ENTRY
- && !set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_rw, p2m->default_access) )
- goto error_unlock;
+ && gfn != INVALID_M2P_ENTRY
+ && !set_p2m_entry(p2m, gfn, mfn, 0, p2m_ram_rw, p2m->default_access) )
+ goto error_unlock;
+ }
+ spin_unlock(&p2m->domain->page_alloc_lock);
}
- spin_unlock(&p2m->domain->page_alloc_lock);
- nesteddone:
P2M_PRINTK("p2m table initialised (%u pages)\n", page_count);
p2m_unlock(p2m);
return 0;
@@ -693,7 +692,8 @@ int p2m_mem_paging_evict(struct p2m_domain *p2m, unsigned long gfn)
/* Remove mapping from p2m table */
p2m_lock(p2m);
- set_p2m_entry(p2m, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paged, p2m->default_access);
+ set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), 0,
+ p2m_ram_paged, p2m->default_access);
audit_p2m(p2m, 1);
p2m_unlock(p2m);
@@ -743,7 +743,8 @@ void p2m_mem_paging_populate(struct p2m_domain *p2m, unsigned long gfn)
if ( p2mt == p2m_ram_paged )
{
p2m_lock(p2m);
- set_p2m_entry(p2m, gfn, _mfn(PAGING_MFN), 0, p2m_ram_paging_in_start, p2m->default_access);
+ set_p2m_entry(p2m, gfn, _mfn(INVALID_MFN), 0,
+ p2m_ram_paging_in_start, p2m->default_access);
audit_p2m(p2m, 1);
p2m_unlock(p2m);
}
diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h
index cbf1da2835..14976083d7 100644
--- a/xen/include/asm-x86/p2m.h
+++ b/xen/include/asm-x86/p2m.h
@@ -47,10 +47,6 @@
*/
#define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START)
-#ifdef __x86_64__
-#define HAVE_GRANT_MAP_P2M
-#endif
-
/*
* The upper levels of the p2m pagetable always contain full rights; all
* variation in the access control bits is made in the level-1 PTEs.
@@ -78,20 +74,16 @@ typedef enum {
p2m_mmio_direct = 5, /* Read/write mapping of genuine MMIO area */
p2m_populate_on_demand = 6, /* Place-holder for empty memory */
- /* Note that these can only be used if HAVE_GRANT_MAP_P2M is
- defined. They get defined anyway so as to avoid lots of
- #ifdef's everywhere else. */
- p2m_grant_map_rw = 7, /* Read/write grant mapping */
- p2m_grant_map_ro = 8, /* Read-only grant mapping */
-
- /* Likewise, although these are defined in all builds, they can only
+ /* Although these are defined in all builds, they can only
* be used in 64-bit builds */
+ p2m_grant_map_rw = 7, /* Read/write grant mapping */
+ p2m_grant_map_ro = 8, /* Read-only grant mapping */
p2m_ram_paging_out = 9, /* Memory that is being paged out */
p2m_ram_paged = 10, /* Memory that has been paged out */
p2m_ram_paging_in = 11, /* Memory that is being paged in */
p2m_ram_paging_in_start = 12, /* Memory that is being paged in */
p2m_ram_shared = 13, /* Shared or sharable memory */
- p2m_ram_broken =14, /* Broken page, access cause domain crash */
+ p2m_ram_broken = 14, /* Broken page, access cause domain crash */
} p2m_type_t;
/*
@@ -170,6 +162,9 @@ typedef enum {
* reinit the type correctly after fault */
#define P2M_SHARABLE_TYPES (p2m_to_mask(p2m_ram_rw))
#define P2M_SHARED_TYPES (p2m_to_mask(p2m_ram_shared))
+
+/* Broken type: the frame backing this pfn has failed in hardware
+ * and must not be touched. */
#define P2M_BROKEN_TYPES (p2m_to_mask(p2m_ram_broken))
/* Useful predicates */
@@ -190,12 +185,7 @@ typedef enum {
#define p2m_is_shared(_t) (p2m_to_mask(_t) & P2M_SHARED_TYPES)
#define p2m_is_broken(_t) (p2m_to_mask(_t) & P2M_BROKEN_TYPES)
-/* Populate-on-demand */
-#define POPULATE_ON_DEMAND_MFN (1<<9)
-#define POD_PAGE_ORDER 9
-
-#define PAGING_MFN INVALID_MFN
-
+/* Per-p2m-table state */
struct p2m_domain {
/* Lock that protects updates to the p2m */
spinlock_t lock;
@@ -298,10 +288,6 @@ struct p2m_domain *p2m_get_p2m(struct vcpu *v);
#define p2m_get_pagetable(p2m) ((p2m)->phys_table)
-/* Flushes specified p2m table */
-void p2m_flush(struct vcpu *v, struct p2m_domain *p2m);
-/* Flushes all nested p2m tables */
-void p2m_flush_nestedp2m(struct domain *d);
/*
* The P2M lock. This protects all updates to the p2m table.
@@ -376,23 +362,6 @@ void p2m_flush_nestedp2m(struct domain *d);
spin_unlock(&(_domain)->arch.nested_p2m_lock); \
} while (0)
-/* Extract the type from the PTE flags that store it */
-static inline p2m_type_t p2m_flags_to_type(unsigned long flags)
-{
- /* Type is stored in the "available" bits */
-#ifdef __x86_64__
- /* For AMD IOMMUs we need to use type 0 for plain RAM, but we need
- * to make sure that an entirely empty PTE doesn't have RAM type */
- if ( flags == 0 )
- return p2m_invalid;
- /* AMD IOMMUs use bits 9-11 to encode next io page level and bits
- * 59-62 for iommu flags so we can't use them to store p2m type info. */
- return (flags >> 12) & 0x7f;
-#else
- return (flags >> 9) & 0x7;
-#endif
-}
-
/* Read the current domain's p2m table. Do not populate PoD pages. */
static inline mfn_t gfn_to_mfn_type_current(struct p2m_domain *p2m,
unsigned long gfn, p2m_type_t *t,
@@ -508,38 +477,6 @@ int p2m_alloc_table(struct p2m_domain *p2m);
void p2m_teardown(struct p2m_domain *p2m);
void p2m_final_teardown(struct domain *d);
-/* Dump PoD information about the domain */
-void p2m_pod_dump_data(struct p2m_domain *p2m);
-
-/* Move all pages from the populate-on-demand cache to the domain page_list
- * (usually in preparation for domain destruction) */
-void p2m_pod_empty_cache(struct domain *d);
-
-/* Set populate-on-demand cache size so that the total memory allocated to a
- * domain matches target */
-int p2m_pod_set_mem_target(struct domain *d, unsigned long target);
-
-/* Call when decreasing memory reservation to handle PoD entries properly.
- * Will return '1' if all entries were handled and nothing more need be done.*/
-int
-p2m_pod_decrease_reservation(struct domain *d,
- xen_pfn_t gpfn,
- unsigned int order);
-
-/* Called by p2m code when demand-populating a PoD page */
-int
-p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
- unsigned int order,
- p2m_query_t q);
-
-/* Scan pod cache when offline/broken page triggered */
-int
-p2m_pod_offline_or_broken_hit(struct page_info *p);
-
-/* Replace pod cache when offline/broken page triggered */
-void
-p2m_pod_offline_or_broken_replace(struct page_info *p);
-
/* Add a page to a domain's p2m table */
int guest_physmap_add_entry(struct p2m_domain *p2m, unsigned long gfn,
unsigned long mfn, unsigned int page_order,
@@ -553,10 +490,7 @@ void guest_physmap_remove_entry(struct p2m_domain *p2m, unsigned long gfn,
int guest_physmap_mark_populate_on_demand(struct domain *d, unsigned long gfn,
unsigned int order);
-/* Untyped version for RAM only, for compatibility
- *
- * Return 0 for success
- */
+/* Untyped version for RAM only, for compatibility */
static inline int guest_physmap_add_page(struct domain *d,
unsigned long gfn,
unsigned long mfn,
@@ -584,8 +518,46 @@ p2m_type_t p2m_change_type(struct p2m_domain *p2m, unsigned long gfn,
int set_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn, mfn_t mfn);
int clear_mmio_p2m_entry(struct p2m_domain *p2m, unsigned long gfn);
-void nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
- l1_pgentry_t *p, mfn_t table_mfn, l1_pgentry_t new, unsigned int level);
+
+/*
+ * Populate-on-demand
+ */
+
+/* Dump PoD information about the domain */
+void p2m_pod_dump_data(struct p2m_domain *p2m);
+
+/* Move all pages from the populate-on-demand cache to the domain page_list
+ * (usually in preparation for domain destruction) */
+void p2m_pod_empty_cache(struct domain *d);
+
+/* Set populate-on-demand cache size so that the total memory allocated to a
+ * domain matches target */
+int p2m_pod_set_mem_target(struct domain *d, unsigned long target);
+
+/* Call when decreasing memory reservation to handle PoD entries properly.
+ * Will return '1' if all entries were handled and nothing more need be done.*/
+int
+p2m_pod_decrease_reservation(struct domain *d,
+ xen_pfn_t gpfn,
+ unsigned int order);
+
+/* Called by p2m code when demand-populating a PoD page */
+int
+p2m_pod_demand_populate(struct p2m_domain *p2m, unsigned long gfn,
+ unsigned int order,
+ p2m_query_t q);
+
+/* Scan pod cache when offline/broken page triggered */
+int
+p2m_pod_offline_or_broken_hit(struct page_info *p);
+
+/* Replace pod cache when offline/broken page triggered */
+void
+p2m_pod_offline_or_broken_replace(struct page_info *p);
+
+/*
+ * Paging to disk and page-sharing
+ */
#ifdef __x86_64__
/* Modify p2m table for shared gfn */
@@ -680,6 +652,40 @@ extern void audit_p2m(struct p2m_domain *p2m, int strict_m2p);
#define P2M_DEBUG(_f, _a...) do { (void)(_f); } while(0)
#endif
+
+/*
+ * Functions specific to the p2m-pt implementation
+ */
+
+/* Extract the type from the PTE flags that store it */
+static inline p2m_type_t p2m_flags_to_type(unsigned long flags)
+{
+ /* Type is stored in the "available" bits */
+#ifdef __x86_64__
+ /* For AMD IOMMUs we need to use type 0 for plain RAM, but we need
+ * to make sure that an entirely empty PTE doesn't have RAM type */
+ if ( flags == 0 )
+ return p2m_invalid;
+ /* AMD IOMMUs use bits 9-11 to encode next io page level and bits
+ * 59-62 for iommu flags so we can't use them to store p2m type info. */
+ return (flags >> 12) & 0x7f;
+#else
+ return (flags >> 9) & 0x7;
+#endif
+}
+
+/*
+ * Nested p2m: shadow p2m tables used for nexted HVM virtualization
+ */
+
+/* Flushes specified p2m table */
+void p2m_flush(struct vcpu *v, struct p2m_domain *p2m);
+/* Flushes all nested p2m tables */
+void p2m_flush_nestedp2m(struct domain *d);
+
+void nestedp2m_write_p2m_entry(struct p2m_domain *p2m, unsigned long gfn,
+ l1_pgentry_t *p, mfn_t table_mfn, l1_pgentry_t new, unsigned int level);
+
#endif /* _XEN_P2M_H */
/*
diff --git a/xen/include/asm-x86/x86_32/page.h b/xen/include/asm-x86/x86_32/page.h
index 122463dc4d..8dd4310b27 100644
--- a/xen/include/asm-x86/x86_32/page.h
+++ b/xen/include/asm-x86/x86_32/page.h
@@ -15,6 +15,7 @@
#define L3_PAGETABLE_ENTRIES 4
#define ROOT_PAGETABLE_ENTRIES L3_PAGETABLE_ENTRIES
#define SUPERPAGE_ORDER PAGETABLE_ORDER
+#define SUPERPAGE_PAGES (1<<SUPERPAGE_ORDER)
/*
* Architecturally, physical addresses may be up to 52 bits. However, the
diff --git a/xen/include/asm-x86/x86_64/page.h b/xen/include/asm-x86/x86_64/page.h
index 38edb91bf3..d146e992e8 100644
--- a/xen/include/asm-x86/x86_64/page.h
+++ b/xen/include/asm-x86/x86_64/page.h
@@ -17,6 +17,7 @@
#define L4_PAGETABLE_ENTRIES (1<<PAGETABLE_ORDER)
#define ROOT_PAGETABLE_ENTRIES L4_PAGETABLE_ENTRIES
#define SUPERPAGE_ORDER PAGETABLE_ORDER
+#define SUPERPAGE_PAGES (1<<SUPERPAGE_ORDER)
#define __PAGE_OFFSET DIRECTMAP_VIRT_START
#define __XEN_VIRT_START XEN_VIRT_START