X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=xen-mapcache.c;h=8f3a5920135264d0323ab598523b992e49ad743d;hb=47989f14472262a289894058f7babf1db37edda5;hp=a80cbdb6a720766dfa677de87d77eff4c1cb63b7;hpb=e2deee3ea6136b6189e8cfd26379420b9a398d96;p=mirror_qemu.git diff --git a/xen-mapcache.c b/xen-mapcache.c index a80cbdb6a7..8f3a592013 100644 --- a/xen-mapcache.c +++ b/xen-mapcache.c @@ -8,16 +8,15 @@ * GNU GPL, version 2 or (at your option) any later version. */ -#include "config.h" +#include "qemu/osdep.h" #include -#include "hw/xen_backend.h" +#include "hw/xen/xen_backend.h" #include "sysemu/blockdev.h" #include "qemu/bitmap.h" #include -#include #include "sysemu/xen-mapcache.h" #include "trace.h" @@ -33,10 +32,10 @@ # define DPRINTF(fmt, ...) do { } while (0) #endif -#if defined(__i386__) +#if HOST_LONG_BITS == 32 # define MCACHE_BUCKET_SHIFT 16 # define MCACHE_MAX_SIZE (1UL<<31) /* 2GB Cap */ -#elif defined(__x86_64__) +#else # define MCACHE_BUCKET_SHIFT 20 # define MCACHE_MAX_SIZE (1UL<<35) /* 32GB Cap */ #endif @@ -49,9 +48,6 @@ */ #define NON_MCACHE_MEMORY_SIZE (80 * 1024 * 1024) -#define mapcache_lock() ((void)0) -#define mapcache_unlock() ((void)0) - typedef struct MapCacheEntry { hwaddr paddr_index; uint8_t *vaddr_base; @@ -79,11 +75,22 @@ typedef struct MapCache { unsigned int mcache_bucket_shift; phys_offset_to_gaddr_t phys_offset_to_gaddr; + QemuMutex lock; void *opaque; } MapCache; static MapCache *mapcache; +static inline void mapcache_lock(void) +{ + qemu_mutex_lock(&mapcache->lock); +} + +static inline void mapcache_unlock(void) +{ + qemu_mutex_unlock(&mapcache->lock); +} + static inline int test_bits(int nr, int size, const unsigned long *addr) { unsigned long res = find_next_zero_bit(addr, size + nr, nr); @@ -102,6 +109,7 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque) mapcache->phys_offset_to_gaddr = f; mapcache->opaque = opaque; + qemu_mutex_init(&mapcache->lock); QTAILQ_INIT(&mapcache->locked_entries); @@ -160,19 +168,17 @@ static void xen_remap_bucket(MapCacheEntry *entry, exit(-1); } } - if (entry->valid_mapping != NULL) { - g_free(entry->valid_mapping); - entry->valid_mapping = NULL; - } + g_free(entry->valid_mapping); + entry->valid_mapping = NULL; for (i = 0; i < nb_pfn; 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, nb_pfn); + vaddr_base = xenforeignmemory_map(xen_fmem, xen_domid, PROT_READ|PROT_WRITE, + nb_pfn, pfns, err); if (vaddr_base == NULL) { - perror("xc_map_foreign_bulk"); + perror("xenforeignmemory_map"); exit(-1); } @@ -193,13 +199,14 @@ static void xen_remap_bucket(MapCacheEntry *entry, g_free(err); } -uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, - uint8_t lock) +static uint8_t *xen_map_cache_unlocked(hwaddr phys_addr, hwaddr size, + uint8_t lock) { MapCacheEntry *entry, *pentry = NULL; hwaddr address_index; hwaddr address_offset; - hwaddr __size = size; + hwaddr cache_size = size; + hwaddr test_bit_size; bool translated = false; tryagain: @@ -208,28 +215,43 @@ tryagain: trace_xen_map_cache(phys_addr); + /* test_bit_size is always a multiple of XC_PAGE_SIZE */ + if (size) { + test_bit_size = size + (phys_addr & (XC_PAGE_SIZE - 1)); + + if (test_bit_size % XC_PAGE_SIZE) { + test_bit_size += XC_PAGE_SIZE - (test_bit_size % XC_PAGE_SIZE); + } + } else { + test_bit_size = XC_PAGE_SIZE; + } + if (mapcache->last_entry != NULL && mapcache->last_entry->paddr_index == address_index && - !lock && !__size) { + !lock && !size && + test_bits(address_offset >> XC_PAGE_SHIFT, + test_bit_size >> XC_PAGE_SHIFT, + mapcache->last_entry->valid_mapping)) { trace_xen_map_cache_return(mapcache->last_entry->vaddr_base + address_offset); return mapcache->last_entry->vaddr_base + address_offset; } /* size is always a multiple of MCACHE_BUCKET_SIZE */ if (size) { - __size = size + address_offset; - if (__size % MCACHE_BUCKET_SIZE) { - __size += MCACHE_BUCKET_SIZE - (__size % MCACHE_BUCKET_SIZE); + cache_size = size + address_offset; + if (cache_size % MCACHE_BUCKET_SIZE) { + cache_size += MCACHE_BUCKET_SIZE - (cache_size % MCACHE_BUCKET_SIZE); } } else { - __size = MCACHE_BUCKET_SIZE; + cache_size = MCACHE_BUCKET_SIZE; } entry = &mapcache->entry[address_index % mapcache->nr_buckets]; while (entry && entry->lock && entry->vaddr_base && - (entry->paddr_index != address_index || entry->size != __size || - !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT, + (entry->paddr_index != address_index || entry->size != cache_size || + !test_bits(address_offset >> XC_PAGE_SHIFT, + test_bit_size >> XC_PAGE_SHIFT, entry->valid_mapping))) { pentry = entry; entry = entry->next; @@ -237,17 +259,19 @@ tryagain: if (!entry) { entry = g_malloc0(sizeof (MapCacheEntry)); pentry->next = entry; - xen_remap_bucket(entry, __size, address_index); + xen_remap_bucket(entry, cache_size, address_index); } else if (!entry->lock) { if (!entry->vaddr_base || entry->paddr_index != address_index || - entry->size != __size || - !test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT, + entry->size != cache_size || + !test_bits(address_offset >> XC_PAGE_SHIFT, + test_bit_size >> XC_PAGE_SHIFT, entry->valid_mapping)) { - xen_remap_bucket(entry, __size, address_index); + xen_remap_bucket(entry, cache_size, address_index); } } - if(!test_bits(address_offset >> XC_PAGE_SHIFT, size >> XC_PAGE_SHIFT, + if(!test_bits(address_offset >> XC_PAGE_SHIFT, + test_bit_size >> XC_PAGE_SHIFT, entry->valid_mapping)) { mapcache->last_entry = NULL; if (!translated && mapcache->phys_offset_to_gaddr) { @@ -273,14 +297,27 @@ tryagain: return mapcache->last_entry->vaddr_base + address_offset; } +uint8_t *xen_map_cache(hwaddr phys_addr, hwaddr size, + uint8_t lock) +{ + uint8_t *p; + + mapcache_lock(); + p = xen_map_cache_unlocked(phys_addr, size, lock); + mapcache_unlock(); + return p; +} + ram_addr_t xen_ram_addr_from_mapcache(void *ptr) { MapCacheEntry *entry = NULL; MapCacheRev *reventry; hwaddr paddr_index; hwaddr size; + ram_addr_t raddr; int found = 0; + mapcache_lock(); QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { if (reventry->vaddr_req == ptr) { paddr_index = reventry->paddr_index; @@ -305,13 +342,16 @@ ram_addr_t xen_ram_addr_from_mapcache(void *ptr) } if (!entry) { DPRINTF("Trying to find address %p that is not in the mapcache!\n", ptr); - return 0; + raddr = 0; + } else { + raddr = (reventry->paddr_index << MCACHE_BUCKET_SHIFT) + + ((unsigned long) ptr - (unsigned long) entry->vaddr_base); } - return (reventry->paddr_index << MCACHE_BUCKET_SHIFT) + - ((unsigned long) ptr - (unsigned long) entry->vaddr_base); + mapcache_unlock(); + return raddr; } -void xen_invalidate_map_cache_entry(uint8_t *buffer) +static void xen_invalidate_map_cache_entry_unlocked(uint8_t *buffer) { MapCacheEntry *entry = NULL, *pentry = NULL; MapCacheRev *reventry; @@ -365,6 +405,13 @@ void xen_invalidate_map_cache_entry(uint8_t *buffer) g_free(entry); } +void xen_invalidate_map_cache_entry(uint8_t *buffer) +{ + mapcache_lock(); + xen_invalidate_map_cache_entry_unlocked(buffer); + mapcache_unlock(); +} + void xen_invalidate_map_cache(void) { unsigned long i; @@ -373,14 +420,14 @@ void xen_invalidate_map_cache(void) /* Flush pending AIO before destroying the mapcache */ bdrv_drain_all(); + mapcache_lock(); + QTAILQ_FOREACH(reventry, &mapcache->locked_entries, next) { DPRINTF("There should be no locked mappings at this time, " "but "TARGET_FMT_plx" -> %p is present\n", reventry->paddr_index, reventry->vaddr_req); } - mapcache_lock(); - for (i = 0; i < mapcache->nr_buckets; i++) { MapCacheEntry *entry = &mapcache->entry[i];