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

[Xen-devel] Re: [Qemu-devel] [PATCH RFC V3 07/12] xen: Introduce the Xen mapcache


  • To: anthony.perard@xxxxxxxxxx
  • From: Blue Swirl <blauwirbel@xxxxxxxxx>
  • Date: Fri, 17 Sep 2010 19:07:33 +0000
  • Cc: xen-devel@xxxxxxxxxxxxxxxxxxx, qemu-devel@xxxxxxxxxx, Stefano.Stabellini@xxxxxxxxxxxxx
  • Delivery-date: Fri, 17 Sep 2010 12:08:39 -0700
  • Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; b=YNcsvFLuUvBjPo6FF9rHYyi6kK2NWE1wQsfTKLCQETyQEAHKl8hWs7KlI6LLeeFvwM 0EI/cOeAquj7keXbbTn0/ulmhLo+WwyUIMmhds6NOehBOEijYQIcvLJReyW2xIPM6Tg2 oonWJ/SOwjp3uKpJZ/335F71cKOYYt0Fub6c0=
  • List-id: Xen developer discussion <xen-devel.lists.xensource.com>

On Fri, Sep 17, 2010 at 11:15 AM,  <anthony.perard@xxxxxxxxxx> wrote:
> From: Anthony PERARD <anthony.perard@xxxxxxxxxx>
>
> The mapcache maps chucks of guest memory on demand, unmaps them when
> they are not needed anymore.
>
> 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: Anthony PERARD <anthony.perard@xxxxxxxxxx>
> ---
> ÂMakefile.target | Â Â2 +-
> Âexec.c     Â|  36 ++++++-
> Âhw/xen.h    Â|  Â4 +
> Âxen-all.c    |  63 ++++++++++++
> Âxen-stub.c   Â|  Â4 +
> Âxen_mapcache.c Â| Â302 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++
> Âxen_mapcache.h Â| Â 26 +++++
> Â7 files changed, 432 insertions(+), 5 deletions(-)
> Âcreate mode 100644 xen_mapcache.c
> Âcreate mode 100644 xen_mapcache.h
>
> diff --git a/Makefile.target b/Makefile.target
> index 6b390e6..ea14393 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -183,7 +183,7 @@ QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
>
> Â# xen backend driver support
> Âobj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
> -obj-$(CONFIG_XEN) += xen-all.o
> +obj-$(CONFIG_XEN) += xen-all.o xen_mapcache.o
> Âobj-$(CONFIG_NO_XEN) += xen-stub.o
>
> Â# xen full virtualized machine
> diff --git a/exec.c b/exec.c
> index 380dab5..f5888eb 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -60,6 +60,9 @@
> Â#endif
> Â#endif
>
> +#include "hw/xen.h"
> +#include "xen_mapcache.h"
> +
> Â//#define DEBUG_TB_INVALIDATE
> Â//#define DEBUG_FLUSH
> Â//#define DEBUG_TLB
> @@ -2833,6 +2836,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 {
> @@ -2856,15 +2860,17 @@ 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_enabled()) {
> + Â Â Â Â Â Â Â Âxen_ram_alloc(new_block->offset, size);
> + Â Â Â Â Â Â} else {
> + Â Â Â Â Â Â Â Ânew_block->host = qemu_vmalloc(size);
> + Â Â Â Â Â Â}
> Â#endif
> Â#ifdef MADV_MERGEABLE
> Â Â Â Â Â Â madvise(new_block->host, size, MADV_MERGEABLE);
> Â#endif
> Â Â Â Â }
> Â Â }
> -
> - Â Ânew_block->offset = find_ram_offset(size);
> Â Â new_block->length = size;
>
> Â Â QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
> @@ -2905,7 +2911,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_enabled()) {
> + Â Â Â Â Â Â Â Â Â Âqemu_invalidate_entry(block->host);
> + Â Â Â Â Â Â Â Â} else {
> + Â Â Â Â Â Â Â Â Â Âqemu_vfree(block->host);
> + Â Â Â Â Â Â Â Â}
> Â#endif
> Â Â Â Â Â Â }
> Â Â Â Â Â Â qemu_free(block);
> @@ -2931,6 +2941,14 @@ 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_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)

braces

> + Â Â Â Â Â Â Â Â Â Âreturn qemu_map_cache(addr, 0, 1);
> + Â Â Â Â Â Â Â Âblock->host = qemu_map_cache(block->offset, block->length, 
> 1);
> + Â Â Â Â Â Â}
> Â Â Â Â Â Â return block->host + (addr - block->offset);
> Â Â Â Â }
> Â Â }
> @@ -2949,11 +2967,18 @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
> Â Â uint8_t *host = ptr;
>
> Â Â QLIST_FOREACH(block, &ram_list.blocks, next) {
> + Â Â Â Â/* This case append when the block is not mapped. */
> + Â Â Â Âif (block->host == NULL)

braces

> + Â Â Â Â Â Âcontinue;
> Â Â Â Â if (host - block->host < block->length) {
> Â Â Â Â Â Â return block->offset + (host - block->host);
> Â Â Â Â }
> Â Â }
>
> + Â Âif (xen_enabled()) {
> + Â Â Â Âreturn qemu_ram_addr_from_mapcache(ptr);
> + Â Â}
> +
> Â Â fprintf(stderr, "Bad ram pointer %p\n", ptr);
> Â Â abort();
>
> @@ -3728,6 +3753,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..2b62ff5 100644
> --- a/hw/xen.h
> +++ b/hw/xen.h
> @@ -34,4 +34,8 @@ void xen_piix_pci_write_config_client(uint32_t address, 
> uint32_t val, int len);
>
> Âint xen_init(int smp_cpus);
>
> +#ifdef NEED_CPU_H
> +void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size);
> +#endif
> +
> Â#endif /* QEMU_HW_XEN_H */
> diff --git a/xen-all.c b/xen-all.c
> index 765f87a..4e0b061 100644
> --- a/xen-all.c
> +++ b/xen-all.c
> @@ -12,6 +12,8 @@
> Â#include "hw/xen_common.h"
> Â#include "hw/xen_backend.h"
>
> +#include "xen_mapcache.h"
> +
> Â/* Xen specific function for piix pci */
>
> Âint xen_pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
> @@ -52,6 +54,63 @@ qemu_irq *i8259_xen_init(void)
> Â Â return qemu_allocate_irqs(i8259_set_irq, NULL, 16);
> Â}
>
> +
> +/* Memory Ops */
> +
> +static void xen_ram_init(ram_addr_t ram_size)
> +{
> + Â ÂRAMBlock *new_block;
> + Â Âram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
> +
> + Â Ânew_block = qemu_mallocz(sizeof (*new_block));
> + Â Âpstrcpy(new_block->idstr, sizeof (new_block->idstr), "xen.ram");
> + Â Ânew_block->host = NULL;
> + Â Ânew_block->offset = 0;
> + Â Ânew_block->length = ram_size;
> +
> + Â ÂQLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
> +
> + Â Âram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â new_block->length >> 
> TARGET_PAGE_BITS);
> + Â Âmemset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS),
> + Â Â Â Â Â 0xff, new_block->length >> TARGET_PAGE_BITS);
> +
> + Â Âif (ram_size >= 0xe0000000 ) {
> + Â Â Â Âabove_4g_mem_size = ram_size - 0xe0000000;
> + Â Â Â Âbelow_4g_mem_size = 0xe0000000;
> + Â Â} else {
> + Â Â Â Âbelow_4g_mem_size = ram_size;
> + Â Â}
> +
> + Â Âcpu_register_physical_memory(0, below_4g_mem_size, new_block->offset);
> +#if TARGET_PHYS_ADDR_BITS > 32
> + Â Âif (above_4g_mem_size > 0) {
> + Â Â Â Âcpu_register_physical_memory(0x100000000ULL, above_4g_mem_size,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â new_block->offset + below_4g_mem_size);
> + Â Â}
> +#endif
> +}
> +
> +void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
> +{
> + Â Âunsigned long nr_pfn;
> + Â Âxen_pfn_t *pfn_list;
> + Â Âint i;
> +
> + Â Ânr_pfn = size >> TARGET_PAGE_BITS;
> + Â Âpfn_list = qemu_malloc(sizeof (*pfn_list) * nr_pfn);
> +
> + Â Âfor (i = 0; i < nr_pfn; i++)

braces

> + Â Â Â Âpfn_list[i] = (ram_addr >> TARGET_PAGE_BITS) + i;
> +
> + Â Âif (xc_domain_memory_populate_physmap(xen_xc, xen_domid, nr_pfn, 0, 0, 
> pfn_list)) {
> + Â Â Â Âhw_error("xen: failed to populate ram at %lx", ram_addr);
> + Â Â}
> +
> + Â Âqemu_free(pfn_list);
> +}
> +
> +
> Â/* Initialise Xen */
>
> Âint xen_init(int smp_cpus)
> @@ -62,5 +121,9 @@ int xen_init(int smp_cpus)
> Â Â Â Â return -1;
> Â Â }
>
> + Â Â/* Init RAM management */
> + Â Âqemu_map_cache_init();
> + Â Âxen_ram_init(ram_size);
> +
> Â Â return 0;
> Â}
> diff --git a/xen-stub.c b/xen-stub.c
> index 07e64bc..c9f477d 100644
> --- a/xen-stub.c
> +++ b/xen-stub.c
> @@ -24,6 +24,10 @@ void xen_piix_pci_write_config_client(uint32_t address, 
> uint32_t val, int len)
> Â{
> Â}
>
> +void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size)
> +{
> +}
> +
> Âint xen_init(int smp_cpus)
> Â{
> Â Â return -ENOSYS;
> diff --git a/xen_mapcache.c b/xen_mapcache.c
> new file mode 100644
> index 0000000..8e3bf6c
> --- /dev/null
> +++ b/xen_mapcache.c
> @@ -0,0 +1,302 @@
> +#include "config.h"
> +
> +#include "hw/xen_backend.h"
> +#include "blockdev.h"
> +
> +#include <xen/hvm/params.h>
> +#include <sys/mman.h>
> +
> +#include "xen_mapcache.h"
> +
> +
> +//#define MAPCACHE_DEBUG
> +
> +#ifdef MAPCACHE_DEBUG
> +#define DPRINTF(fmt, ...) do { \
> + Â Âfprintf(stderr, "xen_mapcache: " fmt, ## __VA_ARGS__); \
> +} while (0)
> +#else
> +#define DPRINTF(fmt, ...) do { } while (0)
> +#endif
> +
> +#if defined(MAPCACHE)
> +
> +#define BITS_PER_LONG (sizeof(long)*8)

Please add spaces around '*', also the below #defines need more spaces.

> +#define BITS_TO_LONGS(bits) \
> + Â Â(((bits)+BITS_PER_LONG-1)/BITS_PER_LONG)
> +#define DECLARE_BITMAP(name,bits) \
> + Â Âunsigned long name[BITS_TO_LONGS(bits)]
> +#define test_bit(bit,map) \
> + Â Â(!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG))))
> +
> +typedef struct MapCacheEntry {
> + Â Âunsigned long paddr_index;
> + Â Âuint8_t *vaddr_base;
> + Â ÂDECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>XC_PAGE_SHIFT);
> + Â Âuint8_t lock;
> + Â Âstruct MapCacheEntry *next;
> +} MapCacheEntry;
> +
> +typedef struct MapCacheRev {
> + Â Âuint8_t *vaddr_req;
> + Â Âunsigned long paddr_index;
> + Â ÂQTAILQ_ENTRY(MapCacheRev) next;
> +} MapCacheRev;
> +
> +typedef struct MapCache {
> + Â ÂMapCacheEntry *entry;
> + Â Âunsigned long nr_buckets;
> + Â ÂQTAILQ_HEAD(map_cache_head, MapCacheRev) locked_entries;
> +
> + Â Â/* For most cases (>99.9%), the page address is the same. */
> + Â Âunsigned long last_address_index;
> +  Âuint8_t   Â*last_address_vaddr;
> +} MapCache;
> +
> +static MapCache *mapcache;
> +
> +
> +int qemu_map_cache_init(void)
> +{
> + Â Âunsigned long size;
> +
> + Â Âmapcache = qemu_mallocz(sizeof (MapCache));
> +
> + Â ÂQTAILQ_INIT(&mapcache->locked_entries);
> + Â Âmapcache->last_address_index = ~0UL;
> +
> + Â Âmapcache->nr_buckets = (((MAX_MCACHE_SIZE >> XC_PAGE_SHIFT) +
> + Â Â Â Â Â Â Â Â Â (1UL << (MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT)) - 1) >>
> + Â Â Â Â Â Â Â Â Â(MCACHE_BUCKET_SHIFT - XC_PAGE_SHIFT));
> +
> + Â Â/*
> + Â Â * Use mmap() directly: lets us allocate a big hash table with no 
> up-front
> + Â Â * cost in storage space. The OS will allocate memory only for the 
> buckets
> + Â Â * that we actually use. All others will contain all zeroes.
> + Â Â */
> + Â Âsize = mapcache->nr_buckets * sizeof(MapCacheEntry);
> + Â Âsize = (size + XC_PAGE_SIZE - 1) & ~(XC_PAGE_SIZE - 1);
> + Â ÂDPRINTF("qemu_map_cache_init, nr_buckets = %lx size %lu\n", 
> mapcache->nr_buckets, size);
> + Â Âmapcache->entry = mmap(NULL, size, PROT_READ|PROT_WRITE,
> + Â Â Â Â Â Â Â Â Â Â Â Â ÂMAP_SHARED|MAP_ANON, -1, 0);
> + Â Âif (mapcache->entry == MAP_FAILED) {
> + Â Â Â Âerrno = ENOMEM;

Is this needed, can't we just use whatever was in errno?

> + Â Â Â Âreturn -1;
> + Â Â}
> +
> + Â Âreturn 0;
> +}
> +
> +static void qemu_remap_bucket(MapCacheEntry *entry,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âtarget_phys_addr_t size,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Âunsigned long address_index)
> +{
> + Â Âuint8_t *vaddr_base;
> + Â Âxen_pfn_t *pfns;
> + Â Âint *err;
> + Â Âunsigned int i, j;

There are a lot of size >> XC_PAGE_SHIFT uses here. I think it would
be clearer to add size >>= XC_PAGE_SHIFT or a new variable.

> +
> + Â Âpfns = qemu_mallocz((size >> XC_PAGE_SHIFT) * sizeof (xen_pfn_t));
> + Â Âerr = qemu_mallocz((size >> XC_PAGE_SHIFT) * sizeof (int));
> +
> + Â Âif (entry->vaddr_base != NULL) {
> + Â Â Â Âerrno = munmap(entry->vaddr_base, size);
> + Â Â Â Âif (errno) {
> + Â Â Â Â Â Âfprintf(stderr, "unmap fails %d\n", errno);

munmap() returns -1 on error, so please don't clobber errno and use perror().

> + Â Â Â Â Â Âexit(-1);
> + Â Â Â Â}
> + Â Â}
> +
> + Â Âfor (i = 0; i < size >> XC_PAGE_SHIFT; i++) {
> + Â Â Â Âpfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-XC_PAGE_SHIFT)) + i;
> + Â Â}
> +
> + Â Âvaddr_base = xc_map_foreign_bulk(xen_xc, xen_domid, PROT_READ|PROT_WRITE,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pfns, err,
> + Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â size >> XC_PAGE_SHIFT);
> + Â Âif (vaddr_base == NULL) {
> + Â Â Â Âfprintf(stderr, "xc_map_foreign_bulk error %d\n", errno);

perror()?

> + Â Â Â Âexit(-1);
> + Â Â}
> +
> + Â Âentry->vaddr_base Â= vaddr_base;
> + Â Âentry->paddr_index = address_index;
> +
> + Â Âfor (i = 0; i < size >> XC_PAGE_SHIFT; i += BITS_PER_LONG) {
> + Â Â Â Âunsigned long word = 0;
> + Â Â Â Âj = ((i + BITS_PER_LONG) > (size >> XC_PAGE_SHIFT)) ?
> + Â Â Â Â Â Â(size >> XC_PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG;

Maybe this would be clearer with 'if'.

> + Â Â Â Âwhile (j > 0) {
> + Â Â Â Â Â Âword = (word << 1) | !err[i + --j];

You are mixing bitwise OR with logical NOT, is this correct?

> + Â Â Â Â}
> + Â Â Â Âentry->valid_mapping[i / BITS_PER_LONG] = word;
> + Â Â}
> +
> + Â Âqemu_free(pfns);
> + Â Âqemu_free(err);
> +}
> +
> +uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t 
> size, uint8_t lock)
> +{
> + Â ÂMapCacheEntry *entry, *pentry = NULL;
> + Â Âunsigned long address_index Â= phys_addr >> MCACHE_BUCKET_SHIFT;
> + Â Âunsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1);

