debuggers.hg
changeset 22791:32b7a4f2d399
x86/mm: make page-sharing use the proper typecount functions
instead of having its own cmpxchg loops.
This should remove some confusion about the use of PGT_none,
and also makes page-sharing participate properly in the TLB
flushing discipline.
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
instead of having its own cmpxchg loops.
This should remove some confusion about the use of PGT_none,
and also makes page-sharing participate properly in the TLB
flushing discipline.
Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
author | Tim Deegan <Tim.Deegan@citrix.com> |
---|---|
date | Thu Jan 13 15:46:13 2011 +0000 (2011-01-13) |
parents | b01ef59c8c80 |
children | f1a5ac39c15e |
files | xen/arch/x86/mm.c |
line diff
1.1 --- a/xen/arch/x86/mm.c Thu Jan 13 15:46:13 2011 +0000 1.2 +++ b/xen/arch/x86/mm.c Thu Jan 13 15:46:13 2011 +0000 1.3 @@ -2367,7 +2367,7 @@ static int __get_page_type(struct page_i 1.4 1.5 /* No special validation needed for writable pages. */ 1.6 /* Page tables and GDT/LDT need to be scanned for validity. */ 1.7 - if ( type == PGT_writable_page ) 1.8 + if ( type == PGT_writable_page || type == PGT_shared_page ) 1.9 nx |= PGT_validated; 1.10 } 1.11 } 1.12 @@ -4167,32 +4167,25 @@ int page_make_sharable(struct domain *d, 1.13 struct page_info *page, 1.14 int expected_refcnt) 1.15 { 1.16 - unsigned long x, nx, y; 1.17 - 1.18 - /* Acquire ref first, so that the page doesn't dissapear from us */ 1.19 - if(!get_page(page, d)) 1.20 - return -EINVAL; 1.21 - 1.22 spin_lock(&d->page_alloc_lock); 1.23 1.24 /* Change page type and count atomically */ 1.25 - y = page->u.inuse.type_info; 1.26 - nx = PGT_shared_page | PGT_validated | 1; 1.27 - do { 1.28 - x = y; 1.29 - /* We can only change the type if count is zero, and 1.30 - type is PGT_none */ 1.31 - if((x & (PGT_type_mask | PGT_count_mask)) != PGT_none) 1.32 - { 1.33 - put_page(page); 1.34 - spin_unlock(&d->page_alloc_lock); 1.35 - return -EEXIST; 1.36 - } 1.37 - y = cmpxchg(&page->u.inuse.type_info, x, nx); 1.38 - } while(x != y); 1.39 - 1.40 - /* Check if the ref count is 2. The first from PGT_allocated, and the second 1.41 - * from get_page at the top of this function */ 1.42 + if ( !get_page_and_type(page, d, PGT_shared_page) ) 1.43 + { 1.44 + spin_unlock(&d->page_alloc_lock); 1.45 + return -EINVAL; 1.46 + } 1.47 + 1.48 + /* Check it wasn't already sharable and undo if it was */ 1.49 + if ( (page->u.inuse.type_info & PGT_count_mask) != 1 ) 1.50 + { 1.51 + put_page_and_type(page); 1.52 + spin_unlock(&d->page_alloc_lock); 1.53 + return -EEXIST; 1.54 + } 1.55 + 1.56 + /* Check if the ref count is 2. The first from PGT_allocated, and 1.57 + * the second from get_page_and_type at the top of this function */ 1.58 if(page->count_info != (PGC_allocated | (2 + expected_refcnt))) 1.59 { 1.60 /* Return type count back to zero */ 1.61 @@ -4205,39 +4198,27 @@ int page_make_sharable(struct domain *d, 1.62 d->tot_pages--; 1.63 page_list_del(page, &d->page_list); 1.64 spin_unlock(&d->page_alloc_lock); 1.65 - 1.66 - /* NOTE: We are not putting the page back. In effect this function acquires 1.67 - * one ref and type ref for the caller */ 1.68 - 1.69 return 0; 1.70 } 1.71 1.72 int page_make_private(struct domain *d, struct page_info *page) 1.73 { 1.74 - unsigned long x, y; 1.75 - 1.76 if(!get_page(page, dom_cow)) 1.77 return -EINVAL; 1.78 1.79 spin_lock(&d->page_alloc_lock); 1.80 1.81 - /* Change page type and count atomically */ 1.82 - y = page->u.inuse.type_info; 1.83 - do { 1.84 - x = y; 1.85 - /* We can only change the type if count is one */ 1.86 - if((x & (PGT_type_mask | PGT_count_mask)) != 1.87 - (PGT_shared_page | 1)) 1.88 - { 1.89 - put_page(page); 1.90 - spin_unlock(&d->page_alloc_lock); 1.91 - return -EEXIST; 1.92 - } 1.93 - y = cmpxchg(&page->u.inuse.type_info, x, PGT_none); 1.94 - } while(x != y); 1.95 - 1.96 - /* We dropped type ref above, drop one ref count too */ 1.97 - put_page(page); 1.98 + /* We can only change the type if count is one */ 1.99 + if ( (page->u.inuse.type_info & (PGT_type_mask | PGT_count_mask)) 1.100 + != (PGT_shared_page | 1) ) 1.101 + { 1.102 + put_page(page); 1.103 + spin_unlock(&d->page_alloc_lock); 1.104 + return -EEXIST; 1.105 + } 1.106 + 1.107 + /* Drop the final typecount */ 1.108 + put_page_and_type(page); 1.109 1.110 /* Change the owner */ 1.111 ASSERT(page_get_owner(page) == dom_cow);