aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/asm-x86/mm.h
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-05-27 09:04:46 +0100
committerKeir Fraser <keir.fraser@citrix.com>2010-05-27 09:04:46 +0100
commit06ef473029dcd540b7e4fb76f89cc54fd53a840e (patch)
tree249c7b6f44168e2d7ee1d631c892e2130e2df2cb /xen/include/asm-x86/mm.h
parent92ed5b7e9c642ff0f7c68eb8a39bd687726ba03c (diff)
downloadxen-06ef473029dcd540b7e4fb76f89cc54fd53a840e.tar.gz
xen-06ef473029dcd540b7e4fb76f89cc54fd53a840e.tar.bz2
xen-06ef473029dcd540b7e4fb76f89cc54fd53a840e.zip
x86: Speed up PV-guest superpage mapping
The current version of superpage mapping takes a PGT_writable reference to every page in a superpage each time it is mapped. This is extremely slow, so slow that applications become unusable. My solution for this is to introduce a superpage table in the hypervisor, similar to the frametable structure for pages. Currently this table only has a type_info element. There are three types a superpage can have, SGT_mark, SGT_dynamic, or SGT_none. In normal operation, the first time a superpage is mapped, a PGT_writable reference is taken to each page in the superpage, and the superpage is set to type SGT_dynamic and the superpage typecount is incremented. On subsequent mappings and unmappings, only the superpage typecount changes. On the last unmap, the PGT_writable reference on each page is removed. The SGT_mark type is set and cleared through two new MMUEXT hypercalls, mark_super and unmark_super. When the hypercall is made, the superpage's type is set to SGT_mark and a PGT_writable reference is taken to its pages. On unmark, the type is cleared and the reference removed. If a page is already set to SGT_dynamic when mark_super is called, the type is changed to SGT_mark and no additional PGT_writable reference is taken. If there are still outstanding mappings of this superpage when unmark_super is called, the type is set to SGT_dynamic and the PGT_writable reference is not removed. Fast superpage mapping is only supported on 64 bit hypervisors. For 32 bit hyperviors, superpage mapping is supported but will be extremely slow. Signed-off-by: Dave McCracken <dave.mccracken@oracle.com>
Diffstat (limited to 'xen/include/asm-x86/mm.h')
-rw-r--r--xen/include/asm-x86/mm.h24
1 files changed, 23 insertions, 1 deletions
diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h
index 26a1a680f2..f1d6c8dc1c 100644
--- a/xen/include/asm-x86/mm.h
+++ b/xen/include/asm-x86/mm.h
@@ -214,6 +214,23 @@ struct page_info
#define PGC_count_width PG_shift(9)
#define PGC_count_mask ((1UL<<PGC_count_width)-1)
+#ifdef __x86_64__
+struct spage_info
+{
+ unsigned long type_info;
+};
+
+ /* The following page types are MUTUALLY EXCLUSIVE. */
+#define SGT_none PG_mask(0, 2) /* superpage not in use */
+#define SGT_mark PG_mask(1, 2) /* Marked as a superpage */
+#define SGT_dynamic PG_mask(2, 2) /* has been dynamically mapped as a superpage */
+#define SGT_type_mask PG_mask(3, 2) /* Bits 30-31 or 62-63. */
+
+ /* Count of uses of this superpage as its current type. */
+#define SGT_count_width PG_shift(3)
+#define SGT_count_mask ((1UL<<SGT_count_width)-1)
+#endif
+
#if defined(__i386__)
#define is_xen_heap_page(page) is_xen_heap_mfn(page_to_mfn(page))
#define is_xen_heap_mfn(mfn) ({ \
@@ -262,6 +279,9 @@ extern void share_xen_page_with_privileged_guests(
struct page_info *page, int readonly);
#define frame_table ((struct page_info *)FRAMETABLE_VIRT_START)
+#ifdef __x86_64__
+#define spage_table ((struct spage_info *)SPAGETABLE_VIRT_START)
+#endif
extern unsigned long max_page;
extern unsigned long total_pages;
void init_frametable(void);
@@ -305,6 +325,8 @@ void cleanup_page_cacheattr(struct page_info *page);
int is_iomem_page(unsigned long mfn);
+void clear_superpage_mark(struct page_info *page);
+
struct domain *page_get_owner_and_reference(struct page_info *page);
void put_page(struct page_info *page);
int get_page(struct page_info *page, struct domain *domain);
@@ -370,7 +392,7 @@ pae_copy_root(struct vcpu *v, l3_pgentry_t *l3tab);
int check_descriptor(const struct domain *, struct desc_struct *d);
-extern int opt_allow_hugepage;
+extern int opt_allow_superpage;
extern int mem_hotplug;
/******************************************************************************