[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] New memory_op XENMEM_exchange. Allows atomic
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxxxx # Node ID ee3d108289370351347f46284024f3347897d2bb # Parent 231e07e22f9cd09e310a0db65ed62acb12c51855 [XEN] New memory_op XENMEM_exchange. Allows atomic exchange of one memory reservation for another of the same size, but with different properties. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/arch/ia64/xen/domain.c | 7 xen/arch/x86/domain_build.c | 2 xen/arch/x86/mm.c | 7 xen/arch/x86/shadow.c | 4 xen/arch/x86/shadow_public.c | 4 xen/common/grant_table.c | 2 xen/common/memory.c | 274 +++++++++++++++++++++++++++++++++---- xen/common/page_alloc.c | 86 +++++++---- xen/include/asm-ia64/grant_table.h | 4 xen/include/asm-ia64/mm.h | 7 xen/include/asm-x86/grant_table.h | 3 xen/include/asm-x86/mm.h | 3 xen/include/public/memory.h | 48 ++++++ xen/include/xen/mm.h | 14 + 14 files changed, 386 insertions(+), 79 deletions(-) diff -r 231e07e22f9c -r ee3d10828937 xen/arch/ia64/xen/domain.c --- a/xen/arch/ia64/xen/domain.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/arch/ia64/xen/domain.c Fri Jun 16 14:43:54 2006 +0100 @@ -1308,10 +1308,10 @@ destroy_grant_host_mapping(unsigned long //XXX heavily depends on the struct page layout. //XXX SMP int -steal_page_for_grant_transfer(struct domain *d, struct page_info *page) +steal_page(struct domain *d, struct page_info *page, unsigned int memflags) { #if 0 /* if big endian */ -# error "implement big endian version of steal_page_for_grant_transfer()" +# error "implement big endian version of steal_page()" #endif u32 _d, _nd; u64 x, nx, y; @@ -1371,7 +1371,8 @@ steal_page_for_grant_transfer(struct dom * Unlink from 'd'. At least one reference remains (now anonymous), so * noone else is spinning to try to delete this page from 'd'. */ - d->tot_pages--; + if ( !(memflags & MEMF_no_refcount) ) + d->tot_pages--; list_del(&page->list); spin_unlock(&d->page_alloc_lock); diff -r 231e07e22f9c -r ee3d10828937 xen/arch/x86/domain_build.c --- a/xen/arch/x86/domain_build.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/arch/x86/domain_build.c Fri Jun 16 14:43:54 2006 +0100 @@ -374,7 +374,7 @@ int construct_dom0(struct domain *d, * Allocate from DMA pool: on i386 this ensures that our low-memory 1:1 * mapping covers the allocation. */ - if ( (page = alloc_domheap_pages(d, order, ALLOC_DOM_DMA)) == NULL ) + if ( (page = alloc_domheap_pages(d, order, MEMF_dma)) == NULL ) panic("Not enough RAM for domain 0 allocation.\n"); alloc_spfn = page_to_mfn(page); alloc_epfn = alloc_spfn + d->tot_pages; diff -r 231e07e22f9c -r ee3d10828937 xen/arch/x86/mm.c --- a/xen/arch/x86/mm.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/arch/x86/mm.c Fri Jun 16 14:43:54 2006 +0100 @@ -2598,8 +2598,8 @@ int destroy_grant_host_mapping( return destroy_grant_va_mapping(addr, frame); } -int steal_page_for_grant_transfer( - struct domain *d, struct page_info *page) +int steal_page( + struct domain *d, struct page_info *page, unsigned int memflags) { u32 _d, _nd, x, y; @@ -2636,7 +2636,8 @@ int steal_page_for_grant_transfer( * Unlink from 'd'. At least one reference remains (now anonymous), so * noone else is spinning to try to delete this page from 'd'. */ - d->tot_pages--; + if ( !(memflags & MEMF_no_refcount) ) + d->tot_pages--; list_del(&page->list); spin_unlock(&d->page_alloc_lock); diff -r 231e07e22f9c -r ee3d10828937 xen/arch/x86/shadow.c --- a/xen/arch/x86/shadow.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/arch/x86/shadow.c Fri Jun 16 14:43:54 2006 +0100 @@ -292,10 +292,10 @@ alloc_shadow_page(struct domain *d, #elif CONFIG_PAGING_LEVELS >= 3 if ( d->arch.ops->guest_paging_levels == PAGING_L2 && psh_type == PGT_l4_shadow ) /* allocated for PAE PDP page */ - page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); + page = alloc_domheap_pages(NULL, 0, MEMF_dma); else if ( d->arch.ops->guest_paging_levels == PAGING_L3 && (psh_type == PGT_l3_shadow || psh_type == PGT_l4_shadow) ) - page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); /* allocated for PAE PDP page */ + page = alloc_domheap_pages(NULL, 0, MEMF_dma); /* allocated for PAE PDP page */ else page = alloc_domheap_page(NULL); #endif diff -r 231e07e22f9c -r ee3d10828937 xen/arch/x86/shadow_public.c --- a/xen/arch/x86/shadow_public.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/arch/x86/shadow_public.c Fri Jun 16 14:43:54 2006 +0100 @@ -43,7 +43,7 @@ int shadow_direct_map_init(struct domain struct page_info *page; l3_pgentry_t *root; - if ( !(page = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA)) ) + if ( !(page = alloc_domheap_pages(NULL, 0, MEMF_dma)) ) return 0; root = map_domain_page(page_to_mfn(page)); @@ -395,7 +395,7 @@ static void alloc_monitor_pagetable(stru ASSERT(!pagetable_get_paddr(v->arch.monitor_table)); /* we should only get called once */ - m3mfn_info = alloc_domheap_pages(NULL, 0, ALLOC_DOM_DMA); + m3mfn_info = alloc_domheap_pages(NULL, 0, MEMF_dma); ASSERT( m3mfn_info ); m3mfn = page_to_mfn(m3mfn_info); diff -r 231e07e22f9c -r ee3d10828937 xen/common/grant_table.c --- a/xen/common/grant_table.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/common/grant_table.c Fri Jun 16 14:43:54 2006 +0100 @@ -634,7 +634,7 @@ gnttab_transfer( goto copyback; } - if ( steal_page_for_grant_transfer(d, page) < 0 ) + if ( steal_page(d, page, 0) < 0 ) { gop.status = GNTST_bad_page; goto copyback; diff -r 231e07e22f9c -r ee3d10828937 xen/common/memory.c --- a/xen/common/memory.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/common/memory.c Fri Jun 16 14:43:54 2006 +0100 @@ -34,7 +34,7 @@ increase_reservation( XEN_GUEST_HANDLE(xen_pfn_t) extent_list, unsigned int nr_extents, unsigned int extent_order, - unsigned int flags, + unsigned int memflags, int *preempted) { struct page_info *page; @@ -58,11 +58,11 @@ increase_reservation( } if ( unlikely((page = alloc_domheap_pages( - d, extent_order, flags)) == NULL) ) + d, extent_order, memflags)) == NULL) ) { DPRINTK("Could not allocate order=%d extent: " - "id=%d flags=%x (%ld of %d)\n", - extent_order, d->domain_id, flags, i, nr_extents); + "id=%d memflags=%x (%ld of %d)\n", + extent_order, d->domain_id, memflags, i, nr_extents); return i; } @@ -84,7 +84,7 @@ populate_physmap( XEN_GUEST_HANDLE(xen_pfn_t) extent_list, unsigned int nr_extents, unsigned int extent_order, - unsigned int flags, + unsigned int memflags, int *preempted) { struct page_info *page; @@ -111,11 +111,11 @@ populate_physmap( goto out; if ( unlikely((page = alloc_domheap_pages( - d, extent_order, flags)) == NULL) ) + d, extent_order, memflags)) == NULL) ) { DPRINTK("Could not allocate order=%d extent: " - "id=%d flags=%x (%ld of %d)\n", - extent_order, d->domain_id, flags, i, nr_extents); + "id=%d memflags=%x (%ld of %d)\n", + extent_order, d->domain_id, memflags, i, nr_extents); goto out; } @@ -183,7 +183,6 @@ decrease_reservation( XEN_GUEST_HANDLE(xen_pfn_t) extent_list, unsigned int nr_extents, unsigned int extent_order, - unsigned int flags, int *preempted) { unsigned long i, j; @@ -276,10 +275,234 @@ translate_gpfn_list( return 0; } +static long +memory_exchange(XEN_GUEST_HANDLE(xen_memory_exchange_t) arg) +{ + struct xen_memory_exchange exch; + LIST_HEAD(in_chunk_list); + LIST_HEAD(out_chunk_list); + unsigned long in_chunk_order, out_chunk_order; + unsigned long gpfn, gmfn, mfn; + unsigned long i, j, k; + unsigned int memflags = 0; + long rc = 0; + struct domain *d; + struct page_info *page; + + if ( copy_from_guest(&exch, arg, 1) ) + return -EFAULT; + + /* Various sanity checks. */ + if ( (exch.nr_exchanged > exch.in.nr_extents) || + /* Input and output domain identifiers match? */ + (exch.in.domid != exch.out.domid) || + /* Sizes of input and output lists do not overflow a long? */ + ((~0UL >> exch.in.extent_order) < exch.in.nr_extents) || + ((~0UL >> exch.out.extent_order) < exch.out.nr_extents) || + /* Sizes of input and output lists match? */ + ((exch.in.nr_extents << exch.in.extent_order) != + (exch.out.nr_extents << exch.out.extent_order)) ) + { + rc = -EINVAL; + goto fail_early; + } + + /* Only privileged guests can allocate multi-page contiguous extents. */ + if ( ((exch.in.extent_order != 0) || (exch.out.extent_order != 0)) && + !multipage_allocation_permitted(current->domain) ) + { + rc = -EPERM; + goto fail_early; + } + + if ( (exch.out.address_bits != 0) && + (exch.out.address_bits < + (get_order_from_pages(max_page) + PAGE_SHIFT)) ) + { + if ( exch.out.address_bits < 31 ) + { + rc = -ENOMEM; + goto fail_early; + } + memflags = MEMF_dma; + } + + guest_handle_add_offset(exch.in.extent_start, exch.nr_exchanged); + exch.in.nr_extents -= exch.nr_exchanged; + + if ( exch.in.extent_order <= exch.out.extent_order ) + { + in_chunk_order = exch.out.extent_order - exch.in.extent_order; + out_chunk_order = 0; + guest_handle_add_offset( + exch.out.extent_start, exch.nr_exchanged >> in_chunk_order); + exch.out.nr_extents -= exch.nr_exchanged >> in_chunk_order; + } + else + { + in_chunk_order = 0; + out_chunk_order = exch.in.extent_order - exch.out.extent_order; + guest_handle_add_offset( + exch.out.extent_start, exch.nr_exchanged << out_chunk_order); + exch.out.nr_extents -= exch.nr_exchanged << out_chunk_order; + } + + /* + * Only support exchange on calling domain right now. Otherwise there are + * tricky corner cases to consider (e.g., DOMF_dying domain). + */ + if ( unlikely(exch.in.domid != DOMID_SELF) ) + { + rc = IS_PRIV(current->domain) ? -EINVAL : -EPERM; + goto fail_early; + } + d = current->domain; + + for ( i = 0; i < (exch.in.nr_extents >> in_chunk_order); i++ ) + { + if ( hypercall_preempt_check() ) + { + exch.nr_exchanged += i << in_chunk_order; + if ( copy_field_to_guest(arg, &exch, nr_exchanged) ) + return -EFAULT; + return hypercall_create_continuation( + __HYPERVISOR_memory_op, "lh", XENMEM_exchange, arg); + } + + /* Steal a chunk's worth of input pages from the domain. */ + for ( j = 0; j < (1UL << in_chunk_order); j++ ) + { + if ( unlikely(__copy_from_guest_offset( + &gmfn, exch.in.extent_start, (i<<in_chunk_order)+j, 1)) ) + { + rc = -EFAULT; + goto fail; + } + + for ( k = 0; k < (1UL << exch.in.extent_order); k++ ) + { + mfn = gmfn_to_mfn(d, gmfn + k); + if ( unlikely(!mfn_valid(mfn)) ) + { + rc = -EINVAL; + goto fail; + } + + page = mfn_to_page(mfn); + + if ( unlikely(steal_page(d, page, MEMF_no_refcount)) ) + { + rc = -EINVAL; + goto fail; + } + + list_add(&page->list, &in_chunk_list); + } + } + + /* Allocate a chunk's worth of anonymous output pages. */ + for ( j = 0; j < (1UL << out_chunk_order); j++ ) + { + page = alloc_domheap_pages( + NULL, exch.out.extent_order, memflags); + if ( unlikely(page == NULL) ) + { + rc = -ENOMEM; + goto fail; + } + + list_add(&page->list, &out_chunk_list); + } + + /* + * Success! Beyond this point we cannot fail for this chunk. + */ + + /* Destroy final reference to each input page. */ + while ( !list_empty(&in_chunk_list) ) + { + page = list_entry(in_chunk_list.next, struct page_info, list); + list_del(&page->list); + if ( !test_and_clear_bit(_PGC_allocated, &page->count_info) ) + BUG(); + mfn = page_to_mfn(page); + guest_physmap_remove_page(d, mfn_to_gmfn(d, mfn), mfn); + put_page(page); + } + + /* Assign each output page to the domain. */ + j = 0; + while ( !list_empty(&out_chunk_list) ) + { + page = list_entry(out_chunk_list.next, struct page_info, list); + list_del(&page->list); + if ( assign_pages(d, page, exch.out.extent_order, + MEMF_no_refcount) ) + BUG(); + + /* Note that we ignore errors accessing the output extent list. */ + (void)__copy_from_guest_offset( + &gpfn, exch.out.extent_start, (i<<out_chunk_order)+j, 1); + + mfn = page_to_mfn(page); + if ( unlikely(shadow_mode_translate(d)) ) + { + for ( k = 0; k < (1UL << exch.out.extent_order); k++ ) + guest_physmap_add_page(d, gpfn + k, mfn + k); + } + else + { + for ( k = 0; k < (1UL << exch.out.extent_order); k++ ) + set_gpfn_from_mfn(mfn + k, gpfn + k); + (void)__copy_to_guest_offset( + exch.out.extent_start, (i<<out_chunk_order)+j, &mfn, 1); + } + + j++; + } + BUG_ON(j != (1UL << out_chunk_order)); + } + + exch.nr_exchanged += exch.in.nr_extents; + if ( copy_field_to_guest(arg, &exch, nr_exchanged) ) + rc = -EFAULT; + return rc; + + /* + * Failed a chunk! Free any partial chunk work. Tell caller how many + * chunks succeeded. + */ + fail: + /* Reassign any input pages we managed to steal. */ + while ( !list_empty(&in_chunk_list) ) + { + page = list_entry(in_chunk_list.next, struct page_info, list); + list_del(&page->list); + if ( assign_pages(d, page, 0, MEMF_no_refcount) ) + BUG(); + } + + /* Free any output pages we managed to allocate. */ + while ( !list_empty(&out_chunk_list) ) + { + page = list_entry(out_chunk_list.next, struct page_info, list); + list_del(&page->list); + free_domheap_pages(page, exch.out.extent_order); + } + + exch.nr_exchanged += i << in_chunk_order; + + fail_early: + if ( copy_field_to_guest(arg, &exch, nr_exchanged) ) + rc = -EFAULT; + return rc; +} + long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE(void) arg) { struct domain *d; - int rc, op, flags = 0, preempted = 0; + int rc, op, preempted = 0; + unsigned int memflags = 0; unsigned long start_extent, progress; struct xen_memory_reservation reservation; domid_t domid; @@ -291,16 +514,17 @@ long do_memory_op(unsigned long cmd, XEN case XENMEM_increase_reservation: case XENMEM_decrease_reservation: case XENMEM_populate_physmap: + start_extent = cmd >> START_EXTENT_SHIFT; + if ( copy_from_guest(&reservation, arg, 1) ) - return -EFAULT; + return start_extent; /* Is size too large for us to encode a continuation? */ if ( reservation.nr_extents > (ULONG_MAX >> START_EXTENT_SHIFT) ) - return -EINVAL; - - start_extent = cmd >> START_EXTENT_SHIFT; + return start_extent; + if ( unlikely(start_extent > reservation.nr_extents) ) - return -EINVAL; + return start_extent; if ( !guest_handle_is_null(reservation.extent_start) ) guest_handle_add_offset(reservation.extent_start, start_extent); @@ -311,16 +535,15 @@ long do_memory_op(unsigned long cmd, XEN (get_order_from_pages(max_page) + PAGE_SHIFT)) ) { if ( reservation.address_bits < 31 ) - return -ENOMEM; - flags = ALLOC_DOM_DMA; + return start_extent; + memflags = MEMF_dma; } if ( likely(reservation.domid == DOMID_SELF) ) d = current->domain; - else if ( !IS_PRIV(current->domain) ) - return -EPERM; - else if ( (d = find_domain_by_id(reservation.domid)) == NULL ) - return -ESRCH; + else if ( !IS_PRIV(current->domain) || + ((d = find_domain_by_id(reservation.domid)) == NULL) ) + return start_extent; switch ( op ) { @@ -330,7 +553,7 @@ long do_memory_op(unsigned long cmd, XEN reservation.extent_start, reservation.nr_extents, reservation.extent_order, - flags, + memflags, &preempted); break; case XENMEM_decrease_reservation: @@ -339,7 +562,6 @@ long do_memory_op(unsigned long cmd, XEN reservation.extent_start, reservation.nr_extents, reservation.extent_order, - flags, &preempted); break; case XENMEM_populate_physmap: @@ -349,7 +571,7 @@ long do_memory_op(unsigned long cmd, XEN reservation.extent_start, reservation.nr_extents, reservation.extent_order, - flags, + memflags, &preempted); break; } @@ -364,6 +586,10 @@ long do_memory_op(unsigned long cmd, XEN __HYPERVISOR_memory_op, "lh", op | (rc << START_EXTENT_SHIFT), arg); + break; + + case XENMEM_exchange: + rc = memory_exchange(guest_handle_cast(arg, xen_memory_exchange_t)); break; case XENMEM_maximum_ram_page: diff -r 231e07e22f9c -r ee3d10828937 xen/common/page_alloc.c --- a/xen/common/page_alloc.c Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/common/page_alloc.c Fri Jun 16 14:43:54 2006 +0100 @@ -531,16 +531,66 @@ void init_domheap_pages(paddr_t ps, padd } +int assign_pages( + struct domain *d, + struct page_info *pg, + unsigned int order, + unsigned int memflags) +{ + unsigned long i; + + spin_lock(&d->page_alloc_lock); + + if ( unlikely(test_bit(_DOMF_dying, &d->domain_flags)) ) + { + DPRINTK("Cannot assign page to domain%d -- dying.\n", d->domain_id); + goto fail; + } + + if ( !(memflags & MEMF_no_refcount) ) + { + if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) ) + { + DPRINTK("Over-allocation for domain %u: %u > %u\n", + d->domain_id, d->tot_pages + (1 << order), d->max_pages); + goto fail; + } + + if ( unlikely(d->tot_pages == 0) ) + get_knownalive_domain(d); + + d->tot_pages += 1 << order; + } + + for ( i = 0; i < (1 << order); i++ ) + { + ASSERT(page_get_owner(&pg[i]) == NULL); + ASSERT((pg[i].count_info & ~(PGC_allocated | 1)) == 0); + page_set_owner(&pg[i], d); + wmb(); /* Domain pointer must be visible before updating refcnt. */ + pg[i].count_info = PGC_allocated | 1; + list_add_tail(&pg[i].list, &d->page_list); + } + + spin_unlock(&d->page_alloc_lock); + return 0; + + fail: + spin_unlock(&d->page_alloc_lock); + return -1; +} + + struct page_info *alloc_domheap_pages( - struct domain *d, unsigned int order, unsigned int flags) + struct domain *d, unsigned int order, unsigned int memflags) { struct page_info *pg = NULL; cpumask_t mask; - int i; + unsigned long i; ASSERT(!in_irq()); - if ( !(flags & ALLOC_DOM_DMA) ) + if ( !(memflags & MEMF_dma) ) { pg = alloc_heap_pages(MEMZONE_DOM, order); /* Failure? Then check if we can fall back to the DMA pool. */ @@ -582,37 +632,11 @@ struct page_info *alloc_domheap_pages( flush_tlb_mask(mask); } - if ( d == NULL ) - return pg; - - spin_lock(&d->page_alloc_lock); - - if ( unlikely(test_bit(_DOMF_dying, &d->domain_flags)) || - unlikely((d->tot_pages + (1 << order)) > d->max_pages) ) - { - DPRINTK("Over-allocation for domain %u: %u > %u\n", - d->domain_id, d->tot_pages + (1 << order), d->max_pages); - DPRINTK("...or the domain is dying (%d)\n", - !!test_bit(_DOMF_dying, &d->domain_flags)); - spin_unlock(&d->page_alloc_lock); + if ( (d != NULL) && assign_pages(d, pg, order, memflags) ) + { free_heap_pages(pfn_dom_zone_type(page_to_mfn(pg)), pg, order); return NULL; } - - if ( unlikely(d->tot_pages == 0) ) - get_knownalive_domain(d); - - d->tot_pages += 1 << order; - - for ( i = 0; i < (1 << order); i++ ) - { - page_set_owner(&pg[i], d); - wmb(); /* Domain pointer must be visible before updating refcnt. */ - pg[i].count_info |= PGC_allocated | 1; - list_add_tail(&pg[i].list, &d->page_list); - } - - spin_unlock(&d->page_alloc_lock); return pg; } diff -r 231e07e22f9c -r ee3d10828937 xen/include/asm-ia64/grant_table.h --- a/xen/include/asm-ia64/grant_table.h Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/include/asm-ia64/grant_table.h Fri Jun 16 14:43:54 2006 +0100 @@ -12,16 +12,12 @@ #define create_grant_host_mapping(a, f, fl) 0 #define destroy_grant_host_mapping(a, f, fl) 0 -// for grant transfer -#define steal_page_for_grant_transfer(d, p) 0 - #else // for grant map/unmap int create_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, unsigned int flags); int destroy_grant_host_mapping(unsigned long gpaddr, unsigned long mfn, unsigned int flags); // for grant transfer -int steal_page_for_grant_transfer(struct domain *d, struct page_info *page); void guest_physmap_add_page(struct domain *d, unsigned long gpfn, unsigned long mfn); #endif diff -r 231e07e22f9c -r ee3d10828937 xen/include/asm-ia64/mm.h --- a/xen/include/asm-ia64/mm.h Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/include/asm-ia64/mm.h Fri Jun 16 14:43:54 2006 +0100 @@ -474,4 +474,11 @@ extern unsigned long ____lookup_domain_m /* Arch-specific portion of memory_op hypercall. */ #define arch_memory_op(op, arg) (-ENOSYS) +#ifndef CONFIG_XEN_IA64_DOM0_VP +#define steal_page(d, p, f) 0 +#else +int steal_page( + struct domain *d, struct page_info *page, unsigned int memflags); +#endif + #endif /* __ASM_IA64_MM_H__ */ diff -r 231e07e22f9c -r ee3d10828937 xen/include/asm-x86/grant_table.h --- a/xen/include/asm-x86/grant_table.h Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/include/asm-x86/grant_table.h Fri Jun 16 14:43:54 2006 +0100 @@ -18,9 +18,6 @@ int destroy_grant_host_mapping( int destroy_grant_host_mapping( unsigned long addr, unsigned long frame, unsigned int flags); -int steal_page_for_grant_transfer( - struct domain *d, struct page_info *page); - #define gnttab_create_shared_page(d, t, i) \ do { \ share_xen_page_with_guest( \ diff -r 231e07e22f9c -r ee3d10828937 xen/include/asm-x86/mm.h --- a/xen/include/asm-x86/mm.h Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/include/asm-x86/mm.h Fri Jun 16 14:43:54 2006 +0100 @@ -389,4 +389,7 @@ long arch_memory_op(int op, XEN_GUEST_HA long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg); long subarch_memory_op(int op, XEN_GUEST_HANDLE(void) arg); +int steal_page( + struct domain *d, struct page_info *page, unsigned int memflags); + #endif /* __ASM_X86_MM_H__ */ diff -r 231e07e22f9c -r ee3d10828937 xen/include/public/memory.h --- a/xen/include/public/memory.h Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/include/public/memory.h Fri Jun 16 14:43:54 2006 +0100 @@ -10,8 +10,8 @@ #define __XEN_PUBLIC_MEMORY_H__ /* - * Increase or decrease the specified domain's memory reservation. Returns a - * -ve errcode on failure, or the # extents successfully allocated or freed. + * Increase or decrease the specified domain's memory reservation. Returns the + * number of extents successfully allocated or freed. * arg == addr of struct xen_memory_reservation. */ #define XENMEM_increase_reservation 0 @@ -48,10 +48,52 @@ struct xen_memory_reservation { * Unprivileged domains can specify only DOMID_SELF. */ domid_t domid; - }; typedef struct xen_memory_reservation xen_memory_reservation_t; DEFINE_XEN_GUEST_HANDLE(xen_memory_reservation_t); + +/* + * An atomic exchange of memory pages. If return code is zero then + * @out.extent_list provides GMFNs of the newly-allocated memory. + * Returns zero on complete success, otherwise a negative error code. + * On complete success then always @nr_exchanged == @in.nr_extents. + * On partial success @nr_exchanged indicates how much work was done. + */ +#define XENMEM_exchange 11 +struct xen_memory_exchange { + /* + * [IN] Details of memory extents to be exchanged (GMFN bases). + * Note that @in.address_bits is ignored and unused. + */ + struct xen_memory_reservation in; + + /* + * [IN/OUT] Details of new memory extents. + * We require that: + * 1. @in.domid == @out.domid + * 2. @in.nr_extents << @in.extent_order == + * @out.nr_extents << @out.extent_order + * 3. @in.extent_start and @out.extent_start lists must not overlap + * 4. @out.extent_start lists GPFN bases to be populated + * 5. @out.extent_start is overwritten with allocated GMFN bases + */ + struct xen_memory_reservation out; + + /* + * [OUT] Number of input extents that were successfully exchanged: + * 1. The first @nr_exchanged input extents were successfully + * deallocated. + * 2. The corresponding first entries in the output extent list correctly + * indicate the GMFNs that were successfully exchanged. + * 3. All other input and output extents are untouched. + * 4. If not all input exents are exchanged then the return code of this + * command will be non-zero. + * 5. THIS FIELD MUST BE INITIALISED TO ZERO BY THE CALLER! + */ + unsigned long nr_exchanged; +}; +typedef struct xen_memory_exchange xen_memory_exchange_t; +DEFINE_XEN_GUEST_HANDLE(xen_memory_exchange_t); /* * Returns the maximum machine frame number of mapped RAM in this system. diff -r 231e07e22f9c -r ee3d10828937 xen/include/xen/mm.h --- a/xen/include/xen/mm.h Fri Jun 16 10:52:49 2006 +0100 +++ b/xen/include/xen/mm.h Fri Jun 16 14:43:54 2006 +0100 @@ -60,13 +60,23 @@ void free_xenheap_pages(void *v, unsigne /* Domain suballocator. These functions are *not* interrupt-safe.*/ void init_domheap_pages(paddr_t ps, paddr_t pe); struct page_info *alloc_domheap_pages( - struct domain *d, unsigned int order, unsigned int flags); + struct domain *d, unsigned int order, unsigned int memflags); void free_domheap_pages(struct page_info *pg, unsigned int order); unsigned long avail_domheap_pages(void); #define alloc_domheap_page(d) (alloc_domheap_pages(d,0,0)) #define free_domheap_page(p) (free_domheap_pages(p,0)) -#define ALLOC_DOM_DMA 1 +int assign_pages( + struct domain *d, + struct page_info *pg, + unsigned int order, + unsigned int memflags); + +/* memflags: */ +#define _MEMF_dma 0 +#define MEMF_dma (1U<<_MEMF_dma) +#define _MEMF_no_refcount 1 +#define MEMF_no_refcount (1U<<_MEMF_no_refcount) #ifdef CONFIG_PAGEALLOC_MAX_ORDER #define MAX_ORDER CONFIG_PAGEALLOC_MAX_ORDER _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |