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

[Xen-devel] Re: [RFC/PATCH v1] xen-gntdev: Use XENMEM_populate_physmap on unmapped pages in HVM



On Fri, 2011-03-04 at 20:53 +0000, Daniel De Graaf wrote:
> >> Is there some reason the gntdev driver can't just balloon down
> >> (XENMEM_decrease_reservation) to make itself a space to map and then
> >> balloon back up (XENMEM_increase_reservation) after unmap when running
> >> HVM?
> > 
> > I recall having problems with doing this last time, but I think other 
> > changes
> > to make the balloon driver work in HVM may have fixed the issue. I'll try it
> > again; I think this would be the best solution.
> 
> Using the balloon hypercalls does work in my test. Below is a patch that
> uses them directly in gntdev, which is simpler but doesn't handle errors
> in re-ballooning and doesn't take advantage of already-ballooned pages
> from the balloon device. Taking advantage of the balloon device is also
> possible and would be more efficient, but adds another dependency to
> gntdev. Any opinions on which method is preferred? If not, I'll try
> making a patch to implement the balloon-assisted version.

The balloon driver in the 2.6.32 pvops (and all old-style Xen kernels
too) has interfaces which are used by the backend drivers for exactly
this purpose.

It was always a bit of a wart that the backends depended on the balloon
driver in this way. IMHO the core ballooning functionality and kernel
interfaces should be moved into the core kernel under CONFIG_XEN. All
that should remain under CONFIG_XEN_BALLOON is the sysfs and xenbus
integration e.g. the user/admin visible interfaces.

This is somewhat analogous to drivers/xen/{events,grant-table}.c being
core kernel and drivers/xen/{gnt,evt}dev.c being configurable optional
modules.

It's possible that what remains under CONFIG_XEN_BALLOON is such a tiny
amount of code that it's not worth keeping it as a separate option,
although the "depends SYSFS" aspect may make it more worthwhile.

Ian.

> 
> 8<-------------------------------------------------------------------------
> 
> Grant mappings cause the PFN<->MFN mapping to be lost on the pages
> used for the mapping. Instead of leaking memory, explicitly free it
> to the hypervisor and request the memory back after unmapping. This
> removes the need for the bad-page leak workaround.
> 
> Signed-off-by: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
> ---
>  drivers/xen/gntdev.c |   58 +++++++++++++++++++++++++++++++++----------------
>  1 files changed, 39 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
> index d43ff30..104098a 100644
> --- a/drivers/xen/gntdev.c
> +++ b/drivers/xen/gntdev.c
> @@ -41,6 +41,7 @@
>  #include <asm/xen/hypervisor.h>
>  #include <asm/xen/hypercall.h>
>  #include <asm/xen/page.h>
> +#include <xen/interface/memory.h>
>  
>  MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("Derek G. Murray <Derek.Murray@xxxxxxxxxxxx>, "
> @@ -203,27 +204,9 @@ static void gntdev_put_map(struct grant_map *map)
>                       unmap_grant_pages(map, 0, map->count);
>  
>               for (i = 0; i < map->count; i++) {
> -                     uint32_t check, *tmp;
>                       if (!map->pages[i])
>                               continue;
> -                     /* XXX When unmapping in an HVM domain, Xen will
> -                      * sometimes end up mapping the GFN to an invalid MFN.
> -                      * In this case, writes will be discarded and reads will
> -                      * return all 0xFF bytes.  Leak these unusable GFNs
> -                      * until Xen supports fixing their p2m mapping.
> -                      *
> -                      * Confirmed present in Xen 4.1-RC3 with HVM source
> -                      */
> -                     tmp = kmap(map->pages[i]);
> -                     *tmp = 0xdeaddead;
> -                     mb();
> -                     check = *tmp;
> -                     kunmap(map->pages[i]);
> -                     if (check == 0xdeaddead)
> -                             __free_page(map->pages[i]);
> -                     else
> -                             pr_debug("Discard page %d=%ld\n", i,
> -                                     page_to_pfn(map->pages[i]));
> +                     __free_page(map->pages[i]);
>               }
>       }
>       kfree(map->pages);
> @@ -258,11 +241,19 @@ static int map_grant_pages(struct grant_map *map)
>  {
>       int i, err = 0;
>       phys_addr_t addr;
> +     unsigned long frame;
>  
>       if (!use_ptemod) {
> +             struct xen_memory_reservation reservation = {
> +                     .address_bits = 0,
> +                     .extent_order = 0,
> +                     .nr_extents   = 1,
> +                     .domid        = DOMID_SELF
> +             };
>               /* Note: it could already be mapped */
>               if (map->map_ops[0].handle != -1)
>                       return 0;
> +             set_xen_guest_handle(reservation.extent_start, &frame);
>               for (i = 0; i < map->count; i++) {
>                       addr = (phys_addr_t)
>                               pfn_to_kaddr(page_to_pfn(map->pages[i]));
> @@ -271,6 +262,12 @@ static int map_grant_pages(struct grant_map *map)
>                               map->grants[i].domid);
>                       gnttab_set_unmap_op(&map->unmap_ops[i], addr,
>                               map->flags, -1 /* handle */);
> +                     /* TODO batch hypercall, needs buffer */
> +                     frame = page_to_pfn(map->pages[i]);
> +                     err = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
> +                             &reservation);
> +                     if (WARN_ON(err <= 0))
> +                             printk(KERN_INFO "memop returned %d\n", err);
>               }
>       }
>  
> @@ -324,6 +321,29 @@ static int __unmap_grant_pages(struct grant_map *map, 
> int offset, int pages)
>                       map->unmap_ops[offset+i].status);
>               map->unmap_ops[offset+i].handle = -1;
>       }
> +
> +     if (!use_ptemod) {
> +             struct xen_memory_reservation reservation = {
> +                     .address_bits = 0,
> +                     .extent_order = 0,
> +                     .nr_extents   = 1,
> +                     .domid        = DOMID_SELF
> +             };
> +             int rc;
> +             unsigned long frame;
> +             set_xen_guest_handle(reservation.extent_start, &frame);
> +             /* TODO batch hypercall, needs buffer */
> +             for (i = offset; i < pages + offset; i++) {
> +                     frame = page_to_pfn(map->pages[i]);
> +                     rc = HYPERVISOR_memory_op(XENMEM_populate_physmap,
> +                             &reservation);
> +                     if (WARN_ON(rc <= 0)) {
> +                             map->pages[i] = NULL;
> +                             continue;
> +                     }
> +             }
> +     }
> +
>       return err;
>  }
>  



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


 


Rackspace

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