WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-3.0-testing] [XEN] New memory_op XENMEM_exchange. A

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-3.0-testing] [XEN] New memory_op XENMEM_exchange. Allows atomic
From: Xen patchbot-3.0-testing <patchbot-3.0-testing@xxxxxxxxxxxxxxxxxxx>
Date: Sat, 17 Jun 2006 15:50:43 +0000
Delivery-date: Sat, 17 Jun 2006 08:52:54 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID ec2ac5a5f0a31d3fbab26b738af814e7c3428105
# Parent  532979a7807111ff387df950e314ed97dd411e6f
[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-unstable changeset:   10360:ee3d108289370351347f46284024f3347897d2bb
xen-unstable date:        Fri Jun 16 14:43:54 2006 +0100
---
 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-x86/grant_table.h |    3 
 xen/include/asm-x86/mm.h          |    3 
 xen/include/public/memory.h       |   47 ++++++
 xen/include/xen/mm.h              |   14 +
 11 files changed, 374 insertions(+), 72 deletions(-)

diff -r 532979a78071 -r ec2ac5a5f0a3 xen/arch/x86/domain_build.c
--- a/xen/arch/x86/domain_build.c       Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/arch/x86/domain_build.c       Sat Jun 17 12:48:07 2006 +0100
@@ -368,7 +368,7 @@ int construct_dom0(struct domain *d,
         panic("Domain 0 allocation is too small for kernel image.\n");
 
     /* Allocate from DMA pool: PAE L3 table must be below 4GB boundary. */
-    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 532979a78071 -r ec2ac5a5f0a3 xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/arch/x86/mm.c Sat Jun 17 12:48:07 2006 +0100
@@ -2482,8 +2482,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;
 
@@ -2520,7 +2520,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 532979a78071 -r ec2ac5a5f0a3 xen/arch/x86/shadow.c
--- a/xen/arch/x86/shadow.c     Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/arch/x86/shadow.c     Sat Jun 17 12:48:07 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 532979a78071 -r ec2ac5a5f0a3 xen/arch/x86/shadow_public.c
--- a/xen/arch/x86/shadow_public.c      Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/arch/x86/shadow_public.c      Sat Jun 17 12:48:07 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));
@@ -381,7 +381,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 532979a78071 -r ec2ac5a5f0a3 xen/common/grant_table.c
--- a/xen/common/grant_table.c  Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/common/grant_table.c  Sat Jun 17 12:48:07 2006 +0100
@@ -637,7 +637,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 532979a78071 -r ec2ac5a5f0a3 xen/common/memory.c
--- a/xen/common/memory.c       Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/common/memory.c       Sat Jun 17 12:48:07 2006 +0100
@@ -34,7 +34,7 @@ increase_reservation(
     GUEST_HANDLE(ulong) extent_list,
     unsigned int   nr_extents,
     unsigned int   extent_order,
-    unsigned int   flags,
+    unsigned int   memflags,
     int           *preempted)
 {
     struct page_info *page;
@@ -57,11 +57,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;
         }
 
@@ -83,7 +83,7 @@ populate_physmap(
     GUEST_HANDLE(ulong) extent_list,
     unsigned int  nr_extents,
     unsigned int  extent_order,
-    unsigned int  flags,
+    unsigned int  memflags,
     int          *preempted)
 {
     struct page_info *page;
@@ -108,11 +108,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;
         }
 
@@ -180,7 +180,6 @@ decrease_reservation(
     GUEST_HANDLE(ulong) extent_list,
     unsigned int   nr_extents,
     unsigned int   extent_order,
-    unsigned int   flags,
     int           *preempted)
 {
     unsigned long    i, j, gmfn;
@@ -270,10 +269,234 @@ translate_gpfn_list(
     return 0;
 }
 
+static long
+memory_exchange(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, 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;
@@ -285,16 +508,17 @@ long do_memory_op(unsigned long cmd, GUE
     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);
@@ -305,16 +529,15 @@ long do_memory_op(unsigned long cmd, GUE
               (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 )
         {
@@ -324,7 +547,7 @@ long do_memory_op(unsigned long cmd, GUE
                 reservation.extent_start,
                 reservation.nr_extents,
                 reservation.extent_order,
-                flags,
+                memflags,
                 &preempted);
             break;
         case XENMEM_decrease_reservation:
@@ -333,7 +556,6 @@ long do_memory_op(unsigned long cmd, GUE
                 reservation.extent_start,
                 reservation.nr_extents,
                 reservation.extent_order,
-                flags,
                 &preempted);
             break;
         case XENMEM_populate_physmap:
@@ -343,7 +565,7 @@ long do_memory_op(unsigned long cmd, GUE
                 reservation.extent_start,
                 reservation.nr_extents,
                 reservation.extent_order,
-                flags,
+                memflags,
                 &preempted);
             break;
         }
@@ -358,6 +580,10 @@ long do_memory_op(unsigned long cmd, GUE
                 __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 532979a78071 -r ec2ac5a5f0a3 xen/common/page_alloc.c
--- a/xen/common/page_alloc.c   Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/common/page_alloc.c   Sat Jun 17 12:48:07 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 532979a78071 -r ec2ac5a5f0a3 xen/include/asm-x86/grant_table.h
--- a/xen/include/asm-x86/grant_table.h Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/include/asm-x86/grant_table.h Sat Jun 17 12:48:07 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 532979a78071 -r ec2ac5a5f0a3 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h  Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/include/asm-x86/mm.h  Sat Jun 17 12:48:07 2006 +0100
@@ -387,4 +387,7 @@ long arch_memory_op(int op, GUEST_HANDLE
 long arch_memory_op(int op, GUEST_HANDLE(void) arg);
 long subarch_memory_op(int op, GUEST_HANDLE(void) arg);
 
+int steal_page(
+    struct domain *d, struct page_info *page, unsigned int memflags);
+
 #endif /* __ASM_X86_MM_H__ */
diff -r 532979a78071 -r ec2ac5a5f0a3 xen/include/public/memory.h
--- a/xen/include/public/memory.h       Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/include/public/memory.h       Sat Jun 17 12:48:07 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,9 +48,50 @@ typedef struct xen_memory_reservation {
      * Unprivileged domains can specify only DOMID_SELF.
      */
     domid_t        domid;
-
 } xen_memory_reservation_t;
 DEFINE_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
+typedef 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;
+} xen_memory_exchange_t;
+DEFINE_GUEST_HANDLE(xen_memory_exchange_t);
 
 /*
  * Returns the maximum machine frame number of mapped RAM in this system.
diff -r 532979a78071 -r ec2ac5a5f0a3 xen/include/xen/mm.h
--- a/xen/include/xen/mm.h      Sat Jun 17 12:31:40 2006 +0100
+++ b/xen/include/xen/mm.h      Sat Jun 17 12:48:07 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)
 
 /* Up to 2^20 pages can be allocated at once. */
 #define MAX_ORDER 20

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-3.0-testing] [XEN] New memory_op XENMEM_exchange. Allows atomic, Xen patchbot-3 . 0-testing <=