unsigned long will not be long enough on 32 bit host (or 32 bit user
space) for a 64 bit target. I can't remember if this was a supported
case for Xen anyway.

How about address_offset >>= XC_PAGE_SHIFT?

> +
> + Â Âif (address_index == mapcache->last_address_index && !lock)

braces

> + Â Â Â Âreturn mapcache->last_address_vaddr + address_offset;
> +
> + Â Âentry = &mapcache->entry[address_index % mapcache->nr_buckets];
> +
> + Â Âwhile (entry && entry->lock && entry->paddr_index != address_index && 
> entry->vaddr_base) {
> + Â Â Â Âpentry = entry;
> + Â Â Â Âentry = entry->next;
> + Â Â}
> + Â Âif (!entry) {
> + Â Â Â Âentry = qemu_mallocz(sizeof(MapCacheEntry));
> + Â Â Â Âpentry->next = entry;
> + Â Â Â Âqemu_remap_bucket(entry, size ? : MCACHE_BUCKET_SIZE, address_index);
> + Â Â} else if (!entry->lock) {
> + Â Â Â Âif (!entry->vaddr_base || entry->paddr_index != address_index || 
> !test_bit(address_offset>>XC_PAGE_SHIFT, entry->valid_mapping))

I suspect this line is too long. Please also add braces.

> + Â Â Â Â Â Âqemu_remap_bucket(entry, size ? : MCACHE_BUCKET_SIZE, 
> address_index);
> + Â Â}
> +
> + Â Âif (!test_bit(address_offset>>XC_PAGE_SHIFT, entry->valid_mapping)) {
> + Â Â Â Âmapcache->last_address_index = ~0UL;
> + Â Â Â Âreturn NULL;
> + Â Â}
> +
> + Â Âmapcache->last_address_index = address_index;
> + Â Âmapcache->last_address_vaddr = entry->vaddr_base;
> + Â Âif (lock) {
> + Â Â Â ÂMapCacheRev *reventry = qemu_mallocz(sizeof(MapCacheRev));
> + Â Â Â Âentry->lock++;
> + Â Â Â Âreventry->vaddr_req = mapcache->last_address_vaddr + address_offset;
> + Â Â Â Âreventry->paddr_index = mapcache->last_address_index;
> + Â Â Â ÂQTAILQ_INSERT_TAIL(&mapcache->locked_entries, reventry, next);
> + Â Â}
> +
> + Â Âreturn mapcache->last_address_vaddr + address_offset;
> +}
> +
> +ram_addr_t qemu_ram_addr_from_mapcache(void *ptr)
> +{
> + Â ÂMapCacheRev *reventry;
> + Â Âunsigned long paddr_index;
> + Â Âint found = 0;
> +
> + Â ÂQTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> + Â Â Â Âif (reventry->vaddr_req == ptr) {
> + Â Â Â Â Â Âpaddr_index = reventry->paddr_index;
> + Â Â Â Â Â Âfound = 1;
> + Â Â Â Â Â Âbreak;
> + Â Â Â Â}
> + Â Â}
> + Â Âif (!found) {
> + Â Â Â Âfprintf(stderr, "qemu_ram_addr_from_mapcache, could not find %p\n", 
> ptr);
> + Â Â Â ÂQTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> + Â Â Â Â Â ÂDPRINTF(" Â %lx -> %p is present\n", reventry->paddr_index, 
> reventry->vaddr_req);
> + Â Â Â Â}
> + Â Â Â Âabort();
> + Â Â Â Âreturn 0;
> + Â Â}
> +
> + Â Âreturn paddr_index << MCACHE_BUCKET_SHIFT;
> +}
> +
> +void qemu_invalidate_entry(uint8_t *buffer)
> +{
> + Â ÂMapCacheEntry *entry = NULL, *pentry = NULL;
> + Â ÂMapCacheRev *reventry;
> + Â Âunsigned long paddr_index;
> + Â Âint found = 0;
> +
> + Â Âif (mapcache->last_address_vaddr == buffer)
> + Â Â Â Âmapcache->last_address_index = Â~0UL;
> +
> + Â ÂQTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> + Â Â Â Âif (reventry->vaddr_req == buffer) {
> + Â Â Â Â Â Âpaddr_index = reventry->paddr_index;
> + Â Â Â Â Â Âfound = 1;
> + Â Â Â Â Â Âbreak;
> + Â Â Â Â}
> + Â Â}
> + Â Âif (!found) {
> + Â Â Â ÂDPRINTF("qemu_invalidate_entry, could not find %p\n", buffer);
> + Â Â Â ÂQTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> + Â Â Â Â Â ÂDPRINTF(" Â %lx -> %p is present\n", reventry->paddr_index, 
> reventry->vaddr_req);
> + Â Â Â Â}
> + Â Â Â Âreturn;
> + Â Â}
> + Â ÂQTAILQ_REMOVE(&mapcache->locked_entries, reventry, next);
> + Â Âqemu_free(reventry);
> +
> + Â Âentry = &mapcache->entry[paddr_index % mapcache->nr_buckets];
> + Â Âwhile (entry && entry->paddr_index != paddr_index) {
> + Â Â Â Âpentry = entry;
> + Â Â Â Âentry = entry->next;
> + Â Â}
> + Â Âif (!entry) {
> + Â Â Â ÂDPRINTF("Trying to unmap address %p that is not in the mapcache!\n", 
> buffer);
> + Â Â Â Âreturn;
> + Â Â}
> + Â Âentry->lock--;
> + Â Âif (entry->lock > 0 || pentry == NULL)
> + Â Â Â Âreturn;
> +
> + Â Âpentry->next = entry->next;
> + Â Âerrno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
> + Â Âif (errno) {
> + Â Â Â Âfprintf(stderr, "unmap fails %d\n", errno);

Please see my previous munmap comments.

> + Â Â Â Âexit(-1);
> + Â Â}
> + Â Âqemu_free(entry);
> +}
> +
> +void qemu_invalidate_map_cache(void)
> +{
> + Â Âunsigned long i;
> + Â ÂMapCacheRev *reventry;
> +
> + Â Âqemu_aio_flush();
> +
> + Â ÂQTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) {
> + Â Â Â ÂDPRINTF("There should be no locked mappings at this time, but %lx -> 
> %p is present\n", reventry->paddr_index, reventry->vaddr_req);

Probably too long line.

> + Â Â}
> +
> + Â Âmapcache_lock();
> +
> + Â Âfor (i = 0; i < mapcache->nr_buckets; i++) {
> + Â Â Â ÂMapCacheEntry *entry = &mapcache->entry[i];
> +
> + Â Â Â Âif (entry->vaddr_base == NULL)
> + Â Â Â Â Â Âcontinue;
> +
> + Â Â Â Âerrno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE);
> + Â Â Â Âif (errno) {
> + Â Â Â Â Â Âfprintf(stderr, "unmap fails %d\n", errno);
> + Â Â Â Â Â Âexit(-1);
> + Â Â Â Â}
> +
> + Â Â Â Âentry->paddr_index = 0;
> + Â Â Â Âentry->vaddr_base Â= NULL;
> + Â Â}
> +
> + Â Âmapcache->last_address_index = Â~0UL;
> + Â Âmapcache->last_address_vaddr = NULL;
> +
> + Â Âmapcache_unlock();
> +}
> +#else
> +uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, uint8_t lock)
> +{
> + Â Âreturn qemu_get_ram_ptr(phys_addr);
> +}
> +
> +void qemu_invalidate_map_cache(void)
> +{
> +}
> +
> +void qemu_invalidate_entry(uint8_t *buffer)
> +{
> +}
> +#endif /* !MAPCACHE */
> diff --git a/xen_mapcache.h b/xen_mapcache.h
> new file mode 100644
> index 0000000..5a6730f
> --- /dev/null
> +++ b/xen_mapcache.h
> @@ -0,0 +1,26 @@
> +#ifndef XEN_MAPCACHE_H
> +#define XEN_MAPCACHE_H
> +
> +#if (defined(__i386__) || defined(__x86_64__))
> +# Âdefine MAPCACHE

xen_mapcache.c could be split into two files, xen-mapcache-stub.c and
xen-mapcache.c. configure could perform the check for i386 or x86_64
host and define CONFIG_XEN_MAPCACHE=y appropriately. Then
Makefile.target would compile the correct file based on that.

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