# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1232981779 0
# Node ID 055c589f4791811797867736857b08fdd0fd6d49
# Parent c9dc7dcacc1d0c064a131da98a4063fa2cedd716
x86: No need for CMPXCHG8B on page_info structure.
Updates and checks on count_info and page owner can safely be
non-atomic.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/mm.c | 103 ++++++++++++++++++++++++------------------------------
1 files changed, 47 insertions(+), 56 deletions(-)
diff -r c9dc7dcacc1d -r 055c589f4791 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Mon Jan 26 11:22:03 2009 +0000
+++ b/xen/arch/x86/mm.c Mon Jan 26 14:56:19 2009 +0000
@@ -1927,36 +1927,29 @@ void put_page(struct page_info *page)
int get_page(struct page_info *page, struct domain *domain)
{
- u32 x, nx, y = page->count_info;
- u32 d, nd = page->u.inuse._domain;
- u32 _domain = pickle_domptr(domain);
+ u32 x, y = page->count_info;
do {
- x = y;
- nx = x + 1;
- d = nd;
+ x = y;
if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */
/* Keep one spare reference to be acquired by get_page_light(). */
- unlikely(((nx + 1) & PGC_count_mask) <= 1) || /* Overflow? */
- unlikely(d != _domain) ) /* Wrong owner? */
- {
- if ( !_shadow_mode_refcounts(domain) && !domain->is_dying )
- gdprintk(XENLOG_INFO,
- "Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%"
- PRtype_info "\n",
- page_to_mfn(page), domain, unpickle_domptr(d),
- x, page->u.inuse.type_info);
- return 0;
- }
- asm volatile (
- LOCK_PREFIX "cmpxchg8b %2"
- : "=d" (nd), "=a" (y),
- "=m" (*(volatile u64 *)(&page->count_info))
- : "0" (d), "1" (x), "c" (d), "b" (nx) );
- }
- while ( unlikely(nd != d) || unlikely(y != x) );
-
- return 1;
+ unlikely(((x + 2) & PGC_count_mask) <= 1) ) /* Overflow? */
+ goto fail;
+ }
+ while ( (y = cmpxchg(&page->count_info, x, x + 1)) != x );
+
+ if ( likely(page_get_owner(page) == domain) )
+ return 1;
+
+ put_page(page);
+
+ fail:
+ if ( !_shadow_mode_refcounts(domain) && !domain->is_dying )
+ gdprintk(XENLOG_INFO,
+ "Error pfn %lx: rd=%p, od=%p, caf=%08x, taf=%" PRtype_info,
+ page_to_mfn(page), domain, page_get_owner(page),
+ y, page->u.inuse.type_info);
+ return 0;
}
/*
@@ -3478,49 +3471,47 @@ int steal_page(
int steal_page(
struct domain *d, struct page_info *page, unsigned int memflags)
{
- u32 _d, _nd, x, y;
+ u32 x, y;
spin_lock(&d->page_alloc_lock);
+ if ( is_xen_heap_page(page) || (page_get_owner(page) != d) )
+ goto fail;
+
/*
- * The tricky bit: atomically release ownership while there is just one
- * benign reference to the page (PGC_allocated). If that reference
- * disappears then the deallocation routine will safely spin.
+ * We require there is just one reference (PGC_allocated). We temporarily
+ * drop this reference now so that we can safely swizzle the owner.
*/
- _d = pickle_domptr(d);
- _nd = page->u.inuse._domain;
- y = page->count_info;
+ y = page->count_info;
do {
x = y;
- if ( unlikely((x & (PGC_count_mask|PGC_allocated)) !=
- (1 | PGC_allocated)) || unlikely(_nd != _d) )
- {
- MEM_LOG("gnttab_transfer: Bad page %p: ed=%p(%u), sd=%p,"
- " caf=%08x, taf=%" PRtype_info "\n",
- (void *) page_to_mfn(page),
- d, d->domain_id, unpickle_domptr(_nd), x,
- page->u.inuse.type_info);
- spin_unlock(&d->page_alloc_lock);
- return -1;
- }
- asm volatile (
- LOCK_PREFIX "cmpxchg8b %2"
- : "=d" (_nd), "=a" (y),
- "=m" (*(volatile u64 *)(&page->count_info))
- : "0" (_d), "1" (x), "c" (NULL), "b" (x) );
- } while (unlikely(_nd != _d) || unlikely(y != x));
-
- /*
- * Unlink from 'd'. At least one reference remains (now anonymous), so
- * noone else is spinning to try to delete this page from 'd'.
- */
+ if ( (x & (PGC_count_mask|PGC_allocated)) != (1 | PGC_allocated) )
+ goto fail;
+ y = cmpxchg(&page->count_info, x, x & ~PGC_count_mask);
+ } while ( y != x );
+
+ /* Swizzle the owner then reinstate the PGC_allocated reference. */
+ page_set_owner(page, NULL);
+ y = page->count_info;
+ do {
+ x = y;
+ BUG_ON((x & (PGC_count_mask|PGC_allocated)) != PGC_allocated);
+ } while ( (y = cmpxchg(&page->count_info, x, x | 1)) != x );
+
+ /* Unlink from original owner. */
if ( !(memflags & MEMF_no_refcount) )
d->tot_pages--;
list_del(&page->list);
spin_unlock(&d->page_alloc_lock);
-
return 0;
+
+ fail:
+ spin_unlock(&d->page_alloc_lock);
+ MEM_LOG("Bad page %p: ed=%p(%u), sd=%p, caf=%08x, taf=%" PRtype_info,
+ (void *)page_to_mfn(page), d, d->domain_id,
+ page_get_owner(page), page->count_info, page->u.inuse.type_info);
+ return -1;
}
int do_update_va_mapping(unsigned long va, u64 val64,
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|