From 8a5956ad6392f115521dad774055c737c49fb0dd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 21 Mar 2015 16:32:05 +0100 Subject: [PATCH 01/14] rcu tests: fix compilation on 32-bit ppc 32-bit PPC cannot do atomic operations on long long. Inside the loops, we are already using local counters that are summed at the end of the run---with some exceptions (rcu_stress_count for rcutorture, n_nodes for test-rcu-list): fix them to use the same technique. For test-rcu-list, remove the mostly unused member "val" from the list. Then, use a mutex to protect the global counts. Performance does not matter there because every thread will only enter the critical section once. Remaining uses of atomic instructions are for ints or pointers. Reported-by: Andreas Faerber Signed-off-by: Paolo Bonzini --- tests/rcutorture.c | 20 +++++++++++++---- tests/test-rcu-list.c | 50 ++++++++++++++++++++++++------------------- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/tests/rcutorture.c b/tests/rcutorture.c index 60a2ccfe2e..d6b304d000 100644 --- a/tests/rcutorture.c +++ b/tests/rcutorture.c @@ -82,6 +82,7 @@ static volatile int goflag = GOFLAG_INIT; #define RCU_READ_RUN 1000 #define NR_THREADS 100 +static QemuMutex counts_mutex; static QemuThread threads[NR_THREADS]; static struct rcu_reader_data *data[NR_THREADS]; static int n_threads; @@ -130,7 +131,9 @@ static void *rcu_read_perf_test(void *arg) } n_reads_local += RCU_READ_RUN; } - atomic_add(&n_reads, n_reads_local); + qemu_mutex_lock(&counts_mutex); + n_reads += n_reads_local; + qemu_mutex_unlock(&counts_mutex); rcu_unregister_thread(); return NULL; @@ -151,7 +154,9 @@ static void *rcu_update_perf_test(void *arg) synchronize_rcu(); n_updates_local++; } - atomic_add(&n_updates, n_updates_local); + qemu_mutex_lock(&counts_mutex); + n_updates += n_updates_local; + qemu_mutex_unlock(&counts_mutex); rcu_unregister_thread(); return NULL; @@ -241,6 +246,7 @@ static void *rcu_read_stress_test(void *arg) struct rcu_stress *p; int pc; long long n_reads_local = 0; + long long rcu_stress_local[RCU_STRESS_PIPE_LEN + 1] = { 0 }; volatile int garbage = 0; rcu_register_thread(); @@ -265,13 +271,18 @@ static void *rcu_read_stress_test(void *arg) if ((pc > RCU_STRESS_PIPE_LEN) || (pc < 0)) { pc = RCU_STRESS_PIPE_LEN; } - atomic_inc(&rcu_stress_count[pc]); + rcu_stress_local[pc]++; n_reads_local++; if ((++itercnt % 0x1000) == 0) { synchronize_rcu(); } } - atomic_add(&n_reads, n_reads_local); + qemu_mutex_lock(&counts_mutex); + n_reads += n_reads_local; + for (i = 0; i <= RCU_STRESS_PIPE_LEN; i++) { + rcu_stress_count[i] += rcu_stress_local[i]; + } + qemu_mutex_unlock(&counts_mutex); rcu_unregister_thread(); return NULL; @@ -419,6 +430,7 @@ int main(int argc, char *argv[]) int nreaders = 1; int duration = 1; + qemu_mutex_init(&counts_mutex); if (argc >= 2 && argv[1][0] == '-') { g_test_init(&argc, &argv, NULL); if (g_test_quick()) { diff --git a/tests/test-rcu-list.c b/tests/test-rcu-list.c index 46b5e263e5..4c5f62e996 100644 --- a/tests/test-rcu-list.c +++ b/tests/test-rcu-list.c @@ -35,16 +35,15 @@ * Test variables. */ -long long n_reads = 0LL; -long long n_updates = 0LL; -long long n_reclaims = 0LL; -long long n_nodes_removed = 0LL; -long long n_nodes = 0LL; -int g_test_in_charge = 0; +static QemuMutex counts_mutex; +static long long n_reads = 0LL; +static long long n_updates = 0LL; +static long long n_reclaims = 0LL; +static long long n_nodes_removed = 0LL; +static long long n_nodes = 0LL; +static int g_test_in_charge = 0; -int nthreadsrunning; - -char argsbuf[64]; +static int nthreadsrunning; #define GOFLAG_INIT 0 #define GOFLAG_RUN 1 @@ -92,21 +91,21 @@ static void wait_all_threads(void) struct list_element { QLIST_ENTRY(list_element) entry; struct rcu_head rcu; - long long val; }; static void reclaim_list_el(struct rcu_head *prcu) { struct list_element *el = container_of(prcu, struct list_element, rcu); g_free(el); - atomic_add(&n_reclaims, 1); + /* Accessed only from call_rcu thread. */ + n_reclaims++; } static QLIST_HEAD(q_list_head, list_element) Q_list_head; static void *rcu_q_reader(void *arg) { - long long j, n_reads_local = 0; + long long n_reads_local = 0; struct list_element *el; *(struct rcu_reader_data **)arg = &rcu_reader; @@ -118,8 +117,6 @@ static void *rcu_q_reader(void *arg) while (goflag == GOFLAG_RUN) { rcu_read_lock(); QLIST_FOREACH_RCU(el, &Q_list_head, entry) { - j = atomic_read(&el->val); - (void)j; n_reads_local++; if (goflag == GOFLAG_STOP) { break; @@ -129,7 +126,9 @@ static void *rcu_q_reader(void *arg) g_usleep(100); } - atomic_add(&n_reads, n_reads_local); + qemu_mutex_lock(&counts_mutex); + n_reads += n_reads_local; + qemu_mutex_unlock(&counts_mutex); return NULL; } @@ -137,6 +136,7 @@ static void *rcu_q_reader(void *arg) static void *rcu_q_updater(void *arg) { int j, target_el; + long long n_nodes_local = 0; long long n_updates_local = 0; long long n_removed_local = 0; struct list_element *el, *prev_el; @@ -170,8 +170,7 @@ static void *rcu_q_updater(void *arg) j++; if (target_el == j) { prev_el = g_new(struct list_element, 1); - atomic_add(&n_nodes, 1); - prev_el->val = atomic_read(&n_nodes); + n_nodes += n_nodes_local; QLIST_INSERT_BEFORE_RCU(el, prev_el, entry); break; } @@ -181,8 +180,11 @@ static void *rcu_q_updater(void *arg) synchronize_rcu(); } synchronize_rcu(); - atomic_add(&n_updates, n_updates_local); - atomic_add(&n_nodes_removed, n_removed_local); + qemu_mutex_lock(&counts_mutex); + n_nodes += n_nodes_local; + n_updates += n_updates_local; + n_nodes_removed += n_removed_local; + qemu_mutex_unlock(&counts_mutex); return NULL; } @@ -194,10 +196,11 @@ static void rcu_qtest_init(void) srand(time(0)); for (i = 0; i < RCU_Q_LEN; i++) { new_el = g_new(struct list_element, 1); - new_el->val = i; QLIST_INSERT_HEAD_RCU(&Q_list_head, new_el, entry); } - atomic_add(&n_nodes, RCU_Q_LEN); + qemu_mutex_lock(&counts_mutex); + n_nodes += RCU_Q_LEN; + qemu_mutex_unlock(&counts_mutex); } static void rcu_qtest_run(int duration, int nreaders) @@ -233,7 +236,9 @@ static void rcu_qtest(const char *test, int duration, int nreaders) call_rcu1(&prev_el->rcu, reclaim_list_el); n_removed_local++; } - atomic_add(&n_nodes_removed, n_removed_local); + qemu_mutex_lock(&counts_mutex); + n_nodes_removed += n_removed_local; + qemu_mutex_unlock(&counts_mutex); synchronize_rcu(); while (n_nodes_removed > n_reclaims) { g_usleep(100); @@ -277,6 +282,7 @@ int main(int argc, char *argv[]) { int duration = 0, readers = 0; + qemu_mutex_init(&counts_mutex); if (argc >= 2) { if (argv[1][0] == '-') { g_test_init(&argc, &argv, NULL); From 3a5c76baf312d83cb77c8faa72c5f7a477effed0 Mon Sep 17 00:00:00 2001 From: "Gabriel L. Somlo" Date: Thu, 19 Mar 2015 14:20:44 -0400 Subject: [PATCH 02/14] fw_cfg: factor out initialization of FW_CFG_ID (rev. number) The fw_cfg documentation says this of the revision key (0x0001, FW_CFG_ID): > A 32-bit little-endian unsigned int, this item is used as an interface > revision number, and is currently set to 1 by all QEMU architectures > which expose a fw_cfg device. arm/virt doesn't. It could be argued that that's an error in "hw/arm/virt.c"; on the other hand, all of the other fw_cfg providing boards set the interface version to 1 manually, despite the device coming from the same, shared implementation. Therefore, instead of adding fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); to arm/virt, consolidate all such existing calls in the fw_cfg initialization code. Signed-off-by: Gabriel Somlo Message-Id: <1426789244-26318-1-git-send-email-somlo@cmu.edu> Reviewed-by: Laszlo Ersek Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 1 - hw/nvram/fw_cfg.c | 1 + hw/ppc/mac_newworld.c | 1 - hw/ppc/mac_oldworld.c | 1 - hw/sparc/sun4m.c | 1 - hw/sparc64/sun4u.c | 1 - 6 files changed, 1 insertion(+), 5 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index a52d2aff7c..a8e6be14e4 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -702,7 +702,6 @@ static FWCfgState *bochs_bios_init(void) * the APIC ID, not the "CPU index" */ fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)apic_id_limit); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_ACPI_TABLES, acpi_tables, acpi_tables_len); diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 4caf5364da..68eff77983 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -614,6 +614,7 @@ static void fw_cfg_init1(DeviceState *dev) qdev_init_nofail(dev); fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (char *)"QEMU", 4); + fw_cfg_add_i32(s, FW_CFG_ID, 1); fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16); fw_cfg_add_i16(s, FW_CFG_NOGRAPHIC, (uint16_t)(display_type == DT_NOGRAPHIC)); fw_cfg_add_i16(s, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 624b4ab50b..e0397bc796 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -460,7 +460,6 @@ static void ppc_core99_init(MachineState *machine) fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 3079510058..f26133dedd 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -315,7 +315,6 @@ static void ppc_heathrow_init(MachineState *machine) fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, ARCH_HEATHROW); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index b879aa91eb..255ba1f4f5 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -1088,7 +1088,6 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth); diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index f027caf909..6f34e87935 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -895,7 +895,6 @@ static void sun4uv_init(MemoryRegion *address_space_mem, fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); - fw_cfg_add_i32(fw_cfg, FW_CFG_ID, 1); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); fw_cfg_add_i64(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_entry); From 06b82e2d8ead4d1f9441dbf2b03c31369a8f27bd Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 23 Mar 2015 12:51:47 +1100 Subject: [PATCH 03/14] i6300esb: Correct endiannness The IO operations for the i6300esb watchdog timer are marked as DEVICE_NATIVE_ENDIAN. This is not correct, and - as a PCI device - should be DEVICE_LITTLE_ENDIAN. This allows i6300esb to work on ppc targets (yes, using an Intel ICH derived device on ppc is a bit odd, but the driver exists on the guest and there's no more obviously suitable watchdog device). Signed-off-by: David Gibson Message-Id: <1427075508-12099-2-git-send-email-david@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- hw/watchdog/wdt_i6300esb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index b2d158f7ba..e694fa9969 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -369,7 +369,7 @@ static const MemoryRegionOps i6300esb_ops = { i6300esb_mem_writel, }, }, - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, }; static const VMStateDescription vmstate_i6300esb = { From 4bc7b4d56657ebf75b986ad46e959cf7232ff26a Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 23 Mar 2015 12:51:48 +1100 Subject: [PATCH 04/14] i6300esb: Fix signed integer overflow If the guest programs a sufficiently large timeout value an integer overflow can occur in i6300esb_restart_timer(). e.g. if the maximum possible timer preload value of 0xfffff is programmed then we end up with the calculation: timeout = get_ticks_per_sec() * (0xfffff << 15) / 33000000; get_ticks_per_sec() returns 1000000000 (10^9) giving: 10^9 * (0xfffff * 2^15) == 0x1dcd632329b000000 (65 bits) Obviously the division by 33MHz brings it back under 64-bits, but the overflow has already occurred. Since signed integer overflow has undefined behaviour in C, in theory this could be arbitrarily bad. In practice, the overflowed value wraps around to something negative, causing the watchdog to immediately expire, killing the guest, which is still fairly bad. The bug can be triggered by running a Linux guest, loading the i6300esb driver with parameter "heartbeat=2046" and opening /dev/watchdog. The watchdog will trigger as soon as the device is opened. This patch corrects the problem by using muldiv64(), which effectively allows a 128-bit intermediate value between the multiplication and division. Signed-off-by: David Gibson Message-Id: <1427075508-12099-3-git-send-email-david@gibson.dropbear.id.au> Signed-off-by: Paolo Bonzini --- hw/watchdog/wdt_i6300esb.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index e694fa9969..4ebdbb8586 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -125,8 +125,14 @@ static void i6300esb_restart_timer(I6300State *d, int stage) else timeout <<= 5; - /* Get the timeout in units of ticks_per_sec. */ - timeout = get_ticks_per_sec() * timeout / 33000000; + /* Get the timeout in units of ticks_per_sec. + * + * ticks_per_sec is typically 10^9 == 0x3B9ACA00 (30 bits), with + * 20 bits of user supplied preload, and 15 bits of scale, the + * multiply here can exceed 64-bits, before we divide by 33MHz, so + * we use a higher-precision intermediate result. + */ + timeout = muldiv64(get_ticks_per_sec(), timeout, 33000000); i6300esb_debug("stage %d, timeout %" PRIi64 "\n", d->stage, timeout); From bdd459a00a206772185970efbc38c455dc43167e Mon Sep 17 00:00:00 2001 From: Peter Crosthwaite Date: Mon, 23 Mar 2015 03:48:09 -0700 Subject: [PATCH 05/14] cpus: Don't kick un-realized cpus. following a464982499b2f637f6699e3d03e0a9d2e0b5288b, it's now possible for there to be attempts to take the BQL before CPUs have been realized in cases where a machine model inits peripherals before the first CPU. BQL lock aquisition kicks the first_cpu, leading to a segfault if this happens pre-realize. Guard the CPU kick routine to perform no action for a CPU that doesn't exist or doesn't have a thread yet. There was a fix to this with commit 6b49809c597331803ea941eadda813e5bb4e8fe2, but the check there misses the case where the CPU has been inited and not realized. Strengthen the check to make sure that the first_cpu has a thread (i.e. it is realized) before allowing the kick. Signed-off-by: Peter Crosthwaite Message-Id: <1427107689-6946-1-git-send-email-peter.crosthwaite@xilinx.com> Signed-off-by: Paolo Bonzini --- cpus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpus.c b/cpus.c index 314df16190..e6dcae31f5 100644 --- a/cpus.c +++ b/cpus.c @@ -1119,7 +1119,7 @@ bool qemu_in_vcpu_thread(void) void qemu_mutex_lock_iothread(void) { atomic_inc(&iothread_requesting_mutex); - if (!tcg_enabled() || !first_cpu) { + if (!tcg_enabled() || !first_cpu || !first_cpu->thread) { qemu_mutex_lock(&qemu_global_mutex); atomic_dec(&iothread_requesting_mutex); } else { From 16578c6ffe8c4ee5207ccb9b0c994c1b18bb322d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Mar 2015 17:15:17 +0100 Subject: [PATCH 06/14] megasas: use PCI DMA APIs It is wrong to use address_space_memory directly, because there could be an IOMMU in the middle. Signed-off-by: Paolo Bonzini --- hw/scsi/megasas.c | 51 ++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index bf83b65383..ad7317bfe9 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -171,26 +171,29 @@ static bool megasas_is_jbod(MegasasState *s) return s->flags & MEGASAS_MASK_USE_JBOD; } -static void megasas_frame_set_cmd_status(unsigned long frame, uint8_t v) +static void megasas_frame_set_cmd_status(MegasasState *s, + unsigned long frame, uint8_t v) { - stb_phys(&address_space_memory, - frame + offsetof(struct mfi_frame_header, cmd_status), v); + PCIDevice *pci = &s->parent_obj; + stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, cmd_status), v); } -static void megasas_frame_set_scsi_status(unsigned long frame, uint8_t v) +static void megasas_frame_set_scsi_status(MegasasState *s, + unsigned long frame, uint8_t v) { - stb_phys(&address_space_memory, - frame + offsetof(struct mfi_frame_header, scsi_status), v); + PCIDevice *pci = &s->parent_obj; + stb_pci_dma(pci, frame + offsetof(struct mfi_frame_header, scsi_status), v); } /* * Context is considered opaque, but the HBA firmware is running * in little endian mode. So convert it to little endian, too. */ -static uint64_t megasas_frame_get_context(unsigned long frame) +static uint64_t megasas_frame_get_context(MegasasState *s, + unsigned long frame) { - return ldq_le_phys(&address_space_memory, - frame + offsetof(struct mfi_frame_header, context)); + PCIDevice *pci = &s->parent_obj; + return ldq_le_pci_dma(pci, frame + offsetof(struct mfi_frame_header, context)); } static bool megasas_frame_is_ieee_sgl(MegasasCmd *cmd) @@ -523,8 +526,7 @@ static MegasasCmd *megasas_enqueue_frame(MegasasState *s, s->busy++; if (s->consumer_pa) { - s->reply_queue_tail = ldl_le_phys(&address_space_memory, - s->consumer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa); } trace_megasas_qf_enqueue(cmd->index, cmd->count, cmd->context, s->reply_queue_head, s->reply_queue_tail, s->busy); @@ -547,29 +549,24 @@ static void megasas_complete_frame(MegasasState *s, uint64_t context) */ if (megasas_use_queue64(s)) { queue_offset = s->reply_queue_head * sizeof(uint64_t); - stq_le_phys(&address_space_memory, - s->reply_queue_pa + queue_offset, context); + stq_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, context); } else { queue_offset = s->reply_queue_head * sizeof(uint32_t); - stl_le_phys(&address_space_memory, - s->reply_queue_pa + queue_offset, context); + stl_le_pci_dma(pci_dev, s->reply_queue_pa + queue_offset, context); } - s->reply_queue_tail = ldl_le_phys(&address_space_memory, - s->consumer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa); trace_megasas_qf_complete(context, s->reply_queue_head, s->reply_queue_tail, s->busy); } if (megasas_intr_enabled(s)) { /* Update reply queue pointer */ - s->reply_queue_tail = ldl_le_phys(&address_space_memory, - s->consumer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pci_dev, s->consumer_pa); tail = s->reply_queue_head; s->reply_queue_head = megasas_next_index(s, tail, s->fw_cmds); trace_megasas_qf_update(s->reply_queue_head, s->reply_queue_tail, s->busy); - stl_le_phys(&address_space_memory, - s->producer_pa, s->reply_queue_head); + stl_le_pci_dma(pci_dev, s->producer_pa, s->reply_queue_head); /* Notify HBA */ if (msix_enabled(pci_dev)) { trace_megasas_msix_raise(0); @@ -651,8 +648,8 @@ static int megasas_init_firmware(MegasasState *s, MegasasCmd *cmd) pa_lo = le32_to_cpu(initq->pi_addr_lo); pa_hi = le32_to_cpu(initq->pi_addr_hi); s->producer_pa = ((uint64_t) pa_hi << 32) | pa_lo; - s->reply_queue_head = ldl_le_phys(&address_space_memory, s->producer_pa); - s->reply_queue_tail = ldl_le_phys(&address_space_memory, s->consumer_pa); + s->reply_queue_head = ldl_le_pci_dma(pcid, s->producer_pa); + s->reply_queue_tail = ldl_le_pci_dma(pcid, s->consumer_pa); flags = le32_to_cpu(initq->flags); if (flags & MFI_QUEUE_FLAG_CONTEXT64) { s->flags |= MEGASAS_MASK_USE_QUEUE64; @@ -1951,14 +1948,14 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr, * Always read 64bit context, top bits will be * masked out if required in megasas_enqueue_frame() */ - frame_context = megasas_frame_get_context(frame_addr); + frame_context = megasas_frame_get_context(s, frame_addr); cmd = megasas_enqueue_frame(s, frame_addr, frame_context, frame_count); if (!cmd) { /* reply queue full */ trace_megasas_frame_busy(frame_addr); - megasas_frame_set_scsi_status(frame_addr, BUSY); - megasas_frame_set_cmd_status(frame_addr, MFI_STAT_SCSI_DONE_WITH_ERROR); + megasas_frame_set_scsi_status(s, frame_addr, BUSY); + megasas_frame_set_cmd_status(s, frame_addr, MFI_STAT_SCSI_DONE_WITH_ERROR); megasas_complete_frame(s, frame_context); s->event_count++; return; @@ -1993,7 +1990,7 @@ static void megasas_handle_frame(MegasasState *s, uint64_t frame_addr, if (cmd->frame) { cmd->frame->header.cmd_status = frame_status; } else { - megasas_frame_set_cmd_status(frame_addr, frame_status); + megasas_frame_set_cmd_status(s, frame_addr, frame_status); } megasas_unmap_frame(s, cmd); megasas_complete_frame(s, cmd->context); From 0dc40f28518dee8aa95abd330a53f06179e71995 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 23 Mar 2015 17:28:13 +0100 Subject: [PATCH 07/14] vmw_pvscsi: use PCI DMA APIs It is wrong to use address_space_memory directly, because there could be an IOMMU in the middle. Passing the entire PVSCSIRingInfo to RS_GET_FIELD and RS_SET_FIELD makes it easy to go back to the PVSCSIState. Signed-off-by: Paolo Bonzini --- hw/scsi/vmw_pvscsi.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index d3a92fbabf..c6148d380e 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -42,12 +42,12 @@ #define PVSCSI_MAX_CMD_DATA_WORDS \ (sizeof(PVSCSICmdDescSetupRings)/sizeof(uint32_t)) -#define RS_GET_FIELD(rs_pa, field) \ - (ldl_le_phys(&address_space_memory, \ - rs_pa + offsetof(struct PVSCSIRingsState, field))) -#define RS_SET_FIELD(rs_pa, field, val) \ - (stl_le_phys(&address_space_memory, \ - rs_pa + offsetof(struct PVSCSIRingsState, field), val)) +#define RS_GET_FIELD(m, field) \ + (ldl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ + (m)->rs_pa + offsetof(struct PVSCSIRingsState, field))) +#define RS_SET_FIELD(m, field, val) \ + (stl_le_pci_dma(&container_of(m, PVSCSIState, rings)->parent_obj, \ + (m)->rs_pa + offsetof(struct PVSCSIRingsState, field), val)) #define TYPE_PVSCSI "pvscsi" #define PVSCSI(obj) OBJECT_CHECK(PVSCSIState, (obj), TYPE_PVSCSI) @@ -153,13 +153,13 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri) m->cmp_ring_pages_pa[i] = ri->cmpRingPPNs[i] << VMW_PAGE_SHIFT; } - RS_SET_FIELD(m->rs_pa, reqProdIdx, 0); - RS_SET_FIELD(m->rs_pa, reqConsIdx, 0); - RS_SET_FIELD(m->rs_pa, reqNumEntriesLog2, txr_len_log2); + RS_SET_FIELD(m, reqProdIdx, 0); + RS_SET_FIELD(m, reqConsIdx, 0); + RS_SET_FIELD(m, reqNumEntriesLog2, txr_len_log2); - RS_SET_FIELD(m->rs_pa, cmpProdIdx, 0); - RS_SET_FIELD(m->rs_pa, cmpConsIdx, 0); - RS_SET_FIELD(m->rs_pa, cmpNumEntriesLog2, rxr_len_log2); + RS_SET_FIELD(m, cmpProdIdx, 0); + RS_SET_FIELD(m, cmpConsIdx, 0); + RS_SET_FIELD(m, cmpNumEntriesLog2, rxr_len_log2); trace_pvscsi_ring_init_data(txr_len_log2, rxr_len_log2); @@ -185,9 +185,9 @@ pvscsi_ring_init_msg(PVSCSIRingInfo *m, PVSCSICmdDescSetupMsgRing *ri) m->msg_ring_pages_pa[i] = ri->ringPPNs[i] << VMW_PAGE_SHIFT; } - RS_SET_FIELD(m->rs_pa, msgProdIdx, 0); - RS_SET_FIELD(m->rs_pa, msgConsIdx, 0); - RS_SET_FIELD(m->rs_pa, msgNumEntriesLog2, len_log2); + RS_SET_FIELD(m, msgProdIdx, 0); + RS_SET_FIELD(m, msgConsIdx, 0); + RS_SET_FIELD(m, msgNumEntriesLog2, len_log2); trace_pvscsi_ring_init_msg(len_log2); @@ -213,7 +213,7 @@ pvscsi_ring_cleanup(PVSCSIRingInfo *mgr) static hwaddr pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr) { - uint32_t ready_ptr = RS_GET_FIELD(mgr->rs_pa, reqProdIdx); + uint32_t ready_ptr = RS_GET_FIELD(mgr, reqProdIdx); if (ready_ptr != mgr->consumed_ptr) { uint32_t next_ready_ptr = @@ -233,7 +233,7 @@ pvscsi_ring_pop_req_descr(PVSCSIRingInfo *mgr) static void pvscsi_ring_flush_req(PVSCSIRingInfo *mgr) { - RS_SET_FIELD(mgr->rs_pa, reqConsIdx, mgr->consumed_ptr); + RS_SET_FIELD(mgr, reqConsIdx, mgr->consumed_ptr); } static hwaddr @@ -278,14 +278,14 @@ pvscsi_ring_flush_cmp(PVSCSIRingInfo *mgr) trace_pvscsi_ring_flush_cmp(mgr->filled_cmp_ptr); - RS_SET_FIELD(mgr->rs_pa, cmpProdIdx, mgr->filled_cmp_ptr); + RS_SET_FIELD(mgr, cmpProdIdx, mgr->filled_cmp_ptr); } static bool pvscsi_ring_msg_has_room(PVSCSIRingInfo *mgr) { - uint32_t prodIdx = RS_GET_FIELD(mgr->rs_pa, msgProdIdx); - uint32_t consIdx = RS_GET_FIELD(mgr->rs_pa, msgConsIdx); + uint32_t prodIdx = RS_GET_FIELD(mgr, msgProdIdx); + uint32_t consIdx = RS_GET_FIELD(mgr, msgConsIdx); return (prodIdx - consIdx) < (mgr->msg_len_mask + 1); } @@ -298,7 +298,7 @@ pvscsi_ring_flush_msg(PVSCSIRingInfo *mgr) trace_pvscsi_ring_flush_msg(mgr->filled_msg_ptr); - RS_SET_FIELD(mgr->rs_pa, msgProdIdx, mgr->filled_msg_ptr); + RS_SET_FIELD(mgr, msgProdIdx, mgr->filled_msg_ptr); } static void From 78fa62ff1bc0d66f0115b7147c4eb260ad22022a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Wed, 25 Mar 2015 09:18:48 +0100 Subject: [PATCH 08/14] nbd: Fix up comment after commit e140177 Signed-off-by: Markus Armbruster Message-Id: <1427271528-11624-1-git-send-email-armbru@redhat.com> Signed-off-by: Paolo Bonzini --- blockdev-nbd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/blockdev-nbd.c b/blockdev-nbd.c index b29e456f1f..85cda4cfa7 100644 --- a/blockdev-nbd.c +++ b/blockdev-nbd.c @@ -47,8 +47,9 @@ void qmp_nbd_server_start(SocketAddress *addr, Error **errp) } } -/* Hook into the BlockDriverState notifiers to close the export when - * the file is closed. +/* + * Hook into the BlockBackend notifiers to close the export when the + * backend is closed. */ typedef struct NBDCloseNotifier { Notifier n; From 1d5bfde1b978b57156d851d140b99eac8b2adbe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dirk=20M=C3=BCller?= Date: Tue, 24 Mar 2015 23:11:03 +0100 Subject: [PATCH 09/14] m68k: memory: Replace memory_region_init_ram with memory_region_allocate_system_memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 0b183fc871:"memory: move mem_path handling to memory_region_allocate_system_memory" split memory_region_init_ram and memory_region_init_ram_from_file. Also it moved mem-path handling a step up from memory_region_init_ram to memory_region_allocate_system_memory. Therefore for any board that uses memory_region_init_ram directly, -mem-path is not supported. Fix this by replacing memory_region_init_ram with memory_region_allocate_system_memory. Signed-off-by: Dirk Mueller Message-Id: Reviewed-by: Andreas Färber Signed-off-by: Paolo Bonzini --- hw/m68k/an5206.c | 3 +-- hw/m68k/dummy_m68k.c | 4 ++-- hw/m68k/mcf5208.c | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c index f1f13504c0..f63ab2b94d 100644 --- a/hw/m68k/an5206.c +++ b/hw/m68k/an5206.c @@ -50,8 +50,7 @@ static void an5206_init(MachineState *machine) env->rambar0 = AN5206_RAMBAR_ADDR | 1; /* DRAM at address zero */ - memory_region_init_ram(ram, NULL, "an5206.ram", ram_size, &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "an5206.ram", ram_size); memory_region_add_subregion(address_space_mem, 0, ram); /* Internal SRAM. */ diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c index 278f4c03d3..5b77d930e4 100644 --- a/hw/m68k/dummy_m68k.c +++ b/hw/m68k/dummy_m68k.c @@ -42,8 +42,8 @@ static void dummy_m68k_init(MachineState *machine) env->vbr = 0; /* RAM at address zero */ - memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size, &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "dummy_m68k.ram", + ram_size); memory_region_add_subregion(address_space_mem, 0, ram); /* Load kernel. */ diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index a01a4458e6..326a42d27e 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -218,8 +218,7 @@ static void mcf5208evb_init(MachineState *machine) /* TODO: Configure BARs. */ /* DRAM at 0x40000000 */ - memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size, &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "mcf5208.ram", ram_size); memory_region_add_subregion(address_space_mem, 0x40000000, ram); /* Internal SRAM. */ From 6a926fbc6fff58598cce9404019204090a8e8361 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dirk=20M=C3=BCller?= Date: Tue, 24 Mar 2015 22:28:15 +0100 Subject: [PATCH 10/14] mips: memory: Replace memory_region_init_ram with memory_region_allocate_system_memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 0b183fc871:"memory: move mem_path handling to memory_region_allocate_system_memory" split memory_region_init_ram and memory_region_init_ram_from_file. Also it moved mem-path handling a step up from memory_region_init_ram to memory_region_allocate_system_memory. Therefore for any board that uses memory_region_init_ram directly, -mem-path is not supported. Fix this by replacing memory_region_init_ram with memory_region_allocate_system_memory. Signed-off-by: Dirk Mueller Message-Id: Reviewed-by: Andreas Färber Acked-by: Leon Alrae Signed-off-by: Paolo Bonzini --- hw/mips/mips_fulong2e.c | 3 +-- hw/mips/mips_jazz.c | 5 ++--- hw/mips/mips_malta.c | 5 ++--- hw/mips/mips_mipssim.c | 5 ++--- hw/mips/mips_r4k.c | 3 +-- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index ea73585a92..4aae64a9ec 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -301,8 +301,7 @@ static void mips_fulong2e_init(MachineState *machine) bios_size = 1024 * 1024; /* allocate RAM */ - memory_region_init_ram(ram, NULL, "fulong2e.ram", ram_size, &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "fulong2e.ram", ram_size); memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size, &error_abort); vmstate_register_ram_global(bios); diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index ef5dd7d5ab..07f3c270d4 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -182,9 +182,8 @@ static void mips_jazz_init(MachineState *machine, cc->do_unassigned_access = mips_jazz_do_unassigned_access; /* allocate RAM */ - memory_region_init_ram(ram, NULL, "mips_jazz.ram", machine->ram_size, - &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "mips_jazz.ram", + machine->ram_size); memory_region_add_subregion(address_space, 0, ram); memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE, diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 533b2e60fe..b0fa71a514 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -993,9 +993,8 @@ void mips_malta_init(MachineState *machine) } /* register RAM at high address where it is undisturbed by IO */ - memory_region_init_ram(ram_high, NULL, "mips_malta.ram", ram_size, - &error_abort); - vmstate_register_ram_global(ram_high); + memory_region_allocate_system_memory(ram_high, NULL, "mips_malta.ram", + ram_size); memory_region_add_subregion(system_memory, 0x80000000, ram_high); /* alias for pre IO hole access */ diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index 5d44c3f73d..61f74a6315 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -171,9 +171,8 @@ mips_mipssim_init(MachineState *machine) qemu_register_reset(main_cpu_reset, reset_info); /* Allocate RAM. */ - memory_region_init_ram(ram, NULL, "mips_mipssim.ram", ram_size, - &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "mips_mipssim.ram", + ram_size); memory_region_init_ram(bios, NULL, "mips_mipssim.bios", BIOS_SIZE, &error_abort); vmstate_register_ram_global(bios); diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 52564be692..66e2a58e86 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -205,8 +205,7 @@ void mips_r4k_init(MachineState *machine) ((unsigned int)ram_size / (1 << 20))); exit(1); } - memory_region_init_ram(ram, NULL, "mips_r4k.ram", ram_size, &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "mips_r4k.ram", ram_size); memory_region_add_subregion(address_space_mem, 0, ram); From 8e7ba4ed3a0b68ab35736c7859fd950f6705e0cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dirk=20M=C3=BCller?= Date: Tue, 24 Mar 2015 22:30:13 +0100 Subject: [PATCH 11/14] sparc: memory: Replace memory_region_init_ram with memory_region_allocate_system_memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 0b183fc871:"memory: move mem_path handling to memory_region_allocate_system_memory" split memory_region_init_ram and memory_region_init_ram_from_file. Also it moved mem-path handling a step up from memory_region_init_ram to memory_region_allocate_system_memory. Therefore for any board that uses memory_region_init_ram directly, -mem-path is not supported. Fix this by replacing memory_region_init_ram with memory_region_allocate_system_memory. Signed-off-by: Dirk Mueller Message-Id: Reviewed-by: Andreas Färber Signed-off-by: Paolo Bonzini --- hw/sparc/leon3.c | 3 +-- hw/sparc/sun4m.c | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index e41ec0bf3a..7f5dcd6d85 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -151,8 +151,7 @@ static void leon3_generic_hw_init(MachineState *machine) exit(1); } - memory_region_init_ram(ram, NULL, "leon3.ram", ram_size, &error_abort); - vmstate_register_ram_global(ram); + memory_region_allocate_system_memory(ram, NULL, "leon3.ram", ram_size); memory_region_add_subregion(address_space_mem, 0x40000000, ram); /* Allocate BIOS */ diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 255ba1f4f5..a69bf2da45 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -805,9 +805,8 @@ static int ram_init1(SysBusDevice *dev) { RamDevice *d = SUN4M_RAM(dev); - memory_region_init_ram(&d->ram, OBJECT(d), "sun4m.ram", d->size, - &error_abort); - vmstate_register_ram_global(&d->ram); + memory_region_allocate_system_memory(&d->ram, OBJECT(d), "sun4m.ram", + d->size); sysbus_init_mmio(dev, &d->ram); return 0; } From f18c69cfc554cf9776eb3c35b7510e17541afacb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 25 Mar 2015 14:14:56 +0100 Subject: [PATCH 12/14] exec: avoid possible overwriting of mmaped area in qemu_ram_remap It is not necessary to munmap an area before remapping it with MAP_FIXED; if the memory region specified by addr and len overlaps pages of any existing mapping, then the overlapped part of the existing mapping will be discarded. On the other hand, if QEMU does munmap the pages, there is a small probability that another mmap sneaks in and catches the just-freed portion of the address space. In effect, munmap followed by mmap(MAP_FIXED) is a use-after-free error, and Coverity flags it as such. Fix it. Reviewed-by: Gonglei Signed-off-by: Paolo Bonzini --- exec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/exec.c b/exec.c index 8b922db612..6d1e1e4c75 100644 --- a/exec.c +++ b/exec.c @@ -1638,7 +1638,6 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) abort(); } else { flags = MAP_FIXED; - munmap(vaddr, length); if (block->fd >= 0) { flags |= (block->flags & RAM_SHARED ? MAP_SHARED : MAP_PRIVATE); From fe75270cb619549b2aa1ba59bd202faf306204a1 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Thu, 26 Mar 2015 20:57:43 +0800 Subject: [PATCH 13/14] misc: fix typos in copyright declaration Add a space after comma. Signed-off-by: Gonglei Message-Id: <1427374663-10168-1-git-send-email-arei.gonglei@huawei.com> Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini --- bootdevice.c | 2 +- tests/usb-hcd-ohci-test.c | 2 +- tests/usb-hcd-uhci-test.c | 2 +- tests/usb-hcd-xhci-test.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bootdevice.c b/bootdevice.c index 673bfef60c..3cdc0d7b22 100644 --- a/bootdevice.c +++ b/bootdevice.c @@ -1,7 +1,7 @@ /* * QEMU Boot Device Implement * - * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO.,LTD. + * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO., LTD. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/tests/usb-hcd-ohci-test.c b/tests/usb-hcd-ohci-test.c index 1160bde840..fa592d487c 100644 --- a/tests/usb-hcd-ohci-test.c +++ b/tests/usb-hcd-ohci-test.c @@ -1,7 +1,7 @@ /* * QTest testcase for USB OHCI controller * - * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO.,LTD. + * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO., LTD. * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. diff --git a/tests/usb-hcd-uhci-test.c b/tests/usb-hcd-uhci-test.c index 6d631cf366..a96b71683c 100644 --- a/tests/usb-hcd-uhci-test.c +++ b/tests/usb-hcd-uhci-test.c @@ -1,7 +1,7 @@ /* * QTest testcase for USB UHCI controller * - * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO.,LTD. + * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO., LTD. * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. diff --git a/tests/usb-hcd-xhci-test.c b/tests/usb-hcd-xhci-test.c index adf261e963..56ab367316 100644 --- a/tests/usb-hcd-xhci-test.c +++ b/tests/usb-hcd-xhci-test.c @@ -1,7 +1,7 @@ /* * QTest testcase for USB xHCI controller * - * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO.,LTD. + * Copyright (c) 2014 HUAWEI TECHNOLOGIES CO., LTD. * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. From 4020db0475b3e527b3bdc97dff873c2be9da2698 Mon Sep 17 00:00:00 2001 From: Ting Wang Date: Thu, 26 Mar 2015 15:42:32 +0800 Subject: [PATCH 14/14] virtio-scsi-dataplane: fix memory leak for VirtIOSCSIVring VirtIOSCSIVring which allocated in virtio_scsi_vring_init should be free when dataplane has been stopped or failed to start. Signed-off-by: Ting Wang Message-Id: <1427355752-25844-1-git-send-email-kathy.wangting@huawei.com> Signed-off-by: Paolo Bonzini --- hw/scsi/virtio-scsi-dataplane.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index c069cd764c..5575648a98 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -182,13 +182,19 @@ static void virtio_scsi_vring_teardown(VirtIOSCSI *s) if (s->ctrl_vring) { vring_teardown(&s->ctrl_vring->vring, vdev, 0); + g_slice_free(VirtIOSCSIVring, s->ctrl_vring); + s->ctrl_vring = NULL; } if (s->event_vring) { vring_teardown(&s->event_vring->vring, vdev, 1); + g_slice_free(VirtIOSCSIVring, s->event_vring); + s->event_vring = NULL; } if (s->cmd_vrings) { for (i = 0; i < vs->conf.num_queues && s->cmd_vrings[i]; i++) { vring_teardown(&s->cmd_vrings[i]->vring, vdev, 2 + i); + g_slice_free(VirtIOSCSIVring, s->cmd_vrings[i]); + s->cmd_vrings[i] = NULL; } free(s->cmd_vrings); s->cmd_vrings = NULL;