[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] New memory hypercall 'populate_physmap'. Accepts a list of



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 17dc21008351fcbe2b326b267541d23bfba3b388
# Parent  2e82fd7a69212955b75c6adaed4ae2a58ae45399
New memory hypercall 'populate_physmap'. Accepts a list of
pseudophys frame numbers to be populated with memory.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r 2e82fd7a6921 -r 17dc21008351 
linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Fri Jan 27 
11:48:32 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c        Fri Jan 27 
11:49:47 2006
@@ -315,9 +315,9 @@
        pud_t         *pud; 
        pmd_t         *pmd;
        pte_t         *pte;
-       unsigned long  mfn, i, flags;
+       unsigned long  frame, i, flags;
        struct xen_memory_reservation reservation = {
-               .extent_start = &mfn,
+               .extent_start = &frame,
                .nr_extents   = 1,
                .extent_order = 0,
                .domid        = DOMID_SELF
@@ -333,7 +333,7 @@
                pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
                pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
                pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
-               mfn = pte_mfn(*pte);
+               frame = pte_mfn(*pte);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
@@ -345,7 +345,8 @@
        /* 2. Get a new contiguous memory extent. */
        reservation.extent_order = order;
        reservation.address_bits = address_bits;
-       if (HYPERVISOR_memory_op(XENMEM_increase_reservation,
+       frame = __pa(vstart) >> PAGE_SHIFT;
+       if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
                                 &reservation) != 1)
                goto fail;
 
@@ -353,9 +354,8 @@
        for (i = 0; i < (1<<order); i++) {
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE),
-                       pfn_pte_ma(mfn+i, PAGE_KERNEL), 0));
-               xen_machphys_update(mfn+i, (__pa(vstart)>>PAGE_SHIFT)+i);
-               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn+i);
+                       pfn_pte_ma(frame+i, PAGE_KERNEL), 0));
+               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame+i);
        }
 
        flush_tlb_all();
@@ -371,13 +371,13 @@
        reservation.address_bits = 0;
 
        for (i = 0; i < (1<<order); i++) {
+               frame = (__pa(vstart) >> PAGE_SHIFT) + i;
                BUG_ON(HYPERVISOR_memory_op(
-                       XENMEM_increase_reservation, &reservation) != 1);
+                       XENMEM_populate_physmap, &reservation) != 1);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE),
-                       pfn_pte_ma(mfn, PAGE_KERNEL), 0));
-               xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
-               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
+                       pfn_pte_ma(frame, PAGE_KERNEL), 0));
+               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
        }
 
        flush_tlb_all();
@@ -393,9 +393,9 @@
        pud_t         *pud; 
        pmd_t         *pmd;
        pte_t         *pte;
-       unsigned long  mfn, i, flags;
+       unsigned long  frame, i, flags;
        struct xen_memory_reservation reservation = {
-               .extent_start = &mfn,
+               .extent_start = &frame,
                .nr_extents   = 1,
                .extent_order = 0,
                .domid        = DOMID_SELF
@@ -413,7 +413,7 @@
                pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
                pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
                pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
-               mfn = pte_mfn(*pte);
+               frame = pte_mfn(*pte);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
                set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
@@ -424,13 +424,13 @@
 
        /* 2. Map new pages in place of old pages. */
        for (i = 0; i < (1<<order); i++) {
+               frame = (__pa(vstart) >> PAGE_SHIFT) + i;
                BUG_ON(HYPERVISOR_memory_op(
-                       XENMEM_increase_reservation, &reservation) != 1);
+                       XENMEM_populate_physmap, &reservation) != 1);
                BUG_ON(HYPERVISOR_update_va_mapping(
                        vstart + (i*PAGE_SIZE),
-                       pfn_pte_ma(mfn, PAGE_KERNEL), 0));
-               xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
-               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
+                       pfn_pte_ma(frame, PAGE_KERNEL), 0));
+               set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
        }
 
        flush_tlb_all();
diff -r 2e82fd7a6921 -r 17dc21008351 
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Fri Jan 27 
11:48:32 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c        Fri Jan 27 
11:49:47 2006
@@ -139,6 +139,21 @@
        return page;
 }
 
