From c586eac33670c198c6c9ceb1419aa99dafcce907 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 29 Feb 2016 12:18:40 +0100 Subject: [PATCH 01/15] log: do not log if QEMU is daemonized but without -D Commit 96c33a4 ("log: Redirect stderr to logfile if deamonized", 2016-02-22) wanted to move stderr of a daemonized QEMU to the file specified with -D. However, if -D was not passed, the patch had the side effect of not redirecting stderr to /dev/null. This happened because qemu_logfile was set to stderr rather than the expected value of NULL. The fix is simply in the "if" condition of do_qemu_set_log; the "if" for closing the file is also changed to match. Reported-by: Jan Tomko Signed-off-by: Paolo Bonzini --- util/log.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/util/log.c b/util/log.c index a7ddc7ecd1..8b921de588 100644 --- a/util/log.c +++ b/util/log.c @@ -56,7 +56,8 @@ void do_qemu_set_log(int log_flags, bool use_own_buffers) #ifdef CONFIG_TRACE_LOG qemu_loglevel |= LOG_TRACE; #endif - if ((qemu_loglevel || is_daemonized()) && !qemu_logfile) { + if (!qemu_logfile && + (is_daemonized() ? logfilename != NULL : qemu_loglevel)) { if (logfilename) { qemu_logfile = fopen(logfilename, log_append ? "a" : "w"); if (!qemu_logfile) { @@ -72,6 +73,7 @@ void do_qemu_set_log(int log_flags, bool use_own_buffers) } } else { /* Default to stderr if no log file specified */ + assert(!is_daemonized()); qemu_logfile = stderr; } /* must avoid mmap() usage of glibc by setting a buffer "by hand" */ @@ -89,7 +91,8 @@ void do_qemu_set_log(int log_flags, bool use_own_buffers) log_append = 1; } } - if (!qemu_loglevel && !is_daemonized() && qemu_logfile) { + if (qemu_logfile && + (is_daemonized() ? logfilename == NULL : !qemu_loglevel)) { qemu_log_close(); } } From bb8f32c0318cb6c6e13e09ec0f35e21eff246413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= Date: Thu, 25 Feb 2016 13:45:32 +0100 Subject: [PATCH 02/15] i8257: fix Terminal Count status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a DMA transfer is done (ie all bytes have been transfered), the corresponding Terminal Count bit must be set in the status register. This bit is already cleared in i8257_read_cont and i8257_write_cont when required. This fixes (at least) floppy transfer in IBM 40p firmware, which checks in DMA controller if everything went fine. Signed-off-by: HervĂ© Poussineau Message-Id: <1456404332-31556-1-git-send-email-hpoussin@reactos.org> Reviewed-by: John Snow Signed-off-by: Paolo Bonzini --- hw/dma/i8257.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c index 5a52707ae2..6078893efb 100644 --- a/hw/dma/i8257.c +++ b/hw/dma/i8257.c @@ -342,6 +342,10 @@ static void i8257_channel_run(I8257State *d, int ichan) r->now[COUNT], (r->base[COUNT] + 1) << ncont); r->now[COUNT] = n; ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont); + if (n == (r->base[COUNT] + 1) << ncont) { + ldebug("transfer done\n"); + d->status |= (1 << ichan); + } } static void i8257_dma_run(void *opaque) From 528f46af6ecd1e300db18684969104d4067b867b Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 1 Mar 2016 14:18:18 +0800 Subject: [PATCH 03/15] exec: Return RAMBlock pointer from allocating functions Previously we return RAMBlock.offset; now return the pointer to the whole structure. ram_block_add returns void now, error is completely passed with errp. Reviewed-by: Gonglei Signed-off-by: Fam Zheng Message-Id: <1456813104-25902-2-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- exec.c | 51 ++++++++++++++++++----------------------- include/exec/ram_addr.h | 22 +++++++++--------- memory.c | 25 ++++++++++++++++---- 3 files changed, 53 insertions(+), 45 deletions(-) diff --git a/exec.c b/exec.c index c62c43903c..2b14b7954e 100644 --- a/exec.c +++ b/exec.c @@ -1554,7 +1554,7 @@ static void dirty_memory_extend(ram_addr_t old_ram_size, } } -static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp) +static void ram_block_add(RAMBlock *new_block, Error **errp) { RAMBlock *block; RAMBlock *last_block = NULL; @@ -1573,7 +1573,6 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp) if (err) { error_propagate(errp, err); qemu_mutex_unlock_ramlist(); - return -1; } } else { new_block->host = phys_mem_alloc(new_block->max_length, @@ -1583,7 +1582,6 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp) "cannot set up guest memory '%s'", memory_region_name(new_block->mr)); qemu_mutex_unlock_ramlist(); - return -1; } memory_try_enable_merging(new_block->host, new_block->max_length); } @@ -1631,22 +1629,19 @@ static ram_addr_t ram_block_add(RAMBlock *new_block, Error **errp) kvm_setup_guest_memory(new_block->host, new_block->max_length); } } - - return new_block->offset; } #ifdef __linux__ -ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, - bool share, const char *mem_path, - Error **errp) +RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, + bool share, const char *mem_path, + Error **errp) { RAMBlock *new_block; - ram_addr_t addr; Error *local_err = NULL; if (xen_enabled()) { error_setg(errp, "-mem-path not supported with Xen"); - return -1; + return NULL; } if (phys_mem_alloc != qemu_anon_ram_alloc) { @@ -1657,7 +1652,7 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, */ error_setg(errp, "-mem-path not supported with this accelerator"); - return -1; + return NULL; } size = HOST_PAGE_ALIGN(size); @@ -1670,29 +1665,28 @@ ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, mem_path, errp); if (!new_block->host) { g_free(new_block); - return -1; + return NULL; } - addr = ram_block_add(new_block, &local_err); + ram_block_add(new_block, &local_err); if (local_err) { g_free(new_block); error_propagate(errp, local_err); - return -1; + return NULL; } - return addr; + return new_block; } #endif static -ram_addr_t qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size, - void (*resized)(const char*, - uint64_t length, - void *host), - void *host, bool resizeable, - MemoryRegion *mr, Error **errp) +RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size, + void (*resized)(const char*, + uint64_t length, + void *host), + void *host, bool resizeable, + MemoryRegion *mr, Error **errp) { RAMBlock *new_block; - ram_addr_t addr; Error *local_err = NULL; size = HOST_PAGE_ALIGN(size); @@ -1711,29 +1705,28 @@ ram_addr_t qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size, if (resizeable) { new_block->flags |= RAM_RESIZEABLE; } - addr = ram_block_add(new_block, &local_err); + ram_block_add(new_block, &local_err); if (local_err) { g_free(new_block); error_propagate(errp, local_err); - return -1; + return NULL; } - mr->ram_block = new_block; - return addr; + return new_block; } -ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, +RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, MemoryRegion *mr, Error **errp) { return qemu_ram_alloc_internal(size, size, NULL, host, false, mr, errp); } -ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp) +RAMBlock *qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp) { return qemu_ram_alloc_internal(size, size, NULL, NULL, false, mr, errp); } -ram_addr_t qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t maxsz, +RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t maxsz, void (*resized)(const char*, uint64_t length, void *host), diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 5d33def09a..865e19b8ac 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -94,17 +94,17 @@ ram_addr_t last_ram_offset(void); void qemu_mutex_lock_ramlist(void); void qemu_mutex_unlock_ramlist(void); -ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, - bool share, const char *mem_path, - Error **errp); -ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, - MemoryRegion *mr, Error **errp); -ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp); -ram_addr_t qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size, - void (*resized)(const char*, - uint64_t length, - void *host), - MemoryRegion *mr, Error **errp); +RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, + bool share, const char *mem_path, + Error **errp); +RAMBlock *qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, + MemoryRegion *mr, Error **errp); +RAMBlock *qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp); +RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size, + void (*resized)(const char*, + uint64_t length, + void *host), + MemoryRegion *mr, Error **errp); int qemu_get_ram_fd(ram_addr_t addr); void qemu_set_ram_fd(ram_addr_t addr, int fd); void *qemu_get_ram_block_host_ptr(ram_addr_t addr); diff --git a/memory.c b/memory.c index 013c2ed531..d630b01856 100644 --- a/memory.c +++ b/memory.c @@ -1270,11 +1270,14 @@ void memory_region_init_ram(MemoryRegion *mr, uint64_t size, Error **errp) { + RAMBlock *ram_block; + memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_addr = qemu_ram_alloc(size, mr, errp); + ram_block = qemu_ram_alloc(size, mr, errp); + mr->ram_addr = ram_block->offset; mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } @@ -1288,11 +1291,14 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, void *host), Error **errp) { + RAMBlock *ram_block; + memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_addr = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp); + ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp); + mr->ram_addr = ram_block->offset; mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } @@ -1305,11 +1311,14 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, const char *path, Error **errp) { + RAMBlock *ram_block; + memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - mr->ram_addr = qemu_ram_alloc_from_file(size, mr, share, path, errp); + ram_block = qemu_ram_alloc_from_file(size, mr, share, path, errp); + mr->ram_addr = ram_block->offset; mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } #endif @@ -1320,6 +1329,8 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, uint64_t size, void *ptr) { + RAMBlock *ram_block; + memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; @@ -1328,7 +1339,8 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ assert(ptr != NULL); - mr->ram_addr = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); + ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); + mr->ram_addr = ram_block->offset; } void memory_region_set_skip_dump(MemoryRegion *mr) @@ -1356,13 +1368,16 @@ void memory_region_init_rom_device(MemoryRegion *mr, uint64_t size, Error **errp) { + RAMBlock *ram_block; + memory_region_init(mr, owner, name, size); mr->ops = ops; mr->opaque = opaque; mr->terminates = true; mr->rom_device = true; mr->destructor = memory_region_destructor_rom_device; - mr->ram_addr = qemu_ram_alloc(size, mr, errp); + ram_block = qemu_ram_alloc(size, mr, errp); + mr->ram_addr = ram_block->offset; } void memory_region_init_iommu(MemoryRegion *mr, From 0a75601853c00f3729fa62c49ec0d4bb1e3d9bc1 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 1 Mar 2016 14:18:19 +0800 Subject: [PATCH 04/15] memory: Move assignment to ram_block to memory_region_init_* We don't force "const" qualifiers with pointers in QEMU, but it's still good to keep a clean function interface. Assigning to mr->ram_block is in this sense ugly - one initializer mutating its owning object's state. Move it to memory_region_init_*, where mr->ram_addr is assigned. Reviewed-by: Gonglei Signed-off-by: Fam Zheng Message-Id: <1456813104-25902-3-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- exec.c | 1 - memory.c | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/exec.c b/exec.c index 2b14b7954e..83e3f7d31b 100644 --- a/exec.c +++ b/exec.c @@ -1711,7 +1711,6 @@ RAMBlock *qemu_ram_alloc_internal(ram_addr_t size, ram_addr_t max_size, error_propagate(errp, local_err); return NULL; } - mr->ram_block = new_block; return new_block; } diff --git a/memory.c b/memory.c index d630b01856..1aa777da7f 100644 --- a/memory.c +++ b/memory.c @@ -1277,6 +1277,7 @@ void memory_region_init_ram(MemoryRegion *mr, mr->terminates = true; mr->destructor = memory_region_destructor_ram; ram_block = qemu_ram_alloc(size, mr, errp); + mr->ram_block = ram_block; mr->ram_addr = ram_block->offset; mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } @@ -1298,6 +1299,7 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, mr->terminates = true; mr->destructor = memory_region_destructor_ram; ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp); + mr->ram_block = ram_block; mr->ram_addr = ram_block->offset; mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } @@ -1318,6 +1320,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, mr->terminates = true; mr->destructor = memory_region_destructor_ram; ram_block = qemu_ram_alloc_from_file(size, mr, share, path, errp); + mr->ram_block = ram_block; mr->ram_addr = ram_block->offset; mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } @@ -1340,6 +1343,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ assert(ptr != NULL); ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); + mr->ram_block = ram_block; mr->ram_addr = ram_block->offset; } @@ -1377,6 +1381,7 @@ void memory_region_init_rom_device(MemoryRegion *mr, mr->rom_device = true; mr->destructor = memory_region_destructor_rom_device; ram_block = qemu_ram_alloc(size, mr, errp); + mr->ram_block = ram_block; mr->ram_addr = ram_block->offset; } From 7ebb2745acbb8d910eab07dc5f0aa01a4457703c Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 1 Mar 2016 14:18:20 +0800 Subject: [PATCH 05/15] memory: Implement memory_region_get_ram_addr with mr->ram_block Signed-off-by: Fam Zheng Message-Id: <1456813104-25902-4-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 8 +------- memory.c | 5 +++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index d5284c2435..810d2c0b30 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -978,14 +978,8 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, /** * memory_region_get_ram_addr: Get the ram address associated with a memory * region - * - * DO NOT USE THIS FUNCTION. This is a temporary workaround while the Xen - * code is being reworked. */ -static inline ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr) -{ - return mr->ram_addr; -} +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr); uint64_t memory_region_get_alignment(const MemoryRegion *mr); /** diff --git a/memory.c b/memory.c index 1aa777da7f..d83405b176 100644 --- a/memory.c +++ b/memory.c @@ -1640,6 +1640,11 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) return ptr + offset; } +ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr) +{ + return mr->ram_block ? mr->ram_block->offset : RAM_ADDR_INVALID; +} + void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp) { assert(mr->ram_addr != RAM_ADDR_INVALID); From 8e41fb63c5bf29ecabe0cee1239bf6230f19978a Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 1 Mar 2016 14:18:21 +0800 Subject: [PATCH 06/15] memory: Drop MemoryRegion.ram_addr All references to mr->ram_addr are replaced by memory_region_get_ram_addr(mr) (except for a few assertions that are replaced with mr->ram_block). Reviewed-by: Gonglei Signed-off-by: Fam Zheng Message-Id: <1456813104-25902-5-git-send-email-famz@redhat.com> Acked-by: Laszlo Ersek Signed-off-by: Paolo Bonzini --- cputlb.c | 4 +- exec.c | 3 +- hw/misc/ivshmem.c | 9 +++-- include/exec/memory.h | 1 - kvm-all.c | 3 +- memory.c | 71 ++++++++++++++---------------------- scripts/dump-guest-memory.py | 2 +- 7 files changed, 40 insertions(+), 53 deletions(-) diff --git a/cputlb.c b/cputlb.c index 3973030161..2f7a166491 100644 --- a/cputlb.c +++ b/cputlb.c @@ -416,8 +416,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, /* Write access calls the I/O callback. */ te->addr_write = address | TLB_MMIO; } else if (memory_region_is_ram(section->mr) - && cpu_physical_memory_is_clean(section->mr->ram_addr - + xlat)) { + && cpu_physical_memory_is_clean( + memory_region_get_ram_addr(section->mr) + xlat)) { te->addr_write = address | TLB_NOTDIRTY; } else { te->addr_write = address; diff --git a/exec.c b/exec.c index 83e3f7d31b..6ed4203b97 100644 --- a/exec.c +++ b/exec.c @@ -2699,7 +2699,8 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr, } } else { /* RAM case */ - ptr = qemu_get_ram_ptr(mr->ram_block, mr->ram_addr + addr1); + ptr = qemu_get_ram_ptr(mr->ram_block, + memory_region_get_ram_addr(mr) + addr1); memcpy(buf, ptr, l); } diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 48b7a34a8f..1838bc8506 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -400,7 +400,7 @@ static int create_shared_memory_BAR(IVShmemState *s, int fd, uint8_t attr, memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2", s->ivshmem_size, ptr); - qemu_set_ram_fd(s->ivshmem.ram_addr, fd); + qemu_set_ram_fd(memory_region_get_ram_addr(&s->ivshmem), fd); vmstate_register_ram(&s->ivshmem, DEVICE(s)); memory_region_add_subregion(&s->bar, 0, &s->ivshmem); @@ -661,7 +661,8 @@ static void ivshmem_read(void *opaque, const uint8_t *buf, int size) } memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2", s->ivshmem_size, map_ptr); - qemu_set_ram_fd(s->ivshmem.ram_addr, incoming_fd); + qemu_set_ram_fd(memory_region_get_ram_addr(&s->ivshmem), + incoming_fd); vmstate_register_ram(&s->ivshmem, DEVICE(s)); IVSHMEM_DPRINTF("guest h/w addr = %p, size = %" PRIu64 "\n", @@ -996,8 +997,10 @@ static void pci_ivshmem_exit(PCIDevice *dev) strerror(errno)); } - if ((fd = qemu_get_ram_fd(s->ivshmem.ram_addr)) != -1) + fd = qemu_get_ram_fd(memory_region_get_ram_addr(&s->ivshmem)); + if (fd != -1) { close(fd); + } } vmstate_unregister_ram(&s->ivshmem, DEVICE(dev)); diff --git a/include/exec/memory.h b/include/exec/memory.h index 810d2c0b30..2de789871d 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -169,7 +169,6 @@ struct MemoryRegion { bool flush_coalesced_mmio; bool global_locking; uint8_t dirty_log_mask; - ram_addr_t ram_addr; RAMBlock *ram_block; Object *owner; const MemoryRegionIOMMUOps *iommu_ops; diff --git a/kvm-all.c b/kvm-all.c index a65e73fb1d..161200edb0 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -366,7 +366,8 @@ static void kvm_log_stop(MemoryListener *listener, static int kvm_get_dirty_pages_log_range(MemoryRegionSection *section, unsigned long *bitmap) { - ram_addr_t start = section->offset_within_region + section->mr->ram_addr; + ram_addr_t start = section->offset_within_region + + memory_region_get_ram_addr(section->mr); ram_addr_t pages = int128_get64(section->size) / getpagesize(); cpu_physical_memory_set_dirty_lebitmap(bitmap, start, pages); diff --git a/memory.c b/memory.c index d83405b176..5b5791caf4 100644 --- a/memory.c +++ b/memory.c @@ -902,12 +902,12 @@ static void memory_region_destructor_none(MemoryRegion *mr) static void memory_region_destructor_ram(MemoryRegion *mr) { - qemu_ram_free(mr->ram_addr); + qemu_ram_free(memory_region_get_ram_addr(mr)); } static void memory_region_destructor_rom_device(MemoryRegion *mr) { - qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK); + qemu_ram_free(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); } static bool memory_region_need_escape(char c) @@ -1038,7 +1038,6 @@ static void memory_region_initfn(Object *obj) ObjectProperty *op; mr->ops = &unassigned_mem_ops; - mr->ram_addr = RAM_ADDR_INVALID; mr->enabled = true; mr->romd_mode = true; mr->global_locking = true; @@ -1270,15 +1269,11 @@ void memory_region_init_ram(MemoryRegion *mr, uint64_t size, Error **errp) { - RAMBlock *ram_block; - memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - ram_block = qemu_ram_alloc(size, mr, errp); - mr->ram_block = ram_block; - mr->ram_addr = ram_block->offset; + mr->ram_block = qemu_ram_alloc(size, mr, errp); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } @@ -1292,15 +1287,12 @@ void memory_region_init_resizeable_ram(MemoryRegion *mr, void *host), Error **errp) { - RAMBlock *ram_block; - memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, mr, errp); - mr->ram_block = ram_block; - mr->ram_addr = ram_block->offset; + mr->ram_block = qemu_ram_alloc_resizeable(size, max_size, resized, + mr, errp); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } @@ -1313,15 +1305,11 @@ void memory_region_init_ram_from_file(MemoryRegion *mr, const char *path, Error **errp) { - RAMBlock *ram_block; - memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; - ram_block = qemu_ram_alloc_from_file(size, mr, share, path, errp); - mr->ram_block = ram_block; - mr->ram_addr = ram_block->offset; + mr->ram_block = qemu_ram_alloc_from_file(size, mr, share, path, errp); mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; } #endif @@ -1332,8 +1320,6 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, uint64_t size, void *ptr) { - RAMBlock *ram_block; - memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; @@ -1342,9 +1328,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ assert(ptr != NULL); - ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); - mr->ram_block = ram_block; - mr->ram_addr = ram_block->offset; + mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); } void memory_region_set_skip_dump(MemoryRegion *mr) @@ -1372,17 +1356,13 @@ void memory_region_init_rom_device(MemoryRegion *mr, uint64_t size, Error **errp) { - RAMBlock *ram_block; - memory_region_init(mr, owner, name, size); mr->ops = ops; mr->opaque = opaque; mr->terminates = true; mr->rom_device = true; mr->destructor = memory_region_destructor_rom_device; - ram_block = qemu_ram_alloc(size, mr, errp); - mr->ram_block = ram_block; - mr->ram_addr = ram_block->offset; + mr->ram_block = qemu_ram_alloc(size, mr, errp); } void memory_region_init_iommu(MemoryRegion *mr, @@ -1547,24 +1527,26 @@ void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size, unsigned client) { - assert(mr->ram_addr != RAM_ADDR_INVALID); - return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size, client); + assert(mr->ram_block); + return cpu_physical_memory_get_dirty(memory_region_get_ram_addr(mr) + addr, + size, client); } void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size) { - assert(mr->ram_addr != RAM_ADDR_INVALID); - cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, + assert(mr->ram_block); + cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr, + size, memory_region_get_dirty_log_mask(mr)); } bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size, unsigned client) { - assert(mr->ram_addr != RAM_ADDR_INVALID); - return cpu_physical_memory_test_and_clear_dirty(mr->ram_addr + addr, - size, client); + assert(mr->ram_block); + return cpu_physical_memory_test_and_clear_dirty( + memory_region_get_ram_addr(mr) + addr, size, client); } @@ -1607,9 +1589,9 @@ void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode) void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr, hwaddr size, unsigned client) { - assert(mr->ram_addr != RAM_ADDR_INVALID); - cpu_physical_memory_test_and_clear_dirty(mr->ram_addr + addr, size, - client); + assert(mr->ram_block); + cpu_physical_memory_test_and_clear_dirty( + memory_region_get_ram_addr(mr) + addr, size, client); } int memory_region_get_fd(MemoryRegion *mr) @@ -1618,9 +1600,9 @@ int memory_region_get_fd(MemoryRegion *mr) return memory_region_get_fd(mr->alias); } - assert(mr->ram_addr != RAM_ADDR_INVALID); + assert(mr->ram_block); - return qemu_get_ram_fd(mr->ram_addr & TARGET_PAGE_MASK); + return qemu_get_ram_fd(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); } void *memory_region_get_ram_ptr(MemoryRegion *mr) @@ -1633,8 +1615,9 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) offset += mr->alias_offset; mr = mr->alias; } - assert(mr->ram_addr != RAM_ADDR_INVALID); - ptr = qemu_get_ram_ptr(mr->ram_block, mr->ram_addr & TARGET_PAGE_MASK); + assert(mr->ram_block); + ptr = qemu_get_ram_ptr(mr->ram_block, + memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); rcu_read_unlock(); return ptr + offset; @@ -1647,9 +1630,9 @@ ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr) void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp) { - assert(mr->ram_addr != RAM_ADDR_INVALID); + assert(mr->ram_block); - qemu_ram_resize(mr->ram_addr, newsize, errp); + qemu_ram_resize(memory_region_get_ram_addr(mr), newsize, errp); } static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as) diff --git a/scripts/dump-guest-memory.py b/scripts/dump-guest-memory.py index f274bf80fa..c0a2e99f46 100644 --- a/scripts/dump-guest-memory.py +++ b/scripts/dump-guest-memory.py @@ -352,7 +352,7 @@ def memory_region_get_ram_ptr(memory_region): return (memory_region_get_ram_ptr(memory_region["alias"].dereference()) + memory_region["alias_offset"]) - return qemu_get_ram_ptr(memory_region["ram_addr"] & TARGET_PAGE_MASK) + return qemu_get_ram_ptr(memory_region["ram_block"]["offset"]) def get_guest_phys_blocks(): From f1060c55bf1377b499affc8d022378d936f0bd99 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 1 Mar 2016 14:18:22 +0800 Subject: [PATCH 07/15] exec: Pass RAMBlock pointer to qemu_ram_free The only caller now knows exactly which RAMBlock to free, so it's not necessary to do the lookup. Reviewed-by: Gonglei Signed-off-by: Fam Zheng Message-Id: <1456813104-25902-6-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- exec.c | 21 +++++++-------------- include/exec/ram_addr.h | 2 +- memory.c | 4 ++-- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/exec.c b/exec.c index 6ed4203b97..ad8b826bc1 100644 --- a/exec.c +++ b/exec.c @@ -1751,22 +1751,15 @@ static void reclaim_ramblock(RAMBlock *block) g_free(block); } -void qemu_ram_free(ram_addr_t addr) +void qemu_ram_free(RAMBlock *block) { - RAMBlock *block; - qemu_mutex_lock_ramlist(); - QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { - if (addr == block->offset) { - QLIST_REMOVE_RCU(block, next); - ram_list.mru_block = NULL; - /* Write list before version */ - smp_wmb(); - ram_list.version++; - call_rcu(block, reclaim_ramblock, rcu); - break; - } - } + QLIST_REMOVE_RCU(block, next); + ram_list.mru_block = NULL; + /* Write list before version */ + smp_wmb(); + ram_list.version++; + call_rcu(block, reclaim_ramblock, rcu); qemu_mutex_unlock_ramlist(); } diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 865e19b8ac..5adf7a4fcd 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -108,7 +108,7 @@ RAMBlock *qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size, int qemu_get_ram_fd(ram_addr_t addr); void qemu_set_ram_fd(ram_addr_t addr, int fd); void *qemu_get_ram_block_host_ptr(ram_addr_t addr); -void qemu_ram_free(ram_addr_t addr); +void qemu_ram_free(RAMBlock *block); int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp); diff --git a/memory.c b/memory.c index 5b5791caf4..9f5c4584d1 100644 --- a/memory.c +++ b/memory.c @@ -902,12 +902,12 @@ static void memory_region_destructor_none(MemoryRegion *mr) static void memory_region_destructor_ram(MemoryRegion *mr) { - qemu_ram_free(memory_region_get_ram_addr(mr)); + qemu_ram_free(mr->ram_block); } static void memory_region_destructor_rom_device(MemoryRegion *mr) { - qemu_ram_free(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); + qemu_ram_free(mr->ram_block); } static bool memory_region_need_escape(char c) From 29cb533d8cbff1330717619780c2f1dfe764e003 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 1 Mar 2016 14:18:23 +0800 Subject: [PATCH 08/15] exec: Factor out section_covers_addr This will be shared by the next patch. Also add a comment explaining the unobvious condition on "size.hi". Signed-off-by: Fam Zheng Message-Id: <1456813104-25902-7-git-send-email-famz@redhat.com> [Small change to the comment. - Paolo] Signed-off-by: Paolo Bonzini --- exec.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/exec.c b/exec.c index ad8b826bc1..9279af5eab 100644 --- a/exec.c +++ b/exec.c @@ -307,6 +307,17 @@ static void phys_page_compact_all(AddressSpaceDispatch *d, int nodes_nb) } } +static inline bool section_covers_addr(const MemoryRegionSection *section, + hwaddr addr) +{ + /* Memory topology clips a memory region to [0, 2^64); size.hi > 0 means + * the section must cover the entire address space. + */ + return section->size.hi || + range_covers_byte(section->offset_within_address_space, + section->size.lo, addr); +} + static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr addr, Node *nodes, MemoryRegionSection *sections) { @@ -322,9 +333,7 @@ static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr addr, lp = p[(index >> (i * P_L2_BITS)) & (P_L2_SIZE - 1)]; } - if (sections[lp.ptr].size.hi || - range_covers_byte(sections[lp.ptr].offset_within_address_space, - sections[lp.ptr].size.lo, addr)) { + if (section_covers_addr(§ions[lp.ptr], addr)) { return §ions[lp.ptr]; } else { return §ions[PHYS_SECTION_UNASSIGNED]; From 729633c2bc30496073431584eb6e304776b4ebd4 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Tue, 1 Mar 2016 14:18:24 +0800 Subject: [PATCH 09/15] exec: Introduce AddressSpaceDispatch.mru_section Under heavy workloads the lookup will likely end up with the same MemoryRegionSection from last time. Using a pointer to cache the result, like ram_list.mru_block, significantly reduces cost of address_space_translate. During address space topology update, as->dispatch will be reallocated so the pointer is invalidated automatically. Perf reports a visible drop on the cpu usage, because phys_page_find is not called. Before: 2.35% qemu-system-x86_64 [.] phys_page_find 0.97% qemu-system-x86_64 [.] address_space_translate_internal 0.95% qemu-system-x86_64 [.] address_space_translate 0.55% qemu-system-x86_64 [.] address_space_lookup_region After: 0.97% qemu-system-x86_64 [.] address_space_translate_internal 0.97% qemu-system-x86_64 [.] address_space_lookup_region 0.84% qemu-system-x86_64 [.] address_space_translate Signed-off-by: Fam Zheng Message-Id: <1456813104-25902-8-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- exec.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/exec.c b/exec.c index 9279af5eab..f09dd4e928 100644 --- a/exec.c +++ b/exec.c @@ -135,6 +135,7 @@ typedef struct PhysPageMap { struct AddressSpaceDispatch { struct rcu_head rcu; + MemoryRegionSection *mru_section; /* This is a multi-level map on the physical address space. * The bottom level has pointers to MemoryRegionSections. */ @@ -351,14 +352,25 @@ static MemoryRegionSection *address_space_lookup_region(AddressSpaceDispatch *d, hwaddr addr, bool resolve_subpage) { - MemoryRegionSection *section; + MemoryRegionSection *section = atomic_read(&d->mru_section); subpage_t *subpage; + bool update; - section = phys_page_find(d->phys_map, addr, d->map.nodes, d->map.sections); + if (section && section != &d->map.sections[PHYS_SECTION_UNASSIGNED] && + section_covers_addr(section, addr)) { + update = false; + } else { + section = phys_page_find(d->phys_map, addr, d->map.nodes, + d->map.sections); + update = true; + } if (resolve_subpage && section->mr->subpage) { subpage = container_of(section->mr, subpage_t, iomem); section = &d->map.sections[subpage->sub_section[SUBPAGE_IDX(addr)]]; } + if (update) { + atomic_set(&d->mru_section, section); + } return section; } From 778d9f9b25dc563252fa6187e23fe6e7d16b5a99 Mon Sep 17 00:00:00 2001 From: Pranith Kumar Date: Fri, 26 Feb 2016 10:16:51 -0500 Subject: [PATCH 10/15] icount: possible options for sleep are on or off icount sleep takes on or off as options. A few places mention sleep=no which is not accepted. This patch corrects them. Signed-off-by: Pranith Kumar Message-Id: <1456499811-16819-1-git-send-email-bobby.prani@gmail.com> Signed-off-by: Paolo Bonzini --- cpus.c | 4 ++-- qemu-options.hx | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cpus.c b/cpus.c index 9592163ff4..bc774e2540 100644 --- a/cpus.c +++ b/cpus.c @@ -630,7 +630,7 @@ void configure_icount(QemuOpts *opts, Error **errp) icount_align_option = qemu_opt_get_bool(opts, "align", false); if (icount_align_option && !icount_sleep) { - error_setg(errp, "align=on and sleep=no are incompatible"); + error_setg(errp, "align=on and sleep=off are incompatible"); } if (strcmp(option, "auto") != 0) { errno = 0; @@ -643,7 +643,7 @@ void configure_icount(QemuOpts *opts, Error **errp) } else if (icount_align_option) { error_setg(errp, "shift=auto and align=on are incompatible"); } else if (!icount_sleep) { - error_setg(errp, "shift=auto and sleep=no are incompatible"); + error_setg(errp, "shift=auto and sleep=off are incompatible"); } use_icount = 2; diff --git a/qemu-options.hx b/qemu-options.hx index 144e6a9b76..2aa6577c14 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3276,7 +3276,7 @@ re-inject them. ETEXI DEF("icount", HAS_ARG, QEMU_OPTION_icount, \ - "-icount [shift=N|auto][,align=on|off][,sleep=no,rr=record|replay,rrfile=]\n" \ + "-icount [shift=N|auto][,align=on|off][,sleep=on|off,rr=record|replay,rrfile=]\n" \ " enable virtual instruction counter with 2^N clock ticks per\n" \ " instruction, enable aligning the host and virtual clocks\n" \ " or disable real time cpu sleeping\n", QEMU_ARCH_ALL) @@ -3289,8 +3289,8 @@ then the virtual cpu speed will be automatically adjusted to keep virtual time within a few seconds of real time. When the virtual cpu is sleeping, the virtual time will advance at default -speed unless @option{sleep=no} is specified. -With @option{sleep=no}, the virtual time will jump to the next timer deadline +speed unless @option{sleep=on|off} is specified. +With @option{sleep=on|off}, the virtual time will jump to the next timer deadline instantly whenever the virtual cpu goes to sleep mode and will not advance if no timer is enabled. This behavior give deterministic execution times from the guest point of view. From 8210f5f6f52159b0d3a27ffe4af97056ac44cba8 Mon Sep 17 00:00:00 2001 From: xiaoqiang zhao Date: Fri, 26 Feb 2016 16:40:51 +0800 Subject: [PATCH 11/15] doc/memory.txt: correct a logic error In the regions overlap example, region B has a higher priority thus should has a larger priority number than C. Signed-off-by: xiaoqiang zhao Message-Id: <1456476051-15121-1-git-send-email-zxq_yx_007@163.com> Signed-off-by: Paolo Bonzini --- docs/memory.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/memory.txt b/docs/memory.txt index 8745f7603f..d0aca0529e 100644 --- a/docs/memory.txt +++ b/docs/memory.txt @@ -180,8 +180,8 @@ aliases that leave holes then the lower priority region will appear in these holes too.) For example, suppose we have a container A of size 0x8000 with two subregions -B and C. B is a container mapped at 0x2000, size 0x4000, priority 1; C is -an MMIO region mapped at 0x0, size 0x6000, priority 2. B currently has two +B and C. B is a container mapped at 0x2000, size 0x4000, priority 2; C is +an MMIO region mapped at 0x0, size 0x6000, priority 1. B currently has two of its own subregions: D of size 0x1000 at offset 0 and E of size 0x1000 at offset 0x2000. As a diagram: From ef00bdaf8c843be61737178707d8eaee6541733b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 26 Feb 2016 16:40:51 +0800 Subject: [PATCH 12/15] doc/memory.txt: correct description of MemoryRegionOps fields Probably what happened was that when the API was being designed it started off with an 'aligned' field, and then later the field name and semantics were changed but the docs weren't updated to match. Similarly, cpu_register_io_memory() does not exist anymore, so clarify the documentation for .old_mmio. Reported-by: Cao jin Signed-off-by: Peter Maydell Signed-off-by: Paolo Bonzini --- docs/memory.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/memory.txt b/docs/memory.txt index d0aca0529e..97134e14c7 100644 --- a/docs/memory.txt +++ b/docs/memory.txt @@ -297,8 +297,9 @@ various constraints can be supplied to control how these callbacks are called: - .valid.min_access_size, .valid.max_access_size define the access sizes (in bytes) which the device accepts; accesses outside this range will have device and bus specific behaviour (ignored, or machine check) - - .valid.aligned specifies that the device only accepts naturally aligned - accesses. Unaligned accesses invoke device and bus specific behaviour. + - .valid.unaligned specifies that the *device being modelled* supports + unaligned accesses; if false, unaligned accesses will invoke the + appropriate bus or CPU specific behaviour. - .impl.min_access_size, .impl.max_access_size define the access sizes (in bytes) supported by the *implementation*; other access sizes will be emulated using the ones available. For example a 4-byte write will be @@ -306,5 +307,5 @@ various constraints can be supplied to control how these callbacks are called: - .impl.unaligned specifies that the *implementation* supports unaligned accesses; if false, unaligned accesses will be emulated by two aligned accesses. - - .old_mmio can be used to ease porting from code using + - .old_mmio eases the porting of code that was formerly using cpu_register_io_memory(). It should not be used in new code. From a95e9a485b0230255aec1c9b53f2bd4612febdce Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 25 Feb 2016 13:33:25 +0100 Subject: [PATCH 13/15] MAINTAINERS: Add entry for include/sysemu/kvm*.h The include/sysemu/kvm*.h header files should be part of the overall KVM section. Signed-off-by: Thomas Huth Message-Id: <1456403605-26587-1-git-send-email-thuth@redhat.com> Signed-off-by: Paolo Bonzini --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 2f5a338218..9d0255c72c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -234,6 +234,7 @@ L: kvm@vger.kernel.org S: Supported F: kvm-* F: */kvm.* +F: include/sysemu/kvm*.h ARM M: Peter Maydell From 8269fb7082f49b5facddbbe1072bc382b2741add Mon Sep 17 00:00:00 2001 From: Wei Yang Date: Sun, 6 Mar 2016 01:57:25 +0000 Subject: [PATCH 14/15] kvm/irqchip: use bitmap utility for gsi tracking By using utilities in bitops and bitmap, this patch tries to make it more friendly to audience. No functional change. Signed-off-by: Wei Yang Message-Id: <1457229445-25954-1-git-send-email-richard.weiyang@gmail.com> Signed-off-by: Paolo Bonzini --- kvm-all.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/kvm-all.c b/kvm-all.c index 161200edb0..44c0464261 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -89,7 +89,7 @@ struct KVMState #ifdef KVM_CAP_IRQ_ROUTING struct kvm_irq_routing *irq_routes; int nr_allocated_irq_routes; - uint32_t *used_gsi_bitmap; + unsigned long *used_gsi_bitmap; unsigned int gsi_count; QTAILQ_HEAD(msi_hashtab, KVMMSIRoute) msi_hashtab[KVM_MSI_HASHTAB_SIZE]; #endif @@ -951,12 +951,12 @@ typedef struct KVMMSIRoute { static void set_gsi(KVMState *s, unsigned int gsi) { - s->used_gsi_bitmap[gsi / 32] |= 1U << (gsi % 32); + set_bit(gsi, s->used_gsi_bitmap); } static void clear_gsi(KVMState *s, unsigned int gsi) { - s->used_gsi_bitmap[gsi / 32] &= ~(1U << (gsi % 32)); + clear_bit(gsi, s->used_gsi_bitmap); } void kvm_init_irq_routing(KVMState *s) @@ -965,17 +965,9 @@ void kvm_init_irq_routing(KVMState *s) gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING) - 1; if (gsi_count > 0) { - unsigned int gsi_bits, i; - /* Round up so we can search ints using ffs */ - gsi_bits = ALIGN(gsi_count, 32); - s->used_gsi_bitmap = g_malloc0(gsi_bits / 8); + s->used_gsi_bitmap = bitmap_new(gsi_count); s->gsi_count = gsi_count; - - /* Mark any over-allocated bits as already in use */ - for (i = gsi_count; i < gsi_bits; i++) { - set_gsi(s, i); - } } s->irq_routes = g_malloc0(sizeof(*s->irq_routes)); @@ -1105,9 +1097,7 @@ static void kvm_flush_dynamic_msi_routes(KVMState *s) static int kvm_irqchip_get_virq(KVMState *s) { - uint32_t *word = s->used_gsi_bitmap; - int max_words = ALIGN(s->gsi_count, 32) / 32; - int i, zeroes; + int next_virq; /* * PIC and IOAPIC share the first 16 GSI numbers, thus the available @@ -1120,16 +1110,12 @@ static int kvm_irqchip_get_virq(KVMState *s) } /* Return the lowest unused GSI in the bitmap */ - for (i = 0; i < max_words; i++) { - zeroes = ctz32(~word[i]); - if (zeroes == 32) { - continue; - } - - return zeroes + i * 32; + next_virq = find_first_zero_bit(s->used_gsi_bitmap, s->gsi_count); + if (next_virq >= s->gsi_count) { + return -ENOSPC; + } else { + return next_virq; } - return -ENOSPC; - } static KVMMSIRoute *kvm_lookup_msi_route(KVMState *s, MSIMessage msg) From 4792b7e9d5254daa383cb38d60d79c2b000ca9fc Mon Sep 17 00:00:00 2001 From: Alex Pyrgiotis Date: Mon, 7 Mar 2016 15:50:22 +0000 Subject: [PATCH 15/15] scsi-bus: Remove tape command from scsi_req_xfer Remove the RECOVER_BUFFERED_DATA command from the list of commands that are handled by scsi_req_xfer(). Given that this command is tape-specific, it should be handled only by scsi_stream_req_xfer(). Signed-off-by: Alex Pyrgiotis Message-Id: <1457365822-22435-1-git-send-email-apyrgio@arrikto.com> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 6dcdbc0508..a21752b67e 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -989,7 +989,6 @@ static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf) } /* fall through */ case READ_10: - case RECOVER_BUFFERED_DATA: case READ_12: case READ_16: cmd->xfer *= dev->blocksize;