From d2f39add725e2be849f5fb014a72368f711056fc Mon Sep 17 00:00:00 2001 From: Dominik Dingel Date: Mon, 25 Apr 2016 13:55:38 +0200 Subject: [PATCH 01/24] exec.c: Ensure right alignment also for file backed ram While in the anonymous ram case we already take care of the right alignment such an alignment gurantee does not exist for file backed ram allocation. Instead, pagesize is used for alignment. On s390 this is not enough for gmap, as we need to satisfy an alignment up to segments. Reported-by: Halil Pasic Signed-off-by: Dominik Dingel Message-Id: <1461585338-45863-1-git-send-email-dingel@linux.vnet.ibm.com> Signed-off-by: Paolo Bonzini --- exec.c | 5 +++-- include/qemu/osdep.h | 13 +++++++++++++ util/oslib-posix.c | 13 ------------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/exec.c b/exec.c index 2e363f06a6..59aed17828 100644 --- a/exec.c +++ b/exec.c @@ -1299,7 +1299,7 @@ static void *file_ram_alloc(RAMBlock *block, } page_size = qemu_fd_getpagesize(fd); - block->mr->align = page_size; + block->mr->align = MAX(page_size, QEMU_VMALLOC_ALIGN); if (memory < page_size) { error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to " @@ -1320,7 +1320,8 @@ static void *file_ram_alloc(RAMBlock *block, perror("ftruncate"); } - area = qemu_ram_mmap(fd, memory, page_size, block->flags & RAM_SHARED); + area = qemu_ram_mmap(fd, memory, block->mr->align, + block->flags & RAM_SHARED); if (area == MAP_FAILED) { error_setg_errno(errp, errno, "unable to map backing store for guest RAM"); diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h index 268ec66958..994bfa023a 100644 --- a/include/qemu/osdep.h +++ b/include/qemu/osdep.h @@ -263,6 +263,19 @@ void qemu_anon_ram_free(void *ptr, size_t size); #endif +#if defined(__linux__) && \ + (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)) + /* Use 2 MiB alignment so transparent hugepages can be used by KVM. + Valgrind does not support alignments larger than 1 MiB, + therefore we need special code which handles running on Valgrind. */ +# define QEMU_VMALLOC_ALIGN (512 * 4096) +#elif defined(__linux__) && defined(__s390x__) + /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ +# define QEMU_VMALLOC_ALIGN (256 * 4096) +#else +# define QEMU_VMALLOC_ALIGN getpagesize() +#endif + int qemu_madvise(void *addr, size_t len, int advice); int qemu_open(const char *name, int flags, ...); diff --git a/util/oslib-posix.c b/util/oslib-posix.c index 6cc4b8f001..4adde93ac1 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -26,19 +26,6 @@ * THE SOFTWARE. */ -#if defined(__linux__) && \ - (defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)) - /* Use 2 MiB alignment so transparent hugepages can be used by KVM. - Valgrind does not support alignments larger than 1 MiB, - therefore we need special code which handles running on Valgrind. */ -# define QEMU_VMALLOC_ALIGN (512 * 4096) -#elif defined(__linux__) && defined(__s390x__) - /* Use 1 MiB (segment size) alignment so gmap can be used by KVM. */ -# define QEMU_VMALLOC_ALIGN (256 * 4096) -#else -# define QEMU_VMALLOC_ALIGN getpagesize() -#endif - #include "qemu/osdep.h" #include #include From dfc007f7f7aab982a8c22cbcb783d72b0db99705 Mon Sep 17 00:00:00 2001 From: Pranith Kumar Date: Mon, 2 May 2016 10:20:52 -0400 Subject: [PATCH 02/24] docs/atomics.txt: Update pointer to linux macro Add a missing end brace and update doc to point to the latest access macro. ACCESS_ONCE() is deprecated. Signed-off-by: Pranith Kumar Message-Id: <1462198852-28694-1-git-send-email-bobby.prani@gmail.com> Signed-off-by: Paolo Bonzini --- docs/atomics.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/atomics.txt b/docs/atomics.txt index ef285e3c2a..bba771ecd6 100644 --- a/docs/atomics.txt +++ b/docs/atomics.txt @@ -62,7 +62,7 @@ operations: typeof(*ptr) atomic_fetch_sub(ptr, val) typeof(*ptr) atomic_fetch_and(ptr, val) typeof(*ptr) atomic_fetch_or(ptr, val) - typeof(*ptr) atomic_xchg(ptr, val + typeof(*ptr) atomic_xchg(ptr, val) typeof(*ptr) atomic_cmpxchg(ptr, old, new) all of which return the old value of *ptr. These operations are @@ -328,7 +328,7 @@ and memory barriers, and the equivalents in QEMU: - atomic_read and atomic_set in Linux give no guarantee at all; atomic_read and atomic_set in QEMU include a compiler barrier - (similar to the ACCESS_ONCE macro in Linux). + (similar to the READ_ONCE/WRITE_ONCE macros in Linux). - most atomic read-modify-write operations in Linux return void; in QEMU, all of them return the old value of the variable. From 691a02e2ce0c413236a78dee6f2651c937b09fb0 Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Thu, 7 Apr 2016 12:50:08 +0530 Subject: [PATCH 03/24] i386: kvmvapic: initialise imm32 variable When processing Task Priorty Register(TPR) access, it could leak automatic stack variable 'imm32' in patch_instruction(). Initialise the variable to avoid it. Reported by: Donghai Zdh Cc: qemu-stable@nongnu.org Signed-off-by: Prasad J Pandit Message-Id: <1460013608-16670-1-git-send-email-ppandit@redhat.com> Signed-off-by: Paolo Bonzini --- hw/i386/kvmvapic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index 8fd27ba2f4..5b71b1ba46 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -397,7 +397,7 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip) CPUX86State *env = &cpu->env; VAPICHandlers *handlers; uint8_t opcode[2]; - uint32_t imm32; + uint32_t imm32 = 0; target_ulong current_pc = 0; target_ulong current_cs_base = 0; uint32_t current_flags = 0; From 5919e0328b7d6a08a661c3c747bae3e841d4e6f4 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 28 Apr 2016 23:33:41 +0200 Subject: [PATCH 04/24] configure: Allow builds with extra warnings The clang compiler supports a useful compiler option -Weverything, and GCC also has other warnings not enabled by -Wall. If glib header files trigger a warning, however, testing glib with -Werror will always fail. A size mismatch is also detected without -Werror, so simply remove it. Cc: qemu-stable@nongnu.org Signed-off-by: Stefan Weil Message-Id: <1461879221-13338-1-git-send-email-sw@weilnetz.de> Signed-off-by: Paolo Bonzini --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 293639cf6d..b5aab7257b 100755 --- a/configure +++ b/configure @@ -2985,7 +2985,7 @@ int main(void) { } EOF -if ! compile_prog "-Werror $CFLAGS" "$LIBS" ; then +if ! compile_prog "$CFLAGS" "$LIBS" ; then error_exit "sizeof(size_t) doesn't match GLIB_SIZEOF_SIZE_T."\ "You probably need to set PKG_CONFIG_LIBDIR"\ "to point to the right pkg-config files for your"\ From 14cb949a3e2efd64ea3271b919b33b452ce7b180 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 16 May 2016 11:11:29 +0200 Subject: [PATCH 05/24] target-i386: key sfence availability on CPUID_SSE, not CPUID_SSE2 sfence was introduced before lfence and mfence. This fixes Linux 2.4's measurement of checksumming speeds for the pIII_sse algorithm: md: linear personality registered as nr 1 md: raid0 personality registered as nr 2 md: raid1 personality registered as nr 3 md: raid5 personality registered as nr 4 raid5: measuring checksumming speed 8regs : 384.400 MB/sec 32regs : 259.200 MB/sec invalid operand: 0000 CPU: 0 EIP: 0010:[] Not tainted EFLAGS: 00000246 eax: c15d8000 ebx: 00000000 ecx: 00000000 edx: c15d5000 esi: 8005003b edi: 00000004 ebp: 00000000 esp: c15bdf50 ds: 0018 es: 0018 ss: 0018 Process swapper (pid: 1, stackpage=c15bd000) Stack: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000206 c0241c6c 00001000 c15d4000 c15d7000 c15d4000 c15d4000 Call Trace: [] [] [] [] [] [] [] Code: 0f ae f8 0f 10 04 24 0f 10 4c 24 10 0f 10 54 24 20 0f 10 5c <0>Kernel panic: Attempted to kill init! Reported-by: Stefan Weil Fixes: 121f3157887f92268a3d6169e2d4601f9292020b Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini --- target-i386/translate.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target-i386/translate.c b/target-i386/translate.c index 8085467945..731b10de06 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -8008,6 +8008,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s, } /* fallthru */ case 0xf9 ... 0xff: /* sfence */ + if (!(s->cpuid_features & CPUID_SSE) + || (prefixes & PREFIX_LOCK)) { + goto illegal_op; + } + break; case 0xe8 ... 0xef: /* lfence */ case 0xf0 ... 0xf7: /* mfence */ if (!(s->cpuid_features & CPUID_SSE2) From 479c2a1cb7fb82d23e66eab78b00fc5b0638439b Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 10 May 2016 18:21:21 +0800 Subject: [PATCH 06/24] ioapic: keep RO bits for IOAPIC entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently IOAPIC RO bits can be written. To be better aligned with hardware, we should let them read-only. Reviewed-by: Radim Krčmář Signed-off-by: Peter Xu Message-Id: <1462875682-1349-2-git-send-email-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- hw/intc/ioapic.c | 4 ++++ include/hw/i386/ioapic_internal.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index 4f42b911a2..c27ee83722 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -281,6 +281,7 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, default: index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1; if (index >= 0 && index < IOAPIC_NUM_PINS) { + uint64_t ro_bits = s->ioredtbl[index] & IOAPIC_RO_BITS; if (s->ioregsel & 1) { s->ioredtbl[index] &= 0xffffffff; s->ioredtbl[index] |= (uint64_t)val << 32; @@ -288,6 +289,9 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, s->ioredtbl[index] &= ~0xffffffffULL; s->ioredtbl[index] |= val; } + /* restore RO bits */ + s->ioredtbl[index] &= IOAPIC_RW_BITS; + s->ioredtbl[index] |= ro_bits; ioapic_service(s); } } diff --git a/include/hw/i386/ioapic_internal.h b/include/hw/i386/ioapic_internal.h index 797ed47305..cab9e67ee7 100644 --- a/include/hw/i386/ioapic_internal.h +++ b/include/hw/i386/ioapic_internal.h @@ -47,6 +47,11 @@ #define IOAPIC_LVT_DEST_MODE (1 << IOAPIC_LVT_DEST_MODE_SHIFT) #define IOAPIC_LVT_DELIV_MODE (7 << IOAPIC_LVT_DELIV_MODE_SHIFT) +/* Bits that are read-only for IOAPIC entry */ +#define IOAPIC_RO_BITS (IOAPIC_LVT_REMOTE_IRR | \ + IOAPIC_LVT_DELIV_STATUS) +#define IOAPIC_RW_BITS (~(uint64_t)IOAPIC_RO_BITS) + #define IOAPIC_TRIGGER_EDGE 0 #define IOAPIC_TRIGGER_LEVEL 1 From ed1263c363c970a7ad5226b8f41dbbf0c92c1e17 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Tue, 10 May 2016 18:21:22 +0800 Subject: [PATCH 07/24] ioapic: clear remote irr bit for edge-triggered interrupts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to better emulate IOAPIC version 0x1X hardware. Linux kernel leveraged this "feature" to do explicit EOI since EOI register is still not introduced at that time. This will also fix the issue that level triggered interrupts failed to work when IR enabled (tested with Linux kernel version 4.5). Reviewed-by: Radim Krčmář Signed-off-by: Peter Xu Message-Id: <1462875682-1349-3-git-send-email-peterx@redhat.com> Signed-off-by: Paolo Bonzini --- hw/intc/ioapic.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index c27ee83722..273bb0854c 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -255,6 +255,34 @@ ioapic_mem_read(void *opaque, hwaddr addr, unsigned int size) return val; } +/* + * This is to satisfy the hack in Linux kernel. One hack of it is to + * simulate clearing the Remote IRR bit of IOAPIC entry using the + * following: + * + * "For IO-APIC's with EOI register, we use that to do an explicit EOI. + * Otherwise, we simulate the EOI message manually by changing the trigger + * mode to edge and then back to level, with RTE being masked during + * this." + * + * (See linux kernel __eoi_ioapic_pin() comment in commit c0205701) + * + * This is based on the assumption that, Remote IRR bit will be + * cleared by IOAPIC hardware when configured as edge-triggered + * interrupts. + * + * Without this, level-triggered interrupts in IR mode might fail to + * work correctly. + */ +static inline void +ioapic_fix_edge_remote_irr(uint64_t *entry) +{ + if (!(*entry & IOAPIC_LVT_TRIGGER_MODE)) { + /* Edge-triggered interrupts, make sure remote IRR is zero */ + *entry &= ~((uint64_t)IOAPIC_LVT_REMOTE_IRR); + } +} + static void ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) @@ -292,6 +320,7 @@ ioapic_mem_write(void *opaque, hwaddr addr, uint64_t val, /* restore RO bits */ s->ioredtbl[index] &= IOAPIC_RW_BITS; s->ioredtbl[index] |= ro_bits; + ioapic_fix_edge_remote_irr(&s->ioredtbl[index]); ioapic_service(s); } } From e92a2d9cb3d8f589c9fe5d2eacc83d8dddea0e16 Mon Sep 17 00:00:00 2001 From: Li Zhijian Date: Thu, 14 Apr 2016 11:25:52 +0800 Subject: [PATCH 08/24] vl: change runstate only if new state is different from current state Previously, qemu will abort at following scenario: (qemu) stop (qemu) system_reset (qemu) system_reset (qemu) 2016-04-13T20:54:38.979158Z qemu-system-x86_64: invalid runstate transition: 'prelaunch' -> 'prelaunch' Signed-off-by: Li Zhijian Acked-by: Paolo Bonzini Message-Id: <1460604352-18630-1-git-send-email-lizhijian@cn.fujitsu.com> Cc: qemu-stable@nongnu.org Signed-off-by: Paolo Bonzini --- vl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vl.c b/vl.c index b1562d8280..2569dbb8d8 100644 --- a/vl.c +++ b/vl.c @@ -690,6 +690,10 @@ void runstate_set(RunState new_state) { assert(new_state < RUN_STATE__MAX); + if (current_run_state == new_state) { + return; + } + if (!runstate_valid_transitions[current_run_state][new_state]) { error_report("invalid runstate transition: '%s' -> '%s'", RunState_lookup[current_run_state], From fa53a0e53efdc7002497ea4a76aacf6cceb170ef Mon Sep 17 00:00:00 2001 From: Gonglei Date: Tue, 10 May 2016 10:04:59 +0800 Subject: [PATCH 09/24] memory: drop find_ram_block() On the one hand, we have already qemu_get_ram_block() whose function is similar. On the other hand, we can directly use mr->ram_block but searching RAMblock by ram_addr which is a kind of waste. Signed-off-by: Gonglei Reviewed-by: Fam Zheng Message-Id: <1462845901-89716-2-git-send-email-arei.gonglei@huawei.com> Signed-off-by: Paolo Bonzini --- exec.c | 34 +++++++--------------------------- include/exec/cpu-common.h | 4 ++-- include/exec/ram_addr.h | 2 +- memory.c | 2 +- migration/ram.c | 2 +- migration/savevm.c | 4 ++-- 6 files changed, 14 insertions(+), 34 deletions(-) diff --git a/exec.c b/exec.c index 59aed17828..e2966ce6c4 100644 --- a/exec.c +++ b/exec.c @@ -1411,34 +1411,18 @@ static void qemu_ram_setup_dump(void *addr, ram_addr_t size) } } -/* Called within an RCU critical section, or while the ramlist lock - * is held. - */ -static RAMBlock *find_ram_block(ram_addr_t addr) -{ - RAMBlock *block; - - QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { - if (block->offset == addr) { - return block; - } - } - - return NULL; -} - const char *qemu_ram_get_idstr(RAMBlock *rb) { return rb->idstr; } /* Called with iothread lock held. */ -void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) +void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev) { - RAMBlock *new_block, *block; + RAMBlock *block; rcu_read_lock(); - new_block = find_ram_block(addr); + assert(new_block); assert(!new_block->idstr[0]); @@ -1452,7 +1436,8 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) pstrcat(new_block->idstr, sizeof(new_block->idstr), name); QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { - if (block != new_block && !strcmp(block->idstr, new_block->idstr)) { + if (block != new_block && + !strcmp(block->idstr, new_block->idstr)) { fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", new_block->idstr); abort(); @@ -1462,17 +1447,14 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) } /* Called with iothread lock held. */ -void qemu_ram_unset_idstr(ram_addr_t addr) +void qemu_ram_unset_idstr(RAMBlock *block) { - RAMBlock *block; - /* FIXME: arch_init.c assumes that this is not called throughout * migration. Ignore the problem since hot-unplug during migration * does not work anyway. */ rcu_read_lock(); - block = find_ram_block(addr); if (block) { memset(block->idstr, 0, sizeof(block->idstr)); } @@ -1496,10 +1478,8 @@ static int memory_try_enable_merging(void *addr, size_t len) * resize callback to update device state and/or add assertions to detect * misuse, if necessary. */ -int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp) +int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp) { - RAMBlock *block = find_ram_block(base); - assert(block); newsize = HOST_PAGE_ALIGN(newsize); diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 04eade5b7b..a2c3b92742 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -61,8 +61,8 @@ MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); RAMBlock *qemu_ram_block_by_name(const char *name); RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, ram_addr_t *ram_addr, ram_addr_t *offset); -void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev); -void qemu_ram_unset_idstr(ram_addr_t addr); +void qemu_ram_set_idstr(RAMBlock *block, const char *name, DeviceState *dev); +void qemu_ram_unset_idstr(RAMBlock *block); const char *qemu_ram_get_idstr(RAMBlock *rb); void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 5adf7a4fcd..5b6e1b8b86 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -110,7 +110,7 @@ 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(RAMBlock *block); -int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp); +int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp); #define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1) #define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE)) diff --git a/memory.c b/memory.c index a8ef85261f..9daac5ea2d 100644 --- a/memory.c +++ b/memory.c @@ -1673,7 +1673,7 @@ void memory_region_ram_resize(MemoryRegion *mr, ram_addr_t newsize, Error **errp { assert(mr->ram_block); - qemu_ram_resize(memory_region_get_ram_addr(mr), newsize, errp); + qemu_ram_resize(mr->ram_block, newsize, errp); } static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as) diff --git a/migration/ram.c b/migration/ram.c index 5e88080faf..6b6900e4c1 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -2478,7 +2478,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) if (length != block->used_length) { Error *local_err = NULL; - ret = qemu_ram_resize(block->offset, length, + ret = qemu_ram_resize(block, length, &local_err); if (local_err) { error_report_err(local_err); diff --git a/migration/savevm.c b/migration/savevm.c index bfb3d9178f..9bc362a1d3 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -2229,13 +2229,13 @@ void hmp_info_snapshots(Monitor *mon, const QDict *qdict) void vmstate_register_ram(MemoryRegion *mr, DeviceState *dev) { - qemu_ram_set_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK, + qemu_ram_set_idstr(mr->ram_block, memory_region_name(mr), dev); } void vmstate_unregister_ram(MemoryRegion *mr, DeviceState *dev) { - qemu_ram_unset_idstr(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); + qemu_ram_unset_idstr(mr->ram_block); } void vmstate_register_ram_global(MemoryRegion *mr) From ab0a99560857302b60053c245d1231acbd976cd4 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Tue, 10 May 2016 10:05:00 +0800 Subject: [PATCH 10/24] exec: adjust rcu_read_lock requirement qemu_ram_unset_idstr() doesn't need rcu lock anymore, meanwhile make the range of rcu lock in qemu_ram_set_idstr() as small as possible. Signed-off-by: Gonglei Message-Id: <1462845901-89716-3-git-send-email-arei.gonglei@huawei.com> Signed-off-by: Paolo Bonzini --- exec.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/exec.c b/exec.c index e2966ce6c4..8cf535ddde 100644 --- a/exec.c +++ b/exec.c @@ -1421,8 +1421,6 @@ void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev) { RAMBlock *block; - rcu_read_lock(); - assert(new_block); assert(!new_block->idstr[0]); @@ -1435,6 +1433,7 @@ void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev) } pstrcat(new_block->idstr, sizeof(new_block->idstr), name); + rcu_read_lock(); QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { if (block != new_block && !strcmp(block->idstr, new_block->idstr)) { @@ -1453,12 +1452,9 @@ void qemu_ram_unset_idstr(RAMBlock *block) * migration. Ignore the problem since hot-unplug during migration * does not work anyway. */ - - rcu_read_lock(); if (block) { memset(block->idstr, 0, sizeof(block->idstr)); } - rcu_read_unlock(); } static int memory_try_enable_merging(void *addr, size_t len) From b61359781958759317ee6fd1a45b59be0b7dbbe1 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Fri, 25 Mar 2016 18:10:28 +0800 Subject: [PATCH 11/24] memory: Remove code for mr->may_overlap The collision check does nothing and hasn't been used. Remove the variable together with related code. Signed-off-by: Fam Zheng Message-Id: <1458900629-2334-2-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- include/exec/memory.h | 1 - memory.c | 35 ----------------------------------- 2 files changed, 36 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 7fb9188c0a..f649697ee9 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -187,7 +187,6 @@ struct MemoryRegion { MemoryRegion *alias; hwaddr alias_offset; int32_t priority; - bool may_overlap; QTAILQ_HEAD(subregions, MemoryRegion) subregions; QTAILQ_ENTRY(MemoryRegion) subregions_link; QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced; diff --git a/memory.c b/memory.c index 9daac5ea2d..ac5236b515 100644 --- a/memory.c +++ b/memory.c @@ -1057,13 +1057,6 @@ static void memory_region_get_priority(Object *obj, Visitor *v, visit_type_int32(v, name, &value, errp); } -static bool memory_region_get_may_overlap(Object *obj, Error **errp) -{ - MemoryRegion *mr = MEMORY_REGION(obj); - - return mr->may_overlap; -} - static void memory_region_get_size(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -1101,10 +1094,6 @@ static void memory_region_initfn(Object *obj) memory_region_get_priority, NULL, /* memory_region_set_priority */ NULL, NULL, &error_abort); - object_property_add_bool(OBJECT(mr), "may-overlap", - memory_region_get_may_overlap, - NULL, /* memory_region_set_may_overlap */ - &error_abort); object_property_add(OBJECT(mr), "size", "uint64", memory_region_get_size, NULL, /* memory_region_set_size, */ @@ -1864,34 +1853,12 @@ void memory_region_del_eventfd(MemoryRegion *mr, static void memory_region_update_container_subregions(MemoryRegion *subregion) { - hwaddr offset = subregion->addr; MemoryRegion *mr = subregion->container; MemoryRegion *other; memory_region_transaction_begin(); memory_region_ref(subregion); - QTAILQ_FOREACH(other, &mr->subregions, subregions_link) { - if (subregion->may_overlap || other->may_overlap) { - continue; - } - if (int128_ge(int128_make64(offset), - int128_add(int128_make64(other->addr), other->size)) - || int128_le(int128_add(int128_make64(offset), subregion->size), - int128_make64(other->addr))) { - continue; - } -#if 0 - printf("warning: subregion collision %llx/%llx (%s) " - "vs %llx/%llx (%s)\n", - (unsigned long long)offset, - (unsigned long long)int128_get64(subregion->size), - subregion->name, - (unsigned long long)other->addr, - (unsigned long long)int128_get64(other->size), - other->name); -#endif - } QTAILQ_FOREACH(other, &mr->subregions, subregions_link) { if (subregion->priority >= other->priority) { QTAILQ_INSERT_BEFORE(other, subregion, subregions_link); @@ -1918,7 +1885,6 @@ void memory_region_add_subregion(MemoryRegion *mr, hwaddr offset, MemoryRegion *subregion) { - subregion->may_overlap = false; subregion->priority = 0; memory_region_add_subregion_common(mr, offset, subregion); } @@ -1928,7 +1894,6 @@ void memory_region_add_subregion_overlap(MemoryRegion *mr, MemoryRegion *subregion, int priority) { - subregion->may_overlap = true; subregion->priority = priority; memory_region_add_subregion_common(mr, offset, subregion); } From 5b5660adf1fdb61db14ec681b10463b8cba633f1 Mon Sep 17 00:00:00 2001 From: Fam Zheng Date: Fri, 25 Mar 2016 18:10:29 +0800 Subject: [PATCH 12/24] memory: Drop FlatRange.romd_mode Its value is alway set to mr->romd_mode, so the removed comparisons are fully superseded by "a->mr == b->mr". Signed-off-by: Fam Zheng Message-Id: <1458900629-2334-3-git-send-email-famz@redhat.com> Signed-off-by: Paolo Bonzini --- memory.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/memory.c b/memory.c index ac5236b515..9d00dc5e7e 100644 --- a/memory.c +++ b/memory.c @@ -227,7 +227,6 @@ struct FlatRange { hwaddr offset_in_region; AddrRange addr; uint8_t dirty_log_mask; - bool romd_mode; bool readonly; }; @@ -252,7 +251,6 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b) return a->mr == b->mr && addrrange_equal(a->addr, b->addr) && a->offset_in_region == b->offset_in_region - && a->romd_mode == b->romd_mode && a->readonly == b->readonly; } @@ -312,7 +310,6 @@ static bool can_merge(FlatRange *r1, FlatRange *r2) r1->addr.size), int128_make64(r2->offset_in_region)) && r1->dirty_log_mask == r2->dirty_log_mask - && r1->romd_mode == r2->romd_mode && r1->readonly == r2->readonly; } @@ -666,7 +663,6 @@ static void render_memory_region(FlatView *view, fr.mr = mr; fr.dirty_log_mask = memory_region_get_dirty_log_mask(mr); - fr.romd_mode = mr->romd_mode; fr.readonly = readonly; /* Render the region itself into any gaps left by the current view. */ From e4e697940dff612b789b0858270c20a8b680f78d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 1 Mar 2016 10:44:50 +0100 Subject: [PATCH 13/24] memory: remove unnecessary masking of MemoryRegion ram_addr mr->ram_block->offset is already aligned to both host and target size (see qemu_ram_alloc_internal). Remove further masking as it is unnecessary. Reviewed-by: Fam Zheng Signed-off-by: Paolo Bonzini --- exec.c | 21 +++++++-------------- memory.c | 5 ++--- translate-all.c | 3 +-- 3 files changed, 10 insertions(+), 19 deletions(-) diff --git a/exec.c b/exec.c index 8cf535ddde..a3a93aeed3 100644 --- a/exec.c +++ b/exec.c @@ -1046,8 +1046,7 @@ hwaddr memory_region_section_get_iotlb(CPUState *cpu, if (memory_region_is_ram(section->mr)) { /* Normal RAM. */ - iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK) - + xlat; + iotlb = memory_region_get_ram_addr(section->mr) + xlat; if (!section->readonly) { iotlb |= PHYS_SECTION_NOTDIRTY; } else { @@ -3079,9 +3078,7 @@ static inline uint32_t address_space_ldl_internal(AddressSpace *as, hwaddr addr, } else { /* RAM case */ ptr = qemu_get_ram_ptr(mr->ram_block, - (memory_region_get_ram_addr(mr) - & TARGET_PAGE_MASK) - + addr1); + memory_region_get_ram_addr(mr) + addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: val = ldl_le_p(ptr); @@ -3175,9 +3172,7 @@ static inline uint64_t address_space_ldq_internal(AddressSpace *as, hwaddr addr, } else { /* RAM case */ ptr = qemu_get_ram_ptr(mr->ram_block, - (memory_region_get_ram_addr(mr) - & TARGET_PAGE_MASK) - + addr1); + memory_region_get_ram_addr(mr) + addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: val = ldq_le_p(ptr); @@ -3291,9 +3286,7 @@ static inline uint32_t address_space_lduw_internal(AddressSpace *as, } else { /* RAM case */ ptr = qemu_get_ram_ptr(mr->ram_block, - (memory_region_get_ram_addr(mr) - & TARGET_PAGE_MASK) - + addr1); + memory_region_get_ram_addr(mr) + addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: val = lduw_le_p(ptr); @@ -3375,7 +3368,7 @@ void address_space_stl_notdirty(AddressSpace *as, hwaddr addr, uint32_t val, r = memory_region_dispatch_write(mr, addr1, val, 4, attrs); } else { - addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK; + addr1 += memory_region_get_ram_addr(mr); ptr = qemu_get_ram_ptr(mr->ram_block, addr1); stl_p(ptr, val); @@ -3430,7 +3423,7 @@ static inline void address_space_stl_internal(AddressSpace *as, r = memory_region_dispatch_write(mr, addr1, val, 4, attrs); } else { /* RAM case */ - addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK; + addr1 += memory_region_get_ram_addr(mr); ptr = qemu_get_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -3540,7 +3533,7 @@ static inline void address_space_stw_internal(AddressSpace *as, r = memory_region_dispatch_write(mr, addr1, val, 2, attrs); } else { /* RAM case */ - addr1 += memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK; + addr1 += memory_region_get_ram_addr(mr); ptr = qemu_get_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: diff --git a/memory.c b/memory.c index 9d00dc5e7e..4e3cda8a12 100644 --- a/memory.c +++ b/memory.c @@ -1628,7 +1628,7 @@ int memory_region_get_fd(MemoryRegion *mr) assert(mr->ram_block); - return qemu_get_ram_fd(memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); + return qemu_get_ram_fd(memory_region_get_ram_addr(mr)); } void *memory_region_get_ram_ptr(MemoryRegion *mr) @@ -1642,8 +1642,7 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) mr = mr->alias; } assert(mr->ram_block); - ptr = qemu_get_ram_ptr(mr->ram_block, - memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK); + ptr = qemu_get_ram_ptr(mr->ram_block, memory_region_get_ram_addr(mr)); rcu_read_unlock(); return ptr + offset; diff --git a/translate-all.c b/translate-all.c index 1c1c85530a..c599dc4d41 100644 --- a/translate-all.c +++ b/translate-all.c @@ -1555,8 +1555,7 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr) rcu_read_unlock(); return; } - ram_addr = (memory_region_get_ram_addr(mr) & TARGET_PAGE_MASK) - + addr; + ram_addr = memory_region_get_ram_addr(mr) + addr; tb_invalidate_phys_page_range(ram_addr, ram_addr + 1, 0); rcu_read_unlock(); } From a2d1761da1de2c4d08f51067b2af8cf6d95899ee Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 16 May 2016 18:33:59 +0100 Subject: [PATCH 14/24] cpus.c: Use pthread_sigmask() rather than sigprocmask() On Linux, sigprocmask() and pthread_sigmask() are in practice the same thing (they only set the signal mask for the calling thread), but the documentation states that the behaviour of sigprocmask() in a multithreaded process is undefined. Use pthread_sigmask() instead (which is what we do in almost all places in QEMU that alter the signal mask already). Signed-off-by: Peter Maydell Message-Id: <1463420039-29761-1-git-send-email-peter.maydell@linaro.org> Signed-off-by: Paolo Bonzini --- cpus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index eb34b4fe76..f8366c684e 100644 --- a/cpus.c +++ b/cpus.c @@ -780,7 +780,7 @@ static void sigbus_reraise(void) raise(SIGBUS); sigemptyset(&set); sigaddset(&set, SIGBUS); - sigprocmask(SIG_UNBLOCK, &set, NULL); + pthread_sigmask(SIG_UNBLOCK, &set, NULL); } perror("Failed to re-raise SIGBUS!\n"); abort(); From 168340b6ba5ab784b9d2ed90351759f36c9b1486 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 17 May 2016 12:27:31 +0100 Subject: [PATCH 15/24] Remove config-devices.mak on 'make clean' Our dependency mechanism works like this: * on first build there is neither a .o nor a .d * we create the .d as a side effect of creating the .o * for rebuilds we know when we need to update the .o, which also updates the .d This system requires that you're never in a situation where there is a .o file but no .d (because then we will never realise we need to build the .d, and we will not have the dependency information about when to rebuild the .o). This is working fine for our object files, but we also try to use it for $TARGET/config-devices.mak (where the dependency file is in $TARGET-config-devices.mak.d). Unfortunately "make clean" doesn't remove config-devices.mak, which means that it puts us in the forbidden situation of "object file exists but not its .d file". This in turn means that we will fail to notice when we need to rebuild: mkdir build/depbug (cd build/depbug && '../../configure') make -C build/depbug -j8 make -C build/depbug clean echo "CONFIG_CANARY = y" >> default-configs/arm-softmmu.mak make -C build/depbug grep CANARY build/depbug/aarch64-softmmu/config-devices.mak The CANARY token should show up in config-devices.mak but does not. Fix this bug by making "make clean" delete the config-devices.mak files. config-all-devices.mak doesn't have the same problem since it has no .d file, but delete it too, since it is created by "make" and logically should be removed by "make clean". (Note that it is important not to remove config-devices.mak until after we have recursively run 'make clean' in the subdirectories.) Signed-off-by: Peter Maydell Message-Id: <1463484451-22979-1-git-send-email-peter.maydell@linaro.org> Signed-off-by: Paolo Bonzini --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 1d076a9d85..a5d7e62626 100644 --- a/Makefile +++ b/Makefile @@ -356,6 +356,7 @@ clean: if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \ rm -f $$d/qemu-options.def; \ done + rm -f $(SUBDIR_DEVICES_MAK) config-all-devices.mak VERSION ?= $(shell cat VERSION) From 6f71b779c8b05cf60ea0fffbcd8c02adfe845ece Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 11 May 2016 22:06:45 +0100 Subject: [PATCH 16/24] scripts/signrom.py: Allow option ROM checksum script to write the size header. Modify the signrom.py script so that if the size byte in the header is 0 (ie. not set) then the script will set the size. If the size byte is non-zero then we do the same as before, so this doesn't require changes to any existing ROM sourcecode. Signed-off-by: Richard W.M. Jones Message-Id: <1463000807-18015-2-git-send-email-rjones@redhat.com> --- scripts/signrom.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/scripts/signrom.py b/scripts/signrom.py index f9c35ccfca..6c8b9bf406 100644 --- a/scripts/signrom.py +++ b/scripts/signrom.py @@ -18,10 +18,29 @@ fin = open(sys.argv[1], 'rb') fout = open(sys.argv[2], 'wb') fin.seek(2) -size = ord(fin.read(1)) * 512 - 1 - +size_byte = ord(fin.read(1)) fin.seek(0) -data = fin.read(size) + +if size_byte == 0: + # If the caller left the size field blank then we will fill it in, + # also rounding the whole input to a multiple of 512 bytes. + data = fin.read() + # +1 because we need a byte to store the checksum. + size = len(data) + 1 + # Round up to next multiple of 512. + size += 511 + size -= size % 512 + if size >= 65536: + sys.exit("%s: option ROM size too large" % sys.argv[1]) + # size-1 because a final byte is added below to store the checksum. + data = data.ljust(size-1, '\0') + data = data[:2] + chr(size/512) + data[3:] +else: + # Otherwise the input file specifies the size so use it. + # -1 because we overwrite the last byte of the file with the checksum. + size = size_byte * 512 - 1 + data = fin.read(size) + fout.write(data) checksum = 0 From fd28938b7adb33f8af11849cdd0d0b2fb92990e3 Mon Sep 17 00:00:00 2001 From: "Richard W.M. Jones" Date: Wed, 11 May 2016 22:06:46 +0100 Subject: [PATCH 17/24] scripts/signrom.py: Check for magic in option ROMs. Because of the risk that compilers might not emit the asm() block at the beginning of the option ROM, check that the ROM contains the required magic signature. Signed-off-by: Richard W.M. Jones Message-Id: <1463000807-18015-3-git-send-email-rjones@redhat.com> Signed-off-by: Paolo Bonzini --- scripts/signrom.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/signrom.py b/scripts/signrom.py index 6c8b9bf406..5629bca222 100644 --- a/scripts/signrom.py +++ b/scripts/signrom.py @@ -17,7 +17,10 @@ if len(sys.argv) < 3: fin = open(sys.argv[1], 'rb') fout = open(sys.argv[2], 'wb') -fin.seek(2) +magic = fin.read(2) +if magic != '\x55\xaa': + sys.exit("%s: option ROM does not begin with magic 55 aa" % sys.argv[1]) + size_byte = ord(fin.read(1)) fin.seek(0) From c98c6c105f66f05aa0b7c1d2a4a3f716450907ef Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Thu, 19 May 2016 16:09:30 +0530 Subject: [PATCH 18/24] esp: check command buffer length before write(CVE-2016-4439) The 53C9X Fast SCSI Controller(FSC) comes with an internal 16-byte FIFO buffer. It is used to handle command and data transfer. While writing to this command buffer 's->cmdbuf[TI_BUFSZ=16]', a check was missing to validate input length. Add check to avoid OOB write access. Fixes CVE-2016-4439. Reported-by: Li Qiang Cc: qemu-stable@nongnu.org Signed-off-by: Prasad J Pandit Message-Id: <1463654371-11169-2-git-send-email-ppandit@redhat.com> Signed-off-by: Paolo Bonzini --- hw/scsi/esp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 8961be2f34..01497e6740 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -448,7 +448,11 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) break; case ESP_FIFO: if (s->do_cmd) { - s->cmdbuf[s->cmdlen++] = val & 0xff; + if (s->cmdlen < TI_BUFSZ) { + s->cmdbuf[s->cmdlen++] = val & 0xff; + } else { + trace_esp_error_fifo_overrun(); + } } else if (s->ti_size == TI_BUFSZ - 1) { trace_esp_error_fifo_overrun(); } else { From 6c1fef6b59563cc415f21e03f81539ed4b33ad90 Mon Sep 17 00:00:00 2001 From: Prasad J Pandit Date: Thu, 19 May 2016 16:09:31 +0530 Subject: [PATCH 19/24] esp: check dma length before reading scsi command(CVE-2016-4441) The 53C9X Fast SCSI Controller(FSC) comes with an internal 16-byte FIFO buffer. It is used to handle command and data transfer. Routine get_cmd() uses DMA to read scsi commands into this buffer. Add check to validate DMA length against buffer size to avoid any overrun. Fixes CVE-2016-4441. Reported-by: Li Qiang Cc: qemu-stable@nongnu.org Signed-off-by: Prasad J Pandit Message-Id: <1463654371-11169-3-git-send-email-ppandit@redhat.com> Signed-off-by: Paolo Bonzini --- hw/scsi/esp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 01497e6740..591c8172d5 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -82,7 +82,7 @@ void esp_request_cancelled(SCSIRequest *req) } } -static uint32_t get_cmd(ESPState *s, uint8_t *buf) +static uint32_t get_cmd(ESPState *s, uint8_t *buf, uint8_t buflen) { uint32_t dmalen; int target; @@ -92,6 +92,9 @@ static uint32_t get_cmd(ESPState *s, uint8_t *buf) dmalen = s->rregs[ESP_TCLO]; dmalen |= s->rregs[ESP_TCMID] << 8; dmalen |= s->rregs[ESP_TCHI] << 16; + if (dmalen > buflen) { + return 0; + } s->dma_memory_read(s->dma_opaque, buf, dmalen); } else { dmalen = s->ti_size; @@ -166,7 +169,7 @@ static void handle_satn(ESPState *s) s->dma_cb = handle_satn; return; } - len = get_cmd(s, buf); + len = get_cmd(s, buf, sizeof(buf)); if (len) do_cmd(s, buf); } @@ -180,7 +183,7 @@ static void handle_s_without_atn(ESPState *s) s->dma_cb = handle_s_without_atn; return; } - len = get_cmd(s, buf); + len = get_cmd(s, buf, sizeof(buf)); if (len) { do_busid_cmd(s, buf, 0); } @@ -192,7 +195,7 @@ static void handle_satn_stop(ESPState *s) s->dma_cb = handle_satn_stop; return; } - s->cmdlen = get_cmd(s, s->cmdbuf); + s->cmdlen = get_cmd(s, s->cmdbuf, sizeof(s->cmdbuf)); if (s->cmdlen) { trace_esp_handle_satn_stop(s->cmdlen); s->do_cmd = 1; From 644c6869d335e10bc10b8399646f767763c4977f Mon Sep 17 00:00:00 2001 From: Vadim Rozenfeld Date: Fri, 13 May 2016 13:03:22 +0200 Subject: [PATCH 20/24] iscsi: pass SCSI status back for SG_IO Signed-off-by: Vadim Rozenfeld Signed-off-by: Paolo Bonzini --- block/iscsi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/iscsi.c b/block/iscsi.c index 10f3906bcc..2ca8e72967 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -761,6 +761,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, acb->ioh->driver_status = 0; acb->ioh->host_status = 0; acb->ioh->resid = 0; + acb->ioh->status = status; #define SG_ERR_DRIVER_SENSE 0x08 From 6ad978e9f40d3edfd9f4a86b4a60e3523eff08fe Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 18 May 2016 11:11:55 +0200 Subject: [PATCH 21/24] coccinelle: add g_assert_cmp* to macro file This helps applying semantic patches to unit tests. Signed-off-by: Paolo Bonzini --- scripts/cocci-macro-file.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h index eceb4be73f..9f2e72e7e1 100644 --- a/scripts/cocci-macro-file.h +++ b/scripts/cocci-macro-file.h @@ -117,3 +117,9 @@ struct { \ type *tqe_next; /* next element */ \ type **tqe_prev; /* address of previous next element */ \ } + +/* From glib */ +#define g_assert_cmpint(a, op, b) g_assert(a op b) +#define g_assert_cmpuint(a, op, b) g_assert(a op b) +#define g_assert_cmphex(a, op, b) g_assert(a op b) +#define g_assert_cmpstr(a, op, b) g_assert(strcmp(a, b) op 0) From 1255166b9974665d1e4a24473e1dc51cd061ef4a Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Fri, 20 May 2016 12:28:35 -0400 Subject: [PATCH 22/24] target-i386: add a generic x86 nmi handler Instead of having x86 ifdefs in core nmi code, this change adds a arch specific handler that the nmi common code can call. Signed-off-by: Bandan Das Message-Id: <1463761717-26558-2-git-send-email-bsd@redhat.com> Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 99437e0b78..e29ccc8341 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -67,6 +67,7 @@ #include "qapi/visitor.h" #include "qapi-visit.h" #include "qom/cpu.h" +#include "hw/nmi.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -1963,11 +1964,28 @@ static CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *machine) return list; } +static void x86_nmi(NMIState *n, int cpu_index, Error **errp) +{ + /* cpu index isn't used */ + CPUState *cs; + + CPU_FOREACH(cs) { + X86CPU *cpu = X86_CPU(cs); + + if (!cpu->apic_state) { + cpu_interrupt(cs, CPU_INTERRUPT_NMI); + } else { + apic_deliver_nmi(cpu->apic_state); + } + } +} + static void pc_machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); PCMachineClass *pcmc = PC_MACHINE_CLASS(oc); HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); pcmc->get_hotplug_handler = mc->get_hotplug_handler; pcmc->pci_enabled = true; @@ -1993,6 +2011,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) hc->plug = pc_machine_device_plug_cb; hc->unplug_request = pc_machine_device_unplug_request_cb; hc->unplug = pc_machine_device_unplug_cb; + nc->nmi_monitor_handler = x86_nmi; } static const TypeInfo pc_machine_info = { @@ -2005,6 +2024,7 @@ static const TypeInfo pc_machine_info = { .class_init = pc_machine_class_init, .interfaces = (InterfaceInfo[]) { { TYPE_HOTPLUG_HANDLER }, + { TYPE_NMI }, { } }, }; From f7e981f29548fe4af7812f5920304fe607e5bf0d Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Fri, 20 May 2016 12:28:36 -0400 Subject: [PATCH 23/24] nmi: remove x86 specific nmi handling nmi_monitor_handle is wired to call the x86 nmi handler. So, we can directly use it at call sites. Signed-off-by: Bandan Das Message-Id: <1463761717-26558-3-git-send-email-bsd@redhat.com> Signed-off-by: Paolo Bonzini --- hw/core/nmi.c | 24 ------------------------ hw/watchdog/watchdog.c | 2 +- include/hw/nmi.h | 1 - 3 files changed, 1 insertion(+), 26 deletions(-) diff --git a/hw/core/nmi.c b/hw/core/nmi.c index f616a79312..bfd0896daf 100644 --- a/hw/core/nmi.c +++ b/hw/core/nmi.c @@ -20,16 +20,11 @@ */ #include "qemu/osdep.h" -#include "qom/cpu.h" #include "hw/nmi.h" #include "qapi/error.h" #include "qapi/qmp/qerror.h" #include "monitor/monitor.h" -#if defined(TARGET_I386) -#include "cpu.h" -#endif - struct do_nmi_s { int cpu_index; Error *err; @@ -78,25 +73,6 @@ void nmi_monitor_handle(int cpu_index, Error **errp) } } -void inject_nmi(void) -{ -#if defined(TARGET_I386) - CPUState *cs; - - CPU_FOREACH(cs) { - X86CPU *cpu = X86_CPU(cs); - - if (!cpu->apic_state) { - cpu_interrupt(cs, CPU_INTERRUPT_NMI); - } else { - apic_deliver_nmi(cpu->apic_state); - } - } -#else - nmi_monitor_handle(0, NULL); -#endif -} - static const TypeInfo nmi_info = { .name = TYPE_NMI, .parent = TYPE_INTERFACE, diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c index bbf3646bae..2aeaf1fbc9 100644 --- a/hw/watchdog/watchdog.c +++ b/hw/watchdog/watchdog.c @@ -143,7 +143,7 @@ void watchdog_perform_action(void) case WDT_NMI: qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_INJECT_NMI, &error_abort); - inject_nmi(); + nmi_monitor_handle(0, NULL); break; } } diff --git a/include/hw/nmi.h b/include/hw/nmi.h index f4cec6257d..b541772e1d 100644 --- a/include/hw/nmi.h +++ b/include/hw/nmi.h @@ -45,6 +45,5 @@ typedef struct NMIClass { } NMIClass; void nmi_monitor_handle(int cpu_index, Error **errp); -void inject_nmi(void); #endif /* NMI_H */ From 1453e6627d19a8d6d54480c6980f5cef5dfc6833 Mon Sep 17 00:00:00 2001 From: Bandan Das Date: Fri, 20 May 2016 12:28:37 -0400 Subject: [PATCH 24/24] cpus: call the core nmi injection function We can call the common function here directly since x86 specific actions will be taken care of by the arch specific nmi handler Signed-off-by: Bandan Das Message-Id: <1463761717-26558-4-git-send-email-bsd@redhat.com> Signed-off-by: Paolo Bonzini --- cpus.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/cpus.c b/cpus.c index f8366c684e..e75895a458 100644 --- a/cpus.c +++ b/cpus.c @@ -1693,21 +1693,7 @@ exit: void qmp_inject_nmi(Error **errp) { -#if defined(TARGET_I386) - CPUState *cs; - - CPU_FOREACH(cs) { - X86CPU *cpu = X86_CPU(cs); - - if (!cpu->apic_state) { - cpu_interrupt(cs, CPU_INTERRUPT_NMI); - } else { - apic_deliver_nmi(cpu->apic_state); - } - } -#else nmi_monitor_handle(monitor_get_cpu_index(), errp); -#endif } void dump_drift_info(FILE *f, fprintf_function cpu_fprintf)