+static struct page *balloon_first_page(void)
+{
+       if (list_empty(&ballooned_pages))
+               return NULL;
+       return LIST_TO_PAGE(ballooned_pages.next);
+}
+
+static struct page *balloon_next_page(struct page *page)
+{
+       struct list_head *next = PAGE_TO_LIST(page)->next;
+       if (next == &ballooned_pages)
+               return NULL;
+       return LIST_TO_PAGE(next);
+}
+
 static void balloon_alarm(unsigned long unused)
 {
        schedule_work(&balloon_worker);
@@ -154,7 +169,7 @@
 
 static int increase_reservation(unsigned long nr_pages)
 {
-       unsigned long *mfn_list, pfn, i, flags;
+       unsigned long *frame_list, pfn, i, flags;
        struct page   *page;
        long           rc;
        struct xen_memory_reservation reservation = {
@@ -166,20 +181,27 @@
        if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
                nr_pages = PAGE_SIZE / sizeof(unsigned long);
 
-       mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
-       if (mfn_list == NULL)
+       frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (frame_list == NULL)
                return -ENOMEM;
 
        balloon_lock(flags);
 
-       reservation.extent_start = mfn_list;
+       page = balloon_first_page();
+       for (i = 0; i < nr_pages; i++) {
+               BUG_ON(page == NULL);
+               frame_list[i] = page_to_pfn(page);;
+               page = balloon_next_page(page);
+       }
+
+       reservation.extent_start = frame_list;
        reservation.nr_extents   = nr_pages;
        rc = HYPERVISOR_memory_op(
-               XENMEM_increase_reservation, &reservation);
+               XENMEM_populate_physmap, &reservation);
        if (rc < nr_pages) {
                int ret;
                /* We hit the Xen hard limit: reprobe. */
-               reservation.extent_start = mfn_list;
+               reservation.extent_start = frame_list;
                reservation.nr_extents   = rc;
                ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
                                &reservation);
@@ -196,15 +218,15 @@
                BUG_ON(phys_to_machine_mapping_valid(pfn));
 
                /* Update P->M and M->P tables. */
-               set_phys_to_machine(pfn, mfn_list[i]);
-               xen_machphys_update(mfn_list[i], pfn);
+               set_phys_to_machine(pfn, frame_list[i]);
+               xen_machphys_update(frame_list[i], pfn);
             
                /* Link back into the page tables if not highmem. */
                if (pfn < max_low_pfn) {
                        int ret;
                        ret = HYPERVISOR_update_va_mapping(
                                (unsigned long)__va(pfn << PAGE_SHIFT),
-                               pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
+                               pfn_pte_ma(frame_list[i], PAGE_KERNEL),
                                0);
                        BUG_ON(ret);
                }
@@ -221,14 +243,14 @@
  out:
        balloon_unlock(flags);
 
-       free_page((unsigned long)mfn_list);
+       free_page((unsigned long)frame_list);
 
        return 0;
 }
 
 static int decrease_reservation(unsigned long nr_pages)
 {
-       unsigned long *mfn_list, pfn, i, flags;
+       unsigned long *frame_list, pfn, i, flags;
        struct page   *page;
        void          *v;
        int            need_sleep = 0;
@@ -242,8 +264,8 @@
        if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
                nr_pages = PAGE_SIZE / sizeof(unsigned long);
 
-       mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
-       if (mfn_list == NULL)
+       frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+       if (frame_list == NULL)
                return -ENOMEM;
 
        for (i = 0; i < nr_pages; i++) {
@@ -254,7 +276,7 @@
                }
 
                pfn = page_to_pfn(page);
-               mfn_list[i] = pfn_to_mfn(pfn);
+               frame_list[i] = pfn_to_mfn(pfn);
 
                if (!PageHighMem(page)) {
                        v = phys_to_virt(pfn << PAGE_SHIFT);
@@ -280,12 +302,12 @@
 
        /* No more mappings: invalidate P2M and add to balloon. */
        for (i = 0; i < nr_pages; i++) {
-               pfn = mfn_to_pfn(mfn_list[i]);
+               pfn = mfn_to_pfn(frame_list[i]);
                set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
                balloon_append(pfn_to_page(pfn));
        }
 
-       reservation.extent_start = mfn_list;
+       reservation.extent_start = frame_list;
        reservation.nr_extents   = nr_pages;
        ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
        BUG_ON(ret != nr_pages);
@@ -295,7 +317,7 @@
 
        balloon_unlock(flags);
 
-       free_page((unsigned long)mfn_list);
+       free_page((unsigned long)frame_list);
 
        return need_sleep;
 }
diff -r 2e82fd7a6921 -r 17dc21008351 xen/common/memory.c
--- a/xen/common/memory.c       Fri Jan 27 11:48:32 2006
+++ b/xen/common/memory.c       Fri Jan 27 11:49:47 2006
@@ -30,7 +30,7 @@
     int           *preempted)
 {
     struct pfn_info *page;
-    unsigned int     i;
+    unsigned long    i;
 
     if ( (extent_list != NULL) &&
          !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
@@ -52,7 +52,7 @@
             d, extent_order, flags)) == NULL) )
         {
             DPRINTK("Could not allocate order=%d extent: "
-                    "id=%d flags=%x (%d of %d)\n",
+                    "id=%d flags=%x (%ld of %d)\n",
                     extent_order, d->domain_id, flags, i, nr_extents);
             return i;
         }
@@ -60,6 +60,58 @@
         /* Inform the domain of the new page's machine address. */ 
         if ( (extent_list != NULL) &&
              (__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
+            return i;
+    }
+
+    return nr_extents;
+}
+    
+static long
+populate_physmap(
+    struct domain *d, 
+    unsigned long *extent_list, 
+    unsigned int   nr_extents,
+    unsigned int   extent_order,
+    unsigned int   flags,
+    int           *preempted)
+{
+    struct pfn_info *page;
+    unsigned long    i, j, pfn, mfn;
+
+    if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
+        return 0;
+
+    if ( (extent_order != 0) &&
+         !multipage_allocation_permitted(current->domain) )
+        return 0;
+
+    for ( i = 0; i < nr_extents; i++ )
+    {
+        if ( hypercall_preempt_check() )
+        {
+            *preempted = 1;
+            return i;
+        }
+
+        if ( unlikely((page = alloc_domheap_pages(
+            d, extent_order, flags)) == 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);
+            return i;
+        }
+
+        mfn = page_to_pfn(page);
+
+        if ( unlikely(__get_user(pfn, &extent_list[i]) != 0) )
+            return i;
+
+        for ( j = 0; j < (1 << extent_order); j++ )
+            set_pfn_from_mfn(mfn + j, pfn + j);
+
+        /* Inform the domain of the new page's machine address. */ 
+        if ( __put_user(mfn, &extent_list[i]) != 0 )
             return i;
     }
 
@@ -76,7 +128,7 @@
     int           *preempted)
 {
     struct pfn_info *page;
-    unsigned long    i, j, mpfn;
+    unsigned long    i, j, mfn;
 
     if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
         return 0;
@@ -89,19 +141,19 @@
             return i;
         }
 
-        if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
+        if ( unlikely(__get_user(mfn, &extent_list[i]) != 0) )
             return i;
 
         for ( j = 0; j < (1 << extent_order); j++ )
         {
-            if ( unlikely((mpfn + j) >= max_page) )
+            if ( unlikely((mfn + j) >= max_page) )
             {
                 DPRINTK("Domain %u page number out of range (%lx >= %lx)\n", 
-                        d->domain_id, mpfn + j, max_page);
+                        d->domain_id, mfn + j, max_page);
                 return i;
             }
             
-            page = pfn_to_page(mpfn + j);
+            page = pfn_to_page(mfn + j);
             if ( unlikely(!get_page(page, d)) )
             {
                 DPRINTK("Bad page free for domain %u\n", d->domain_id);
@@ -143,6 +195,7 @@
     {
     case XENMEM_increase_reservation:
     case XENMEM_decrease_reservation:
+    case XENMEM_populate_physmap:
         if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
             return -EFAULT;
 
@@ -170,14 +223,37 @@
         else if ( (d = find_domain_by_id(reservation.domid)) == NULL )
             return -ESRCH;
 
-        rc = ((op == XENMEM_increase_reservation) ?
-              increase_reservation : decrease_reservation)(
-                  d,
-                  reservation.extent_start,
-                  reservation.nr_extents,
-                  reservation.extent_order,
-                  flags,
-                  &preempted);
+        switch ( op )
+        {
+        case XENMEM_increase_reservation:
+            rc = increase_reservation(
+                d,
+                reservation.extent_start,
+                reservation.nr_extents,
+                reservation.extent_order,
+                flags,
+                &preempted);
+            break;
+        case XENMEM_decrease_reservation:
+            rc = decrease_reservation(
+                d,
+                reservation.extent_start,
+                reservation.nr_extents,
+                reservation.extent_order,
+                flags,
+                &preempted);
+            break;
+        case XENMEM_populate_physmap:
+        default:
+            rc = populate_physmap(
+                d,
+                reservation.extent_start,
+                reservation.nr_extents,
+                reservation.extent_order,
+                flags,
+                &preempted);
+            break;
+        }
 
         if ( unlikely(reservation.domid != DOMID_SELF) )
             put_domain(d);
diff -r 2e82fd7a6921 -r 17dc21008351 xen/include/public/memory.h
--- a/xen/include/public/memory.h       Fri Jan 27 11:48:32 2006
+++ b/xen/include/public/memory.h       Fri Jan 27 11:49:47 2006
@@ -16,11 +16,18 @@
  */
 #define XENMEM_increase_reservation 0
 #define XENMEM_decrease_reservation 1
+#define XENMEM_populate_physmap     6
 typedef struct xen_memory_reservation {
 
     /*
-     * MFN bases of extents to free (XENMEM_decrease_reservation).
-     * MFN bases of extents that were allocated (XENMEM_increase_reservation).
+     * XENMEM_increase_reservation:
+     *   OUT: MFN bases of extents that were allocated
+     * XENMEM_decrease_reservation:
+     *   IN:  MFN bases of extents to free
+     * XENMEM_populate_physmap:
+     *   IN:  PFN bases of extents to populate with memory
+     *   OUT: MFN bases of extents that were allocated
+     *   (NB. This command also updates the mach_to_phys translation table)
      */
     unsigned long *extent_start;
 
@@ -29,11 +36,10 @@
     unsigned int   extent_order;
 
     /*
-     * XENMEM_increase_reservation: maximum # bits addressable by the user
-     * of the allocated region (e.g., I/O devices often have a 32-bit
-     * limitation even in 64-bit systems). If zero then the user has no
-     * addressing restriction.
-     * XENMEM_decrease_reservation: unused.
+     * Mmaximum # bits addressable by the user of the allocated region (e.g., 
+     * I/O devices often have a 32-bit limitation even in 64-bit systems). If 
+     * zero then the user has no addressing restriction.
+     * This field is not used by XENMEM_decrease_reservation.
      */
     unsigned int   address_bits;
 

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.