[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] This patch defines a new PGT type called PGT_shared_page and a new synthetic
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1261031276 0 # Node ID 3a3be3938b2c71d179330b10fcb187db00c837b2 # Parent 9b344d919ee4c54e33d6f14c44a9fa1856aa6b7d This patch defines a new PGT type called PGT_shared_page and a new synthetic domain called 'dom_cow'. In order to share a page, the type needs to be changed to PGT_shared_page and the owner to dom_dow. Only pages with PGT_none, and no type count are allowed to become sharable. Conversly, sharable pages can only be made 'private' if type count equals one. page_make_sharable() and page_make_private() handle these transitions. Signed-off-by: Grzegorz Milos <Grzegorz.Milos@xxxxxxxxxx> --- xen/arch/x86/mm.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++- xen/common/page_alloc.c | 9 +++- xen/include/asm-x86/mm.h | 45 +++++++++++---------- xen/include/public/xen.h | 4 + 4 files changed, 134 insertions(+), 22 deletions(-) diff -r 9b344d919ee4 -r 3a3be3938b2c xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Thu Dec 17 06:27:55 2009 +0000 +++ b/xen/arch/x86/mm.c Thu Dec 17 06:27:56 2009 +0000 @@ -138,7 +138,7 @@ int mem_hotplug = 0; int mem_hotplug = 0; /* Private domain structs for DOMID_XEN and DOMID_IO. */ -struct domain *dom_xen, *dom_io; +struct domain *dom_xen, *dom_io, *dom_cow; /* Frame table size in pages. */ unsigned long max_page; @@ -250,6 +250,13 @@ void __init arch_init_memory(void) */ dom_io = domain_create(DOMID_IO, DOMCRF_dummy, 0); BUG_ON(dom_io == NULL); + + /* + * Initialise our DOMID_IO domain. + * This domain owns sharable pages. + */ + dom_cow = domain_create(DOMID_COW, DOMCRF_dummy, 0); + BUG_ON(dom_cow == NULL); /* First 1MB of RAM is historically marked as I/O. */ for ( i = 0; i < 0x100; i++ ) @@ -3789,6 +3796,95 @@ int steal_page( return -1; } +int page_make_sharable(struct domain *d, + struct page_info *page, + int expected_refcnt) +{ + unsigned long x, nx, y; + + /* Acquire ref first, so that the page doesn't dissapear from us */ + if(!get_page(page, d)) + return -EINVAL; + + spin_lock(&d->page_alloc_lock); + + /* Change page type and count atomically */ + y = page->u.inuse.type_info; + nx = PGT_shared_page | PGT_validated | 1; + do { + x = y; + /* We can only change the type if count is zero, and + type is PGT_none */ + if((x & (PGT_type_mask | PGT_count_mask)) != PGT_none) + { + put_page(page); + spin_unlock(&d->page_alloc_lock); + return -EEXIST; + } + y = cmpxchg(&page->u.inuse.type_info, x, nx); + } while(x != y); + + /* Check if the ref count is 2. The first from PGT_allocated, and the second + * from get_page at the top of this function */ + if(page->count_info != (PGC_allocated | (2 + expected_refcnt))) + { + /* Return type count back to zero */ + put_page_and_type(page); + spin_unlock(&d->page_alloc_lock); + return -E2BIG; + } + + page_set_owner(page, dom_cow); + d->tot_pages--; + page_list_del(page, &d->page_list); + spin_unlock(&d->page_alloc_lock); + + /* NOTE: We are not putting the page back. In effect this function acquires + * one ref and type ref for the caller */ + + return 0; +} + +int page_make_private(struct domain *d, struct page_info *page) +{ + unsigned long x, y; + + if(!get_page(page, dom_cow)) + return -EINVAL; + + spin_lock(&d->page_alloc_lock); + + /* Change page type and count atomically */ + y = page->u.inuse.type_info; + do { + x = y; + /* We can only change the type if count is one */ + if((x & (PGT_type_mask | PGT_count_mask)) != + (PGT_shared_page | 1)) + { + put_page(page); + spin_unlock(&d->page_alloc_lock); + return -EEXIST; + } + y = cmpxchg(&page->u.inuse.type_info, x, PGT_none); + } while(x != y); + + /* We dropped type ref above, drop one ref count too */ + put_page(page); + + /* Change the owner */ + ASSERT(page_get_owner(page) == dom_cow); + page_set_owner(page, d); + + d->tot_pages++; + page_list_add_tail(page, &d->page_list); + spin_unlock(&d->page_alloc_lock); + + put_page(page); + + return 0; +} + static int __do_update_va_mapping( unsigned long va, u64 val64, unsigned long flags, struct domain *pg_owner) { diff -r 9b344d919ee4 -r 3a3be3938b2c xen/common/page_alloc.c --- a/xen/common/page_alloc.c Thu Dec 17 06:27:55 2009 +0000 +++ b/xen/common/page_alloc.c Thu Dec 17 06:27:56 2009 +0000 @@ -1145,7 +1145,7 @@ void free_domheap_pages(struct page_info spin_unlock_recursive(&d->page_alloc_lock); } - else if ( likely(d != NULL) ) + else if ( likely(d != NULL) && likely(d != dom_cow) ) { /* NB. May recursively lock from relinquish_memory(). */ spin_lock_recursive(&d->page_alloc_lock); @@ -1171,6 +1171,13 @@ void free_domheap_pages(struct page_info scrub_one_page(&pg[i]); free_heap_pages(pg, order); + } + else if ( unlikely(d == dom_cow) ) + { + ASSERT(order == 0); + scrub_one_page(pg); + free_heap_pages(pg, 0); + drop_dom_ref = 0; } else { diff -r 9b344d919ee4 -r 3a3be3938b2c xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Thu Dec 17 06:27:55 2009 +0000 +++ b/xen/include/asm-x86/mm.h Thu Dec 17 06:27:56 2009 +0000 @@ -155,33 +155,34 @@ struct page_info #define PG_mask(x, idx) (x ## UL << PG_shift(idx)) /* The following page types are MUTUALLY EXCLUSIVE. */ -#define PGT_none PG_mask(0, 3) /* no special uses of this page */ -#define PGT_l1_page_table PG_mask(1, 3) /* using as an L1 page table? */ -#define PGT_l2_page_table PG_mask(2, 3) /* using as an L2 page table? */ -#define PGT_l3_page_table PG_mask(3, 3) /* using as an L3 page table? */ -#define PGT_l4_page_table PG_mask(4, 3) /* using as an L4 page table? */ -#define PGT_seg_desc_page PG_mask(5, 3) /* using this page in a GDT/LDT? */ -#define PGT_writable_page PG_mask(7, 3) /* has writable mappings? */ -#define PGT_type_mask PG_mask(7, 3) /* Bits 29-31. */ +#define PGT_none PG_mask(0, 4) /* no special uses of this page */ +#define PGT_l1_page_table PG_mask(1, 4) /* using as an L1 page table? */ +#define PGT_l2_page_table PG_mask(2, 4) /* using as an L2 page table? */ +#define PGT_l3_page_table PG_mask(3, 4) /* using as an L3 page table? */ +#define PGT_l4_page_table PG_mask(4, 4) /* using as an L4 page table? */ +#define PGT_seg_desc_page PG_mask(5, 4) /* using this page in a GDT/LDT? */ +#define PGT_writable_page PG_mask(7, 4) /* has writable mappings? */ +#define PGT_shared_page PG_mask(8, 4) /* CoW sharable page */ +#define PGT_type_mask PG_mask(15, 4) /* Bits 28-31 or 60-63. */ /* Owning guest has pinned this page to its current type? */ -#define _PGT_pinned PG_shift(4) -#define PGT_pinned PG_mask(1, 4) +#define _PGT_pinned PG_shift(5) +#define PGT_pinned PG_mask(1, 5) /* Has this page been validated for use as its current type? */ -#define _PGT_validated PG_shift(5) -#define PGT_validated PG_mask(1, 5) +#define _PGT_validated PG_shift(6) +#define PGT_validated PG_mask(1, 6) /* PAE only: is this an L2 page directory containing Xen-private mappings? */ -#define _PGT_pae_xen_l2 PG_shift(6) -#define PGT_pae_xen_l2 PG_mask(1, 6) +#define _PGT_pae_xen_l2 PG_shift(7) +#define PGT_pae_xen_l2 PG_mask(1, 7) /* Has this page been *partially* validated for use as its current type? */ -#define _PGT_partial PG_shift(7) -#define PGT_partial PG_mask(1, 7) +#define _PGT_partial PG_shift(8) +#define PGT_partial PG_mask(1, 8) /* Page is locked? */ -#define _PGT_locked PG_shift(8) -#define PGT_locked PG_mask(1, 8) +#define _PGT_locked PG_shift(9) +#define PGT_locked PG_mask(1, 9) /* Count of uses of this frame as its current type. */ -#define PGT_count_width PG_shift(8) +#define PGT_count_width PG_shift(9) #define PGT_count_mask ((1UL<<PGT_count_width)-1) /* Cleared when the owning guest 'frees' this page. */ @@ -529,6 +530,10 @@ int steal_page( struct domain *d, struct page_info *page, unsigned int memflags); int donate_page( struct domain *d, struct page_info *page, unsigned int memflags); +int page_make_sharable(struct domain *d, + struct page_info *page, + int expected_refcnt); +int page_make_private(struct domain *d, struct page_info *page); int map_ldt_shadow_page(unsigned int); @@ -551,6 +556,6 @@ unsigned int domain_clamp_alloc_bitsize( unsigned long domain_get_maximum_gpfn(struct domain *d); -extern struct domain *dom_xen, *dom_io; /* for vmcoreinfo */ +extern struct domain *dom_xen, *dom_io, *dom_cow; /* for vmcoreinfo */ #endif /* __ASM_X86_MM_H__ */ diff -r 9b344d919ee4 -r 3a3be3938b2c xen/include/public/xen.h --- a/xen/include/public/xen.h Thu Dec 17 06:27:55 2009 +0000 +++ b/xen/include/public/xen.h Thu Dec 17 06:27:56 2009 +0000 @@ -366,6 +366,10 @@ typedef uint16_t domid_t; */ #define DOMID_XEN (0x7FF2U) +/* + * DOMID_COW is used as the owner of sharable pages */ +#define DOMID_COW (0x7FF3U) + /* DOMID_INVALID is used to identity invalid domid */ #define DOMID_INVALID (0x7FFFU) _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |