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

[Xen-devel] Re: [Qemu-devel] [PATCH V6 09/15] xen: Introduce the Xen mapcache



On 21.10.2010, at 19:36, Anthony.Perard@xxxxxxxxxx wrote:

> From: Jun Nakajima <jun.nakajima@xxxxxxxxx>
> 
> On IA32 host or IA32 PAE host, at present, generally, we can't create
> an HVM guest with more than 2G memory, because generally it's almost
> impossible for Qemu to find a large enough and consecutive virtual
> address space to map an HVM guest's whole physical address space.
> The attached patch fixes this issue using dynamic mapping based on
> little blocks of memory.
> 
> Each call to qemu_get_ram_ptr makes a call to qemu_map_cache with the
> lock option, so mapcache will not unmap these ram_ptr.
> 
> Signed-off-by: Jun Nakajima <jun.nakajima@xxxxxxxxx>
> Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
> ---
> Makefile.target     |    3 +
> configure           |    3 +
> exec.c              |   40 ++++++-
> hw/xen.h            |   10 ++
> hw/xen_common.h     |    2 +
> xen-all.c           |   64 +++++++++++
> xen-mapcache-stub.c |   33 ++++++
> xen-mapcache.c      |  301 +++++++++++++++++++++++++++++++++++++++++++++++++++
> xen-mapcache.h      |   14 +++
> xen-stub.c          |    4 +
> 10 files changed, 470 insertions(+), 4 deletions(-)
> create mode 100644 xen-mapcache-stub.c
> create mode 100644 xen-mapcache.c
> create mode 100644 xen-mapcache.h
> 
> diff --git a/Makefile.target b/Makefile.target
> index db84edb..5646582 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -187,8 +187,11 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
> obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
> 
> # xen support
> +CONFIG_NO_XEN_MAPCACHE = $(if $(subst n,,$(CONFIG_XEN_MAPCACHE)),n,y)
> obj-$(CONFIG_XEN) += xen-all.o
> obj-$(CONFIG_NO_XEN) += xen-stub.o
> +obj-$(CONFIG_XEN_MAPCACHE) += xen-mapcache.o
> +obj-$(CONFIG_NO_XEN_MAPCACHE) += xen-mapcache-stub.o
> 
> # xen full virtualized machine
> obj-i386-$(CONFIG_XEN) += xen_machine_fv.o
> diff --git a/configure b/configure
> index f6a7073..d5a8553 100755
> --- a/configure
> +++ b/configure
> @@ -2943,6 +2943,9 @@ case "$target_arch2" in
>   i386|x86_64)
>     if test "$xen" = "yes" -a "$target_softmmu" = "yes" ; then
>       echo "CONFIG_XEN=y" >> $config_target_mak
> +      if test "$cpu" = "i386" -o "$cpu" = "x86_64"; then
> +          echo "CONFIG_XEN_MAPCACHE=y" >> $config_target_mak
> +      fi
>     fi
> esac
> case "$target_arch2" in
> diff --git a/exec.c b/exec.c
> index 631d8c5..d2cded6 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -39,6 +39,7 @@
> #include "hw/qdev.h"
> #include "osdep.h"
> #include "kvm.h"
> +#include "hw/xen.h"
> #include "qemu-timer.h"
> #if defined(CONFIG_USER_ONLY)
> #include <qemu.h>
> @@ -58,6 +59,8 @@
> #include <libutil.h>
> #endif
> #endif
> +#else /* !CONFIG_USER_ONLY */
> +#include "xen-mapcache.h"
> #endif
> 
> //#define DEBUG_TB_INVALIDATE
> @@ -2834,6 +2837,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, 
> const char *name,
>         }
>     }
> 
> +    new_block->offset = find_ram_offset(size);
>     if (host) {
>         new_block->host = host;
>     } else {
> @@ -2855,13 +2859,15 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, 
> const char *name,
>                                    PROT_EXEC|PROT_READ|PROT_WRITE,
>                                    MAP_SHARED | MAP_ANONYMOUS, -1, 0);
> #else
> -            new_block->host = qemu_vmalloc(size);
> +            if (xen_mapcache_enabled()) {
> +                xen_ram_alloc(new_block->offset, size);
> +            } else {
> +                new_block->host = qemu_vmalloc(size);
> +            }
> #endif
>             qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
>         }
>     }
> -
> -    new_block->offset = find_ram_offset(size);
>     new_block->length = size;
> 
>     QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
> @@ -2902,7 +2908,11 @@ void qemu_ram_free(ram_addr_t addr)
> #if defined(TARGET_S390X) && defined(CONFIG_KVM)
>                 munmap(block->host, block->length);
> #else
> -                qemu_vfree(block->host);
> +                if (xen_mapcache_enabled()) {
> +                    qemu_invalidate_entry(block->host);
> +                } else {
> +                    qemu_vfree(block->host);
> +                }
> #endif
>             }
>             qemu_free(block);
> @@ -2928,6 +2938,15 @@ void *qemu_get_ram_ptr(ram_addr_t addr)
>         if (addr - block->offset < block->length) {
>             QLIST_REMOVE(block, next);
>             QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
> +            if (xen_mapcache_enabled()) {
> +                /* We need to check if the requested address is in the RAM
> +                 * because we don't want to map the entire memory in QEMU.
> +                 */
> +                if (block->offset == 0) {
> +                    return qemu_map_cache(addr, 0, 1);
> +                }
> +                block->host = qemu_map_cache(block->offset, block->length, 
> 1);
> +            }
>             return block->host + (addr - block->offset);
>         }
>     }
> @@ -2944,11 +2963,21 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t 
> *ram_addr)
>     uint8_t *host = ptr;
> 
>     QLIST_FOREACH(block, &ram_list.blocks, next) {
> +        /* This case append when the block is not mapped. */
> +        if (block->host == NULL) {
> +            continue;
> +        }
>         if (host - block->host < block->length) {
>             *ram_addr = block->offset + (host - block->host);
>             return 0;
>         }
>     }
> +
> +    if (xen_mapcache_enabled()) {
> +        *ram_addr = qemu_ram_addr_from_mapcache(ptr);
> +        return 0;
> +    }
> +
>     return -1;
> }
> 
> @@ -3733,6 +3762,9 @@ void cpu_physical_memory_unmap(void *buffer, 
> target_phys_addr_t len,
>     if (is_write) {
>         cpu_physical_memory_write(bounce.addr, bounce.buffer, access_len);
>     }
> +    if (xen_enabled()) {
> +        qemu_invalidate_entry(buffer);
> +    }
>     qemu_vfree(bounce.buffer);
>     bounce.buffer = NULL;
>     cpu_notify_map_clients();
> diff --git a/hw/xen.h b/hw/xen.h
> index c5189b1..0261ae6 100644
> --- a/hw/xen.h
> +++ b/hw/xen.h
> @@ -28,10 +28,20 @@ extern int xen_allowed;
> #define xen_enabled() (0)
> #endif
> 
> +#if defined CONFIG_XEN_MAPCACHE
> +#  define xen_mapcache_enabled() (xen_enabled())

static inline int xen_mapcache_enabled(void)
{
#ifdef CONFIG_XEN_MAPCACHE
    return xen_enabled();
#else
    return 0;
#endif
}

> +#else
> +#  define xen_mapcache_enabled() (0)
> +#endif
> +
> int xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num);
> void xen_piix3_set_irq(void *opaque, int irq_num, int level);
> void xen_piix_pci_write_config_client(uint32_t address, uint32_t val, int 
> len);
> 
> int xen_init(int smp_cpus);
> 
> +#if defined(NEED_CPU_H) && !defined(CONFIG_USER_ONLY)
> +void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size);
> +#endif
> +
> #endif /* QEMU_HW_XEN_H */
> diff --git a/hw/xen_common.h b/hw/xen_common.h
> index a24bcb3..2773b45 100644
> --- a/hw/xen_common.h
> +++ b/hw/xen_common.h
> @@ -36,6 +36,8 @@ typedef int qemu_xc_interface;
>     xc_gnttab_map_grant_refs(gnt, count, domids, refs, flags)
> #  define xc_gnttab_munmap(xc, gnt, pages, niov) xc_gnttab_munmap(gnt, pages, 
> niov)
> #  define xc_gnttab_close(xc, dev)               xc_gnttab_close(dev)
> +#  define xc_map_foreign_bulk(xc, domid, opts, pfns, err, size) \
> +    xc_map_foreign_batch(xc, domid, opts, pfns, size)

See my comment on the introduction of these defines.


Alex


_______________________________________________
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®.