From cd306087e5a9ea4091071a0a41c0ea99fac60ab0 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 19 May 2011 18:35:43 +0100 Subject: xen: remove qemu_map_cache_unlock There is no need for qemu_map_cache_unlock, just use qemu_invalidate_entry instead. Signed-off-by: Stefano Stabellini Signed-off-by: Alexander Graf --- exec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index 09928a3b37..01f33bb2bc 100644 --- a/exec.c +++ b/exec.c @@ -3146,7 +3146,7 @@ void qemu_put_ram_ptr(void *addr) xen_unmap_block(block->host, block->length); block->host = NULL; } else { - qemu_map_cache_unlock(addr); + qemu_invalidate_entry(addr); } } } -- cgit v1.2.3-55-g7522 From 6506e4f995967b1a48cc34418c77b318df92ce35 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 19 May 2011 18:35:44 +0100 Subject: xen: remove xen_map_block and xen_unmap_block Replace xen_map_block with qemu_map_cache with the appropriate locking and size parameters. Replace xen_unmap_block with qemu_invalidate_entry. Signed-off-by: Stefano Stabellini Signed-off-by: Alexander Graf --- exec.c | 19 ++++--------------- xen-mapcache-stub.c | 4 ---- xen-mapcache.c | 31 ------------------------------- xen-mapcache.h | 15 --------------- 4 files changed, 4 insertions(+), 65 deletions(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index 01f33bb2bc..e11c1dd97a 100644 --- a/exec.c +++ b/exec.c @@ -53,6 +53,7 @@ #endif #else /* !CONFIG_USER_ONLY */ #include "xen-mapcache.h" +#include "trace.h" #endif //#define DEBUG_TB_INVALIDATE @@ -3088,7 +3089,7 @@ void *qemu_get_ram_ptr(ram_addr_t addr) if (block->offset == 0) { return qemu_map_cache(addr, 0, 1); } else if (block->host == NULL) { - block->host = xen_map_block(block->offset, block->length); + block->host = qemu_map_cache(block->offset, block->length, 1); } } return block->host + (addr - block->offset); @@ -3117,7 +3118,7 @@ void *qemu_safe_ram_ptr(ram_addr_t addr) if (block->offset == 0) { return qemu_map_cache(addr, 0, 1); } else if (block->host == NULL) { - block->host = xen_map_block(block->offset, block->length); + block->host = qemu_map_cache(block->offset, block->length, 1); } } return block->host + (addr - block->offset); @@ -3135,19 +3136,7 @@ void qemu_put_ram_ptr(void *addr) trace_qemu_put_ram_ptr(addr); if (xen_mapcache_enabled()) { - RAMBlock *block; - - QLIST_FOREACH(block, &ram_list.blocks, next) { - if (addr == block->host) { - break; - } - } - if (block && block->host) { - xen_unmap_block(block->host, block->length); - block->host = NULL; - } else { - qemu_invalidate_entry(addr); - } + qemu_invalidate_entry(block->host); } } diff --git a/xen-mapcache-stub.c b/xen-mapcache-stub.c index 60f712b229..8a2380a151 100644 --- a/xen-mapcache-stub.c +++ b/xen-mapcache-stub.c @@ -34,7 +34,3 @@ void qemu_invalidate_map_cache(void) void qemu_invalidate_entry(uint8_t *buffer) { } -uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size) -{ - return NULL; -} diff --git a/xen-mapcache.c b/xen-mapcache.c index 57fe24de86..fac47cd9be 100644 --- a/xen-mapcache.c +++ b/xen-mapcache.c @@ -362,34 +362,3 @@ void qemu_invalidate_map_cache(void) mapcache_unlock(); } - -uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size) -{ - uint8_t *vaddr_base; - xen_pfn_t *pfns; - int *err; - unsigned int i; - target_phys_addr_t nb_pfn = size >> XC_PAGE_SHIFT; - - trace_xen_map_block(phys_addr, size); - phys_addr >>= XC_PAGE_SHIFT; - - pfns = qemu_mallocz(nb_pfn * sizeof (xen_pfn_t)); - err = qemu_mallocz(nb_pfn * sizeof (int)); - - for (i = 0; i < nb_pfn; i++) { - pfns[i] = phys_addr + i; - } - - vaddr_base = xc_map_foreign_bulk(xen_xc, xen_domid, PROT_READ|PROT_WRITE, - pfns, err, nb_pfn); - if (vaddr_base == NULL) { - perror("xc_map_foreign_bulk"); - exit(-1); - } - - qemu_free(pfns); - qemu_free(err); - - return vaddr_base; -} diff --git a/xen-mapcache.h b/xen-mapcache.h index b89b8f9653..6216cc3be7 100644 --- a/xen-mapcache.h +++ b/xen-mapcache.h @@ -9,27 +9,12 @@ #ifndef XEN_MAPCACHE_H #define XEN_MAPCACHE_H -#include -#include "trace.h" - void qemu_map_cache_init(void); uint8_t *qemu_map_cache(target_phys_addr_t phys_addr, target_phys_addr_t size, uint8_t lock); ram_addr_t qemu_ram_addr_from_mapcache(void *ptr); void qemu_invalidate_entry(uint8_t *buffer); void qemu_invalidate_map_cache(void); -uint8_t *xen_map_block(target_phys_addr_t phys_addr, target_phys_addr_t size); - -static inline void xen_unmap_block(void *addr, ram_addr_t size) -{ - trace_xen_unmap_block(addr, size); - - if (munmap(addr, size) != 0) { - hw_error("xen_unmap_block: %s", strerror(errno)); - } -} - - #define mapcache_lock() ((void)0) #define mapcache_unlock() ((void)0) -- cgit v1.2.3-55-g7522 From 38bee5dc94ee355640b030d28f311b03ee2f13d1 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 19 May 2011 18:35:45 +0100 Subject: exec.c: refactor cpu_physical_memory_map Introduce qemu_ram_ptr_length that takes an address and a size as parameters rather than just an address. Refactor cpu_physical_memory_map so that we call qemu_ram_ptr_length only once rather than calling qemu_get_ram_ptr one time per page. This is not only more efficient but also tries to simplify the logic of the function. Currently we are relying on the fact that all the pages are mapped contiguously in qemu's address space: we have a check to make sure that the virtual address returned by qemu_get_ram_ptr from the second call on is consecutive. Now we are making this more explicit replacing all the calls to qemu_get_ram_ptr with a single call to qemu_ram_ptr_length passing a size argument. Signed-off-by: Stefano Stabellini CC: agraf@suse.de CC: anthony@codemonkey.ws Signed-off-by: Alexander Graf --- cpu-common.h | 1 + exec.c | 51 ++++++++++++++++++++++++++++++++++----------------- 2 files changed, 35 insertions(+), 17 deletions(-) (limited to 'exec.c') diff --git a/cpu-common.h b/cpu-common.h index 9f5917224a..b027e43088 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -65,6 +65,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr); void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should only be used for ram local to a device. */ void *qemu_get_ram_ptr(ram_addr_t addr); +void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size); /* Same but slower, to use for migration, where the order of * RAMBlocks must not change. */ void *qemu_safe_ram_ptr(ram_addr_t addr); diff --git a/exec.c b/exec.c index e11c1dd97a..238c173de4 100644 --- a/exec.c +++ b/exec.c @@ -3131,6 +3131,31 @@ void *qemu_safe_ram_ptr(ram_addr_t addr) return NULL; } +/* Return a host pointer to guest's ram. Similar to qemu_get_ram_ptr + * but takes a size argument */ +void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size) +{ + if (xen_mapcache_enabled()) + return qemu_map_cache(addr, *size, 1); + else { + RAMBlock *block; + + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (addr - block->offset < block->length) { + if (addr - block->offset + *size > block->length) + *size = block->length - addr + block->offset; + return block->host + (addr - block->offset); + } + } + + fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr); + abort(); + + *size = 0; + return NULL; + } +} + void qemu_put_ram_ptr(void *addr) { trace_qemu_put_ram_ptr(addr); @@ -3992,14 +4017,12 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, int is_write) { target_phys_addr_t len = *plen; - target_phys_addr_t done = 0; + target_phys_addr_t todo = 0; int l; - uint8_t *ret = NULL; - uint8_t *ptr; target_phys_addr_t page; unsigned long pd; PhysPageDesc *p; - unsigned long addr1; + target_phys_addr_t addr1 = addr; while (len > 0) { page = addr & TARGET_PAGE_MASK; @@ -4014,7 +4037,7 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, } if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { - if (done || bounce.buffer) { + if (todo || bounce.buffer) { break; } bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE); @@ -4023,23 +4046,17 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, if (!is_write) { cpu_physical_memory_read(addr, bounce.buffer, l); } - ptr = bounce.buffer; - } else { - addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); - ptr = qemu_get_ram_ptr(addr1); - } - if (!done) { - ret = ptr; - } else if (ret + done != ptr) { - break; + + *plen = l; + return bounce.buffer; } len -= l; addr += l; - done += l; + todo += l; } - *plen = done; - return ret; + *plen = todo; + return qemu_ram_ptr_length(addr1, plen); } /* Unmaps a memory region previously mapped by cpu_physical_memory_map(). -- cgit v1.2.3-55-g7522 From 712c2b41490a986a5dd99bec99b854bac4322201 Mon Sep 17 00:00:00 2001 From: Stefano Stabellini Date: Thu, 19 May 2011 18:35:46 +0100 Subject: xen: mapcache performance improvements Use qemu_invalidate_entry in cpu_physical_memory_unmap. Do not lock mapcache entries in qemu_get_ram_ptr if the address falls in the ramblock with offset == 0. We don't need to do that because the callers of qemu_get_ram_ptr either try to map an entire block, other from the main ramblock, or until the end of a page to implement a single read or write in the main ramblock. If we don't lock mapcache entries in qemu_get_ram_ptr we don't need to call qemu_invalidate_entry in qemu_put_ram_ptr anymore because we can leave with few long lived block mappings requested by devices. Also move the call to qemu_ram_addr_from_mapcache at the beginning of qemu_ram_addr_from_host. Signed-off-by: Stefano Stabellini Signed-off-by: Alexander Graf --- exec.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) (limited to 'exec.c') diff --git a/exec.c b/exec.c index 238c173de4..7f14332c87 100644 --- a/exec.c +++ b/exec.c @@ -3085,9 +3085,10 @@ void *qemu_get_ram_ptr(ram_addr_t addr) 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. + * In that case just map until the end of the page. */ if (block->offset == 0) { - return qemu_map_cache(addr, 0, 1); + return qemu_map_cache(addr, 0, 0); } else if (block->host == NULL) { block->host = qemu_map_cache(block->offset, block->length, 1); } @@ -3114,9 +3115,10 @@ void *qemu_safe_ram_ptr(ram_addr_t addr) 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. + * In that case just map until the end of the page. */ if (block->offset == 0) { - return qemu_map_cache(addr, 0, 1); + return qemu_map_cache(addr, 0, 0); } else if (block->host == NULL) { block->host = qemu_map_cache(block->offset, block->length, 1); } @@ -3159,10 +3161,6 @@ void *qemu_ram_ptr_length(target_phys_addr_t addr, target_phys_addr_t *size) void qemu_put_ram_ptr(void *addr) { trace_qemu_put_ram_ptr(addr); - - if (xen_mapcache_enabled()) { - qemu_invalidate_entry(block->host); - } } int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) @@ -3170,6 +3168,11 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) RAMBlock *block; uint8_t *host = ptr; + if (xen_mapcache_enabled()) { + *ram_addr = qemu_ram_addr_from_mapcache(ptr); + return 0; + } + QLIST_FOREACH(block, &ram_list.blocks, next) { /* This case append when the block is not mapped. */ if (block->host == NULL) { @@ -3181,11 +3184,6 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) } } - if (xen_mapcache_enabled()) { - *ram_addr = qemu_ram_addr_from_mapcache(ptr); - return 0; - } - return -1; } @@ -4086,13 +4084,7 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, } } if (xen_mapcache_enabled()) { - uint8_t *buffer1 = buffer; - uint8_t *end_buffer = buffer + len; - - while (buffer1 < end_buffer) { - qemu_put_ram_ptr(buffer1); - buffer1 += TARGET_PAGE_SIZE; - } + qemu_invalidate_entry(buffer); } return; } -- cgit v1.2.3-55-g7522