diff options
| author | Peter Maydell <peter.maydell@linaro.org> | 2015-04-30 12:04:11 +0100 |
|---|---|---|
| committer | Peter Maydell <peter.maydell@linaro.org> | 2015-04-30 12:04:11 +0100 |
| commit | 06feaacfb4cfef10cc0c93d97df7bfc8a71dbc7e (patch) | |
| tree | 2aa3c097c678d2d5dde83d6df450aec28b994452 /exec.c | |
| parent | a1fe58f6ad2282399da256b8579b49b43527e486 (diff) | |
| parent | d064d9f381b00538e41f14104b88a1ae85d78865 (diff) | |
| download | focaccia-qemu-06feaacfb4cfef10cc0c93d97df7bfc8a71dbc7e.tar.gz focaccia-qemu-06feaacfb4cfef10cc0c93d97df7bfc8a71dbc7e.zip | |
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
- miscellaneous cleanups for TCG (Emilio) and NBD (Bogdan) - next part in the thread-safe address_space_* saga: atomic access to the bounce buffer and the map_clients list, from Fam - optional support for linking with tcmalloc, also from Fam - reapplying Peter Crosthwaite's "Respect as_translate_internal length clamp" after fixing the SPARC fallout. - build system fix from Wei Liu - small acpi-build and ioport cleanup by myself # gpg: Signature made Wed Apr 29 09:34:00 2015 BST using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (22 commits) nbd/trivial: fix type cast for ioctl translate-all: use bitmap helpers for PageDesc's bitmap target-i386: disable LINT0 after reset Makefile.target: prepend $libs_softmmu to $LIBS milkymist: do not modify libs-softmmu configure: Add support for tcmalloc exec: Respect as_translate_internal length clamp ioport: reserve the whole range of an I/O port in the AddressSpace ioport: loosen assertions on emulation of 16-bit ports ioport: remove wrong comment ide: there is only one data port gus: clean up MemoryRegionPortio sb16: remove useless mixer_write_indexw sun4m: fix slavio sysctrl and led register sizes acpi-build: remove dependency from ram_addr.h memory: add memory_region_ram_resize dma-helpers: Fix race condition of continue_after_map_failure and dma_aio_cancel exec: Notify cpu_register_map_client caller if the bounce buffer is available exec: Protect map_client_list with mutex linux-user, bsd-user: Remove two calls to cpu_exec_init_all ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'exec.c')
| -rw-r--r-- | exec.c | 81 |
1 files changed, 51 insertions, 30 deletions
diff --git a/exec.c b/exec.c index 53d59bb080..ae37b98e8c 100644 --- a/exec.c +++ b/exec.c @@ -380,7 +380,6 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, IOMMUTLBEntry iotlb; MemoryRegionSection *section; MemoryRegion *mr; - hwaddr len = *plen; rcu_read_lock(); for (;;) { @@ -395,7 +394,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, iotlb = mr->iommu_ops->translate(mr, addr, is_write); addr = ((iotlb.translated_addr & ~iotlb.addr_mask) | (addr & iotlb.addr_mask)); - len = MIN(len, (addr | iotlb.addr_mask) - addr + 1); + *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1); if (!(iotlb.perm & (1 << is_write))) { mr = &io_mem_unassigned; break; @@ -406,10 +405,9 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, if (xen_enabled() && memory_access_is_direct(mr, is_write)) { hwaddr page = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr; - len = MIN(page, len); + *plen = MIN(page, *plen); } - *plen = len; *xlat = addr; rcu_read_unlock(); return mr; @@ -429,15 +427,6 @@ address_space_translate_for_iotlb(CPUState *cpu, hwaddr addr, } #endif -void cpu_exec_init_all(void) -{ -#if !defined(CONFIG_USER_ONLY) - qemu_mutex_init(&ram_list.mutex); - memory_map_init(); - io_mem_init(); -#endif -} - #if !defined(CONFIG_USER_ONLY) static int cpu_common_post_load(void *opaque, int version_id) @@ -2518,46 +2507,77 @@ typedef struct { void *buffer; hwaddr addr; hwaddr len; + bool in_use; } BounceBuffer; static BounceBuffer bounce; typedef struct MapClient { - void *opaque; - void (*callback)(void *opaque); + QEMUBH *bh; QLIST_ENTRY(MapClient) link; } MapClient; +QemuMutex map_client_list_lock; static QLIST_HEAD(map_client_list, MapClient) map_client_list = QLIST_HEAD_INITIALIZER(map_client_list); -void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)) +static void cpu_unregister_map_client_do(MapClient *client) +{ + QLIST_REMOVE(client, link); + g_free(client); +} + +static void cpu_notify_map_clients_locked(void) +{ + MapClient *client; + + while (!QLIST_EMPTY(&map_client_list)) { + client = QLIST_FIRST(&map_client_list); + qemu_bh_schedule(client->bh); + cpu_unregister_map_client_do(client); + } +} + +void cpu_register_map_client(QEMUBH *bh) { MapClient *client = g_malloc(sizeof(*client)); - client->opaque = opaque; - client->callback = callback; + qemu_mutex_lock(&map_client_list_lock); + client->bh = bh; QLIST_INSERT_HEAD(&map_client_list, client, link); - return client; + if (!atomic_read(&bounce.in_use)) { + cpu_notify_map_clients_locked(); + } + qemu_mutex_unlock(&map_client_list_lock); } -static void cpu_unregister_map_client(void *_client) +void cpu_exec_init_all(void) { - MapClient *client = (MapClient *)_client; - - QLIST_REMOVE(client, link); - g_free(client); + qemu_mutex_init(&ram_list.mutex); + memory_map_init(); + io_mem_init(); + qemu_mutex_init(&map_client_list_lock); } -static void cpu_notify_map_clients(void) +void cpu_unregister_map_client(QEMUBH *bh) { MapClient *client; - while (!QLIST_EMPTY(&map_client_list)) { - client = QLIST_FIRST(&map_client_list); - client->callback(client->opaque); - cpu_unregister_map_client(client); + qemu_mutex_lock(&map_client_list_lock); + QLIST_FOREACH(client, &map_client_list, link) { + if (client->bh == bh) { + cpu_unregister_map_client_do(client); + break; + } } + qemu_mutex_unlock(&map_client_list_lock); +} + +static void cpu_notify_map_clients(void) +{ + qemu_mutex_lock(&map_client_list_lock); + cpu_notify_map_clients_locked(); + qemu_mutex_unlock(&map_client_list_lock); } bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_write) @@ -2606,7 +2626,7 @@ void *address_space_map(AddressSpace *as, l = len; mr = address_space_translate(as, addr, &xlat, &l, is_write); if (!memory_access_is_direct(mr, is_write)) { - if (bounce.buffer) { + if (atomic_xchg(&bounce.in_use, true)) { return NULL; } /* Avoid unbounded allocations */ @@ -2678,6 +2698,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, qemu_vfree(bounce.buffer); bounce.buffer = NULL; memory_region_unref(bounce.mr); + atomic_mb_set(&bounce.in_use, false); cpu_notify_map_clients(); } |