summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS3
-rw-r--r--Makefile.objs1
-rw-r--r--bsd-user/main.c1
-rw-r--r--hw/dma/rc4030.c81
-rw-r--r--hw/i386/trace-events4
-rw-r--r--hw/ide/ahci.c1
-rw-r--r--hw/ide/core.c4
-rw-r--r--hw/ide/qdev.c11
-rw-r--r--hw/mem/trace-events5
-rw-r--r--hw/s390x/css.c12
-rw-r--r--hw/s390x/s390-pci-bus.c48
-rw-r--r--hw/s390x/s390-pci-bus.h4
-rw-r--r--hw/s390x/s390-pci-inst.c6
-rw-r--r--hw/virtio/trace-events5
-rw-r--r--include/hw/ide/internal.h1
-rw-r--r--io/trace-events6
-rw-r--r--linux-user/main.c1
-rw-r--r--pc-bios/s390-ccw.imgbin26440 -> 26392 bytes
-rw-r--r--pc-bios/s390-ccw/virtio.c3
-rw-r--r--qom/cpu.c6
-rw-r--r--stubs/trace-control.c6
-rw-r--r--target-s390x/kvm.c13
-rw-r--r--trace-events33
-rw-r--r--trace/control-target.c40
-rw-r--r--trace/control.c19
-rw-r--r--trace/control.h19
-rw-r--r--util/trace-events19
-rw-r--r--vl.c1
28 files changed, 202 insertions, 151 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index f3c1f7f307..63cf21fdb1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -145,7 +145,7 @@ F: disas/microblaze.c
 
 MIPS
 M: Aurelien Jarno <aurelien@aurel32.net>
-M: Leon Alrae <leon.alrae@imgtec.com>
+M: Yongbok Kim <yongbok.kim@imgtec.com>
 S: Maintained
 F: target-mips/
 F: hw/mips/
@@ -772,6 +772,7 @@ M: John Snow <jsnow@redhat.com>
 L: qemu-block@nongnu.org
 S: Supported
 F: include/hw/ide.h
+F: include/hw/ide/
 F: hw/ide/
 F: hw/block/block.c
 F: hw/block/cdrom.c
diff --git a/Makefile.objs b/Makefile.objs
index a8e022452f..02fb8e76b8 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -142,6 +142,7 @@ trace-events-y += hw/dma/trace-events
 trace-events-y += hw/sparc/trace-events
 trace-events-y += hw/sd/trace-events
 trace-events-y += hw/isa/trace-events
+trace-events-y += hw/mem/trace-events
 trace-events-y += hw/i386/trace-events
 trace-events-y += hw/9pfs/trace-events
 trace-events-y += hw/ppc/trace-events
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 35125b720f..d803d3e10c 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -1116,7 +1116,6 @@ int main(int argc, char **argv)
         gdbserver_start (gdbstub_port);
         gdb_handlesig(cpu, 0);
     }
-    trace_init_vcpu_events();
     cpu_loop(env);
     /* never exits */
     return 0;
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index 2f2576fafb..17c8518fea 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -616,34 +616,9 @@ static void rc4030_reset(DeviceState *dev)
     qemu_irq_lower(s->jazz_bus_irq);
 }
 
-static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
+static int rc4030_post_load(void *opaque, int version_id)
 {
     rc4030State* s = opaque;
-    int i, j;
-
-    if (version_id != 2)
-        return -EINVAL;
-
-    s->config = qemu_get_be32(f);
-    s->invalid_address_register = qemu_get_be32(f);
-    for (i = 0; i < 8; i++)
-        for (j = 0; j < 4; j++)
-            s->dma_regs[i][j] = qemu_get_be32(f);
-    s->dma_tl_base = qemu_get_be32(f);
-    s->dma_tl_limit = qemu_get_be32(f);
-    s->cache_maint = qemu_get_be32(f);
-    s->remote_failed_address = qemu_get_be32(f);
-    s->memory_failed_address = qemu_get_be32(f);
-    s->cache_ptag = qemu_get_be32(f);
-    s->cache_ltag = qemu_get_be32(f);
-    s->cache_bmask = qemu_get_be32(f);
-    s->memory_refresh_rate = qemu_get_be32(f);
-    s->nvram_protect = qemu_get_be32(f);
-    for (i = 0; i < 15; i++)
-        s->rem_speed[i] = qemu_get_be32(f);
-    s->imr_jazz = qemu_get_be32(f);
-    s->isr_jazz = qemu_get_be32(f);
-    s->itr = qemu_get_be32(f);
 
     set_next_tick(s);
     update_jazz_irq(s);
@@ -651,32 +626,31 @@ static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static void rc4030_save(QEMUFile *f, void *opaque)
-{
-    rc4030State* s = opaque;
-    int i, j;
-
-    qemu_put_be32(f, s->config);
-    qemu_put_be32(f, s->invalid_address_register);
-    for (i = 0; i < 8; i++)
-        for (j = 0; j < 4; j++)
-            qemu_put_be32(f, s->dma_regs[i][j]);
-    qemu_put_be32(f, s->dma_tl_base);
-    qemu_put_be32(f, s->dma_tl_limit);
-    qemu_put_be32(f, s->cache_maint);
-    qemu_put_be32(f, s->remote_failed_address);
-    qemu_put_be32(f, s->memory_failed_address);
-    qemu_put_be32(f, s->cache_ptag);
-    qemu_put_be32(f, s->cache_ltag);
-    qemu_put_be32(f, s->cache_bmask);
-    qemu_put_be32(f, s->memory_refresh_rate);
-    qemu_put_be32(f, s->nvram_protect);
-    for (i = 0; i < 15; i++)
-        qemu_put_be32(f, s->rem_speed[i]);
-    qemu_put_be32(f, s->imr_jazz);
-    qemu_put_be32(f, s->isr_jazz);
-    qemu_put_be32(f, s->itr);
-}
+static const VMStateDescription vmstate_rc4030 = {
+    .name = "rc4030",
+    .version_id = 3,
+    .post_load = rc4030_post_load,
+    .fields = (VMStateField []) {
+        VMSTATE_UINT32(config, rc4030State),
+        VMSTATE_UINT32(invalid_address_register, rc4030State),
+        VMSTATE_UINT32_2DARRAY(dma_regs, rc4030State, 8, 4),
+        VMSTATE_UINT32(dma_tl_base, rc4030State),
+        VMSTATE_UINT32(dma_tl_limit, rc4030State),
+        VMSTATE_UINT32(cache_maint, rc4030State),
+        VMSTATE_UINT32(remote_failed_address, rc4030State),
+        VMSTATE_UINT32(memory_failed_address, rc4030State),
+        VMSTATE_UINT32(cache_ptag, rc4030State),
+        VMSTATE_UINT32(cache_ltag, rc4030State),
+        VMSTATE_UINT32(cache_bmask, rc4030State),
+        VMSTATE_UINT32(memory_refresh_rate, rc4030State),
+        VMSTATE_UINT32(nvram_protect, rc4030State),
+        VMSTATE_UINT32_ARRAY(rem_speed, rc4030State, 16),
+        VMSTATE_UINT32(imr_jazz, rc4030State),
+        VMSTATE_UINT32(isr_jazz, rc4030State),
+        VMSTATE_UINT32(itr, rc4030State),
+        VMSTATE_END_OF_LIST()
+    }
+};
 
 static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write)
 {
@@ -753,8 +727,6 @@ static void rc4030_initfn(Object *obj)
     sysbus_init_irq(sysbus, &s->timer_irq);
     sysbus_init_irq(sysbus, &s->jazz_bus_irq);
 
-    register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
-
     sysbus_init_mmio(sysbus, &s->iomem_chipset);
     sysbus_init_mmio(sysbus, &s->iomem_jazzio);
 }
@@ -813,6 +785,7 @@ static void rc4030_class_init(ObjectClass *klass, void *class_data)
     dc->realize = rc4030_realize;
     dc->unrealize = rc4030_unrealize;
     dc->reset = rc4030_reset;
+    dc->vmsd = &vmstate_rc4030;
 }
 
 static const TypeInfo rc4030_info = {
diff --git a/hw/i386/trace-events b/hw/i386/trace-events
index 1938b988d9..d2b497327e 100644
--- a/hw/i386/trace-events
+++ b/hw/i386/trace-events
@@ -7,10 +7,6 @@ xen_platform_log(char *s) "xen platform: %s"
 xen_pv_mmio_read(uint64_t addr) "WARNING: read from Xen PV Device MMIO space (address %"PRIx64")"
 xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (address %"PRIx64")"
 
-# hw/i386/pc.c
-mhp_pc_dimm_assigned_slot(int slot) "%d"
-mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
-
 # hw/i386/x86-iommu.c
 x86_iommu_iec_notify(bool global, uint32_t index, uint32_t mask) "Notify IEC invalidation: global=%d index=%" PRIu32 " mask=%" PRIu32
 
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index f3438ad78a..63ead21047 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -948,6 +948,7 @@ static void ncq_cb(void *opaque, int ret)
     NCQTransferState *ncq_tfs = (NCQTransferState *)opaque;
     IDEState *ide_state = &ncq_tfs->drive->port.ifs[0];
 
+    ncq_tfs->aiocb = NULL;
     if (ret == -ECANCELED) {
         return;
     }
diff --git a/hw/ide/core.c b/hw/ide/core.c
index b0e42a6562..7291677109 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -908,7 +908,7 @@ eot:
 
 static void ide_sector_start_dma(IDEState *s, enum ide_dma_cmd dma_cmd)
 {
-    s->status = READY_STAT | SEEK_STAT | DRQ_STAT | BUSY_STAT;
+    s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
     s->io_buffer_size = 0;
     s->dma_cmd = dma_cmd;
 
@@ -2582,7 +2582,7 @@ static void ide_restart_cb(void *opaque, int running, RunState state)
 void ide_register_restart_cb(IDEBus *bus)
 {
     if (bus->dma->ops->restart_dma) {
-        qemu_add_vm_change_state_handler(ide_restart_cb, bus);
+        bus->vmstate = qemu_add_vm_change_state_handler(ide_restart_cb, bus);
     }
 }
 
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 2eb055ae70..dbaa75cf59 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -31,6 +31,7 @@
 /* --------------------------------- */
 
 static char *idebus_get_fw_dev_path(DeviceState *dev);
+static void idebus_unrealize(DeviceState *qdev, Error **errp);
 
 static Property ide_props[] = {
     DEFINE_PROP_UINT32("unit", IDEDevice, unit, -1),
@@ -44,6 +45,15 @@ static void ide_bus_class_init(ObjectClass *klass, void *data)
     k->get_fw_dev_path = idebus_get_fw_dev_path;
 }
 
+static void idebus_unrealize(DeviceState *qdev, Error **errp)
+{
+    IDEBus *bus = DO_UPCAST(IDEBus, qbus, qdev->parent_bus);
+
+    if (bus->vmstate) {
+        qemu_del_vm_change_state_handler(bus->vmstate);
+    }
+}
+
 static const TypeInfo ide_bus_info = {
     .name = TYPE_IDE_BUS,
     .parent = TYPE_BUS,
@@ -355,6 +365,7 @@ static void ide_device_class_init(ObjectClass *klass, void *data)
     k->init = ide_qdev_init;
     set_bit(DEVICE_CATEGORY_STORAGE, k->categories);
     k->bus_type = TYPE_IDE_BUS;
+    k->unrealize = idebus_unrealize;
     k->props = ide_props;
 }
 
diff --git a/hw/mem/trace-events b/hw/mem/trace-events
new file mode 100644
index 0000000000..323c3c10d5
--- /dev/null
+++ b/hw/mem/trace-events
@@ -0,0 +1,5 @@
+# See docs/trace-events.txt for syntax documentation.
+
+# hw/mem/pc-dimm.c
+mhp_pc_dimm_assigned_slot(int slot) "%d"
+mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index b0e81efc27..0f2580d644 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -775,7 +775,7 @@ int css_do_xsch(SubchDev *sch)
     PMCW *p = &sch->curr_status.pmcw;
     int ret;
 
-    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
         ret = -ENODEV;
         goto out;
     }
@@ -815,7 +815,7 @@ int css_do_csch(SubchDev *sch)
     PMCW *p = &sch->curr_status.pmcw;
     int ret;
 
-    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
         ret = -ENODEV;
         goto out;
     }
@@ -837,7 +837,7 @@ int css_do_hsch(SubchDev *sch)
     PMCW *p = &sch->curr_status.pmcw;
     int ret;
 
-    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
         ret = -ENODEV;
         goto out;
     }
@@ -913,7 +913,7 @@ int css_do_ssch(SubchDev *sch, ORB *orb)
     PMCW *p = &sch->curr_status.pmcw;
     int ret;
 
-    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
         ret = -ENODEV;
         goto out;
     }
@@ -990,7 +990,7 @@ int css_do_tsch_get_irb(SubchDev *sch, IRB *target_irb, int *irb_len)
     uint16_t stctl;
     IRB irb;
 
-    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
         return 3;
     }
 
@@ -1196,7 +1196,7 @@ int css_do_rsch(SubchDev *sch)
     PMCW *p = &sch->curr_status.pmcw;
     int ret;
 
-    if (!(p->flags & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA))) {
+    if (~(p->flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) {
         ret = -ENODEV;
         goto out;
     }
diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c
index ac8f06d9e7..b7f8bca1fd 100644
--- a/hw/s390x/s390-pci-bus.c
+++ b/hw/s390x/s390-pci-bus.c
@@ -383,7 +383,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
     uint64_t pte;
     uint32_t flags;
     S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, iommu_mr);
-    S390pciState *s;
     IOMMUTLBEntry ret = {
         .target_as = &address_space_memory,
         .iova = 0,
@@ -405,19 +404,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr,
 
     DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
 
-    s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent);
-    /* s390 does not have an APIC mapped to main storage so we use
-     * a separate AddressSpace only for msix notifications
-     */
-    if (addr == ZPCI_MSI_ADDR) {
-        ret.target_as = &s->msix_notify_as;
-        ret.iova = addr;
-        ret.translated_addr = addr;
-        ret.addr_mask = 0xfff;
-        ret.perm = IOMMU_RW;
-        return ret;
-    }
-
     if (addr < pbdev->pba || addr > pbdev->pal) {
         return ret;
     }
@@ -476,7 +462,7 @@ static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
 static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
                                 unsigned int size)
 {
-    S390PCIBusDevice *pbdev;
+    S390PCIBusDevice *pbdev = opaque;
     uint32_t io_int_word;
     uint32_t idx = data >> ZPCI_MSI_VEC_BITS;
     uint32_t vec = data & ZPCI_MSI_VEC_MASK;
@@ -486,7 +472,6 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data,
 
     DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data, idx, vec);
 
-    pbdev = s390_pci_find_dev_by_idx(idx);
     if (!pbdev) {
         e |= (vec << ERR_EVENT_MVN_OFFSET);
         s390_pci_generate_error_event(ERR_EVENT_NOMSI, idx, 0, addr, e);
@@ -548,10 +533,6 @@ static void s390_pcihost_init_as(S390pciState *s)
 
         s->iommu[i] = iommu;
     }
-
-    memory_region_init_io(&s->msix_notify_mr, OBJECT(s),
-                          &s390_msi_ctrl_ops, s, "msix-s390", UINT64_MAX);
-    address_space_init(&s->msix_notify_as, &s->msix_notify_mr, "msix-pci");
 }
 
 static int s390_pcihost_init(SysBusDevice *dev)
@@ -581,7 +562,7 @@ static int s390_pcihost_init(SysBusDevice *dev)
     return 0;
 }
 
-static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
+static int s390_pci_setup_msix(S390PCIBusDevice *pbdev)
 {
     uint8_t pos;
     uint16_t ctrl;
@@ -609,6 +590,26 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev)
     return 0;
 }
 
+static void s390_pci_msix_init(S390PCIBusDevice *pbdev)
+{
+    char *name;
+
+    name = g_strdup_printf("msix-s390-%04x", pbdev->uid);
+
+    memory_region_init_io(&pbdev->msix_notify_mr, OBJECT(pbdev),
+                          &s390_msi_ctrl_ops, pbdev, name, PAGE_SIZE);
+    memory_region_add_subregion(&pbdev->iommu->mr, ZPCI_MSI_ADDR,
+                                &pbdev->msix_notify_mr);
+
+    g_free(name);
+}
+
+static void s390_pci_msix_free(S390PCIBusDevice *pbdev)
+{
+    memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->msix_notify_mr);
+    object_unparent(OBJECT(&pbdev->msix_notify_mr));
+}
+
 static S390PCIBusDevice *s390_pci_device_new(const char *target)
 {
     DeviceState *dev = NULL;
@@ -662,7 +663,9 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev,
         pbdev->pdev = pdev;
         pbdev->iommu = s->iommu[PCI_SLOT(pdev->devfn)];
         pbdev->state = ZPCI_FS_STANDBY;
-        s390_pcihost_setup_msix(pbdev);
+
+        s390_pci_msix_init(pbdev);
+        s390_pci_setup_msix(pbdev);
 
         if (dev->hotplugged) {
             s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY,
@@ -749,6 +752,7 @@ static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev,
     s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED,
                                  pbdev->fh, pbdev->fid);
     object_unparent(OBJECT(pci_dev));
+    s390_pci_msix_free(pbdev);
     pbdev->pdev = NULL;
     pbdev->state = ZPCI_FS_RESERVED;
 out:
diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h
index 4f564e02f2..7f2701301e 100644
--- a/hw/s390x/s390-pci-bus.h
+++ b/hw/s390x/s390-pci-bus.h
@@ -82,6 +82,7 @@
 #define ZPCI_EDMA_ADDR 0x1ffffffffffffffULL
 
 #define PAGE_SHIFT      12
+#define PAGE_SIZE       (1 << PAGE_SHIFT)
 #define PAGE_MASK       (~(PAGE_SIZE-1))
 #define PAGE_DEFAULT_ACC        0
 #define PAGE_DEFAULT_KEY        (PAGE_DEFAULT_ACC << 4)
@@ -283,6 +284,7 @@ typedef struct S390PCIBusDevice {
     AdapterRoutes routes;
     S390PCIIOMMU *iommu;
     MemoryRegion iommu_mr;
+    MemoryRegion msix_notify_mr;
     IndAddr *summary_ind;
     IndAddr *indicator;
     QEMUTimer *release_timer;
@@ -297,8 +299,6 @@ typedef struct S390pciState {
     S390PCIBus *bus;
     S390PCIBusDevice *pbdev[PCI_SLOT_MAX];
     S390PCIIOMMU *iommu[PCI_SLOT_MAX];
-    AddressSpace msix_notify_as;
-    MemoryRegion msix_notify_mr;
     QTAILQ_HEAD(, SeiContainer) pending_sei;
 } S390pciState;
 
diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index f069b110b4..80a51049ca 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -315,6 +315,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
     S390PCIBusDevice *pbdev;
     uint64_t offset;
     uint64_t data;
+    MemoryRegion *mr;
     uint8_t len;
     uint32_t fh;
     uint8_t pcias;
@@ -363,7 +364,7 @@ int pcilg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
             program_interrupt(env, PGM_OPERAND, 4);
             return 0;
         }
-        MemoryRegion *mr = pbdev->pdev->io_regions[pcias].memory;
+        mr = pbdev->pdev->io_regions[pcias].memory;
         memory_region_dispatch_read(mr, offset, &data, len,
                                     MEMTXATTRS_UNSPECIFIED);
     } else if (pcias == 15) {
@@ -442,6 +443,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
     CPUS390XState *env = &cpu->env;
     uint64_t offset, data;
     S390PCIBusDevice *pbdev;
+    MemoryRegion *mr;
     uint8_t len;
     uint32_t fh;
     uint8_t pcias;
@@ -491,7 +493,7 @@ int pcistg_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
             program_interrupt(env, PGM_OPERAND, 4);
             return 0;
         }
-        MemoryRegion *mr;
+
         if (trap_msix(pbdev, offset, pcias)) {
             offset = offset - pbdev->msix.table_offset;
             mr = &pbdev->pdev->msix_table_mmio;
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
index 55184d33b3..8756cefa79 100644
--- a/hw/virtio/trace-events
+++ b/hw/virtio/trace-events
@@ -14,3 +14,8 @@ virtio_rng_guest_not_ready(void *rng) "rng %p: guest not ready"
 virtio_rng_pushed(void *rng, size_t len) "rng %p: %zd bytes pushed"
 virtio_rng_request(void *rng, size_t size, unsigned quota) "rng %p: %zd bytes requested, %u bytes quota left"
 
+# hw/virtio/virtio-balloon.c
+virtio_balloon_handle_output(const char *name, uint64_t gpa) "section name: %s gpa: %"PRIx64
+virtio_balloon_get_config(uint32_t num_pages, uint32_t actual) "num_pages: %d actual: %d"
+virtio_balloon_set_config(uint32_t actual, uint32_t oldactual) "actual: %d oldactual: %d"
+virtio_balloon_to_target(uint64_t target, uint32_t num_pages) "balloon target: %"PRIx64" num_pages: %d"
diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h
index a6dd2c3d30..88dc11808b 100644
--- a/include/hw/ide/internal.h
+++ b/include/hw/ide/internal.h
@@ -482,6 +482,7 @@ struct IDEBus {
     uint32_t retry_nsector;
     PortioList portio_list;
     PortioList portio2_list;
+    VMChangeStateEntry *vmstate;
 };
 
 #define TYPE_IDE_DEVICE "ide-device"
diff --git a/io/trace-events b/io/trace-events
index d064665f44..e31b596ca1 100644
--- a/io/trace-events
+++ b/io/trace-events
@@ -1,11 +1,5 @@
 # See docs/tracing.txt for syntax documentation.
 
-# io/buffer.c
-buffer_resize(const char *buf, size_t olen, size_t len) "%s: old %zd, new %zd"
-buffer_move_empty(const char *buf, size_t len, const char *from) "%s: %zd bytes from %s"
-buffer_move(const char *buf, size_t len, const char *from) "%s: %zd bytes from %s"
-buffer_free(const char *buf, size_t len) "%s: capacity %zd"
-
 # io/task.c
 qio_task_new(void *task, void *source, void *func, void *opaque) "Task new task=%p source=%p func=%p opaque=%p"
 qio_task_complete(void *task) "Task complete task=%p"
diff --git a/linux-user/main.c b/linux-user/main.c
index c8f8573614..9e4b430d66 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4748,7 +4748,6 @@ int main(int argc, char **argv, char **envp)
         }
         gdb_handlesig(cpu, 0);
     }
-    trace_init_vcpu_events();
     cpu_loop(env);
     /* never exits */
     return 0;
diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img
index 089f6ba5e9..cf05bf0be2 100644
--- a/pc-bios/s390-ccw.img
+++ b/pc-bios/s390-ccw.img
Binary files differdiff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c
index 1d34e8c1aa..b333734955 100644
--- a/pc-bios/s390-ccw/virtio.c
+++ b/pc-bios/s390-ccw/virtio.c
@@ -97,7 +97,8 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len)
 
     /* start command processing */
     stsch_err(vdev->schid, &schib);
-    schib.scsw.ctrl = SCSW_FCTL_START_FUNC;
+    /* enable the subchannel for IPL device */
+    schib.pmcw.ena = 1;
     msch(vdev->schid, &schib);
 
     /* start subchannel command */
diff --git a/qom/cpu.c b/qom/cpu.c
index f783b5a6bd..484c49388d 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -29,6 +29,7 @@
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
 #include "hw/qdev-properties.h"
+#include "trace.h"
 
 bool cpu_exists(int64_t id)
 {
@@ -245,6 +246,8 @@ void cpu_reset(CPUState *cpu)
     if (klass->reset != NULL) {
         (*klass->reset)(cpu);
     }
+
+    trace_guest_cpu_reset(cpu);
 }
 
 static void cpu_common_reset(CPUState *cpu)
@@ -333,6 +336,9 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
         cpu_synchronize_post_init(cpu);
         cpu_resume(cpu);
     }
+
+    /* NOTE: latest generic point where the cpu is fully realized */
+    trace_init_vcpu(cpu);
 }
 
 static void cpu_common_initfn(Object *obj)
diff --git a/stubs/trace-control.c b/stubs/trace-control.c
index 2dfcd9fb2b..f765a02018 100644
--- a/stubs/trace-control.c
+++ b/stubs/trace-control.c
@@ -44,3 +44,9 @@ void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
     /* should never be called on non-target binaries */
     abort();
 }
+
+void trace_init_vcpu(CPUState *vcpu)
+{
+    /* should never be called on non-target binaries */
+    abort();
+}
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index fd929e8351..7f745726bd 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -132,6 +132,8 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
     KVM_CAP_LAST_INFO
 };
 
+static QemuMutex qemu_sigp_mutex;
+
 static int cap_sync_regs;
 static int cap_async_pf;
 static int cap_mem_op;
@@ -287,6 +289,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
         }
     }
 
+    qemu_mutex_init(&qemu_sigp_mutex);
+
     return 0;
 }
 
@@ -1776,6 +1780,11 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
     status_reg = &env->regs[r1];
     param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
 
+    if (qemu_mutex_trylock(&qemu_sigp_mutex)) {
+        ret = SIGP_CC_BUSY;
+        goto out;
+    }
+
     switch (order) {
     case SIGP_SET_ARCH:
         ret = sigp_set_architecture(cpu, param, status_reg);
@@ -1785,7 +1794,9 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
         dst_cpu = s390_cpu_addr2state(env->regs[r3]);
         ret = handle_sigp_single_dst(dst_cpu, order, param, status_reg);
     }
+    qemu_mutex_unlock(&qemu_sigp_mutex);
 
+out:
     trace_kvm_sigp_finished(order, CPU(cpu)->cpu_index,
                             dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret);
 
@@ -1990,7 +2001,7 @@ static void insert_stsi_3_2_2(S390CPU *cpu, __u64 addr, uint8_t ar)
         strcpy((char *)sysib.ext_names[0], "KVMguest");
     }
     /* Insert UUID */
-    memcpy(sysib.vm[0].uuid, qemu_uuid, sizeof(sysib.vm[0].uuid));
+    memcpy(sysib.vm[0].uuid, &qemu_uuid, sizeof(sysib.vm[0].uuid));
 
     s390_cpu_virt_mem_write(cpu, addr, ar, &sysib, sizeof(sysib));
 }
diff --git a/trace-events b/trace-events
index 1cb9d37ce4..1a4e092418 100644
--- a/trace-events
+++ b/trace-events
@@ -37,10 +37,6 @@ cpu_out(unsigned int addr, char size, unsigned int val) "addr %#x(%c) value %u"
 # balloon.c
 # Since requests are raised via monitor, not many tracepoints are needed.
 balloon_event(void *opaque, unsigned long addr) "opaque %p addr %lu"
-virtio_balloon_handle_output(const char *name, uint64_t gpa) "section name: %s gpa: %"PRIx64
-virtio_balloon_get_config(uint32_t num_pages, uint32_t actual) "num_pages: %d actual: %d"
-virtio_balloon_set_config(uint32_t actual, uint32_t oldactual) "actual: %d oldactual: %d"
-virtio_balloon_to_target(uint64_t target, uint32_t num_pages) "balloon target: %"PRIx64" num_pages: %d"
 
 # vl.c
 vm_state_notify(int running, int reason) "running %d reason %d"
@@ -83,19 +79,6 @@ xen_map_cache(uint64_t phys_addr) "want %#"PRIx64
 xen_remap_bucket(uint64_t index) "index %#"PRIx64
 xen_map_cache_return(void* ptr) "%p"
 
-# qemu-coroutine.c
-qemu_coroutine_enter(void *from, void *to, void *opaque) "from %p to %p opaque %p"
-qemu_coroutine_yield(void *from, void *to) "from %p to %p"
-qemu_coroutine_terminate(void *co) "self %p"
-
-# qemu-coroutine-lock.c
-qemu_co_queue_run_restart(void *co) "co %p"
-qemu_co_queue_next(void *nxt) "next %p"
-qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p"
-qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
-qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p"
-qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p"
-
 # monitor.c
 handle_qmp_command(void *mon, const char *cmd_name) "mon %p cmd_name \"%s\""
 monitor_protocol_event_handler(uint32_t event, void *qdict) "event=%d data=%p"
@@ -157,6 +140,19 @@ colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u\n"
 
 ### Guest events, keep at bottom
 
+
+## vCPU
+
+# Hot-plug a new virtual (guest) CPU
+#
+# Targets: all
+vcpu guest_cpu_enter(void)
+
+# Reset the state of a virtual (guest) CPU
+#
+# Targets: all
+vcpu guest_cpu_reset(void)
+
 # @vaddr: Access' virtual address.
 # @info : Access' information (see below).
 #
@@ -173,6 +169,7 @@ colo_filter_rewriter_conn_offset(uint32_t offset) ": offset=%u\n"
 #     bool    store      : 1; /* wheter it's a store operation */
 # };
 #
+# Mode: user, softmmu
 # Targets: TCG(all)
 disable vcpu tcg guest_mem_before(TCGv vaddr, uint8_t info) "info=%d", "vaddr=0x%016"PRIx64" info=%d"
 
@@ -181,6 +178,7 @@ disable vcpu tcg guest_mem_before(TCGv vaddr, uint8_t info) "info=%d", "vaddr=0x
 #
 # Start executing a guest system call in syscall emulation mode.
 #
+# Mode: user
 # Targets: TCG(all)
 disable vcpu guest_user_syscall(uint64_t num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6, uint64_t arg7, uint64_t arg8) "num=0x%016"PRIx64" arg1=0x%016"PRIx64" arg2=0x%016"PRIx64" arg3=0x%016"PRIx64" arg4=0x%016"PRIx64" arg5=0x%016"PRIx64" arg6=0x%016"PRIx64" arg7=0x%016"PRIx64" arg8=0x%016"PRIx64
 
@@ -189,5 +187,6 @@ disable vcpu guest_user_syscall(uint64_t num, uint64_t arg1, uint64_t arg2, uint
 #
 # Finish executing a guest system call in syscall emulation mode.
 #
+# Mode: user
 # Targets: TCG(all)
 disable vcpu guest_user_syscall_ret(uint64_t num, uint64_t ret) "num=0x%016"PRIx64" ret=0x%016"PRIx64
diff --git a/trace/control-target.c b/trace/control-target.c
index 72081e2a34..52fcce5a00 100644
--- a/trace/control-target.c
+++ b/trace/control-target.c
@@ -9,6 +9,7 @@
 
 #include "qemu/osdep.h"
 #include "cpu.h"
+#include "trace.h"
 #include "trace/control.h"
 #include "translate-all.h"
 
@@ -81,3 +82,42 @@ void trace_event_set_vcpu_state_dynamic(CPUState *vcpu,
         }
     }
 }
+
+static bool adding_first_cpu(void)
+{
+    CPUState *cpu;
+    size_t count = 0;
+    CPU_FOREACH(cpu) {
+        count++;
+        if (count > 1) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void trace_init_vcpu(CPUState *vcpu)
+{
+    TraceEvent *ev = NULL;
+
+    while ((ev = trace_event_pattern("*", ev)) != NULL) {
+        if (trace_event_is_vcpu(ev) &&
+            trace_event_get_state_static(ev) &&
+            trace_event_get_state_dynamic(ev)) {
+            TraceEventID id = trace_event_get_id(ev);
+            if (adding_first_cpu()) {
+                /* check preconditions */
+                assert(trace_events_dstate[id] == 1);
+                /* disable early-init state ... */
+                trace_events_dstate[id] = 0;
+                trace_events_enabled_count--;
+                /* ... and properly re-enable */
+                trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
+            } else {
+                trace_event_set_vcpu_state_dynamic(vcpu, ev, true);
+            }
+        }
+    }
+
+    trace_guest_cpu_enter(vcpu);
+}
diff --git a/trace/control.c b/trace/control.c
index 05d85accbd..10b3e9baba 100644
--- a/trace/control.c
+++ b/trace/control.c
@@ -269,22 +269,3 @@ char *trace_opt_parse(const char *optarg)
 
     return trace_file;
 }
-
-void trace_init_vcpu_events(void)
-{
-    TraceEvent *ev = NULL;
-    while ((ev = trace_event_pattern("*", ev)) != NULL) {
-        if (trace_event_is_vcpu(ev) &&
-            trace_event_get_state_static(ev) &&
-            trace_event_get_state_dynamic(ev)) {
-            TraceEventID id = trace_event_get_id(ev);
-            /* check preconditions */
-            assert(trace_events_dstate[id] == 1);
-            /* disable early-init state ... */
-            trace_events_dstate[id] = 0;
-            trace_events_enabled_count--;
-            /* ... and properly re-enable */
-            trace_event_set_state_dynamic(ev, true);
-        }
-    }
-}
diff --git a/trace/control.h b/trace/control.h
index 27a16fc955..a22d11242e 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -239,6 +239,14 @@ bool trace_init_backends(void);
 void trace_init_file(const char *file);
 
 /**
+ * trace_init_vcpu:
+ * @vcpu: Added vCPU.
+ *
+ * Set initial dynamic event state for a hot-plugged vCPU.
+ */
+void trace_init_vcpu(CPUState *vcpu);
+
+/**
  * trace_list_events:
  *
  * List all available events.
@@ -269,17 +277,6 @@ extern QemuOptsList qemu_trace_opts;
  */
 char *trace_opt_parse(const char *optarg);
 
-/**
- * trace_init_vcpu_events:
- *
- * Re-synchronize initial event state with vCPUs (which can be created after
- * trace_init_events()).
- *
- * Precondition: event states won't be changed between trace_enable_events() and
- * trace_init_vcpu_events() (e.g., through QMP).
- */
-void trace_init_vcpu_events(void);
-
 
 #include "trace/control-internal.h"
 
diff --git a/util/trace-events b/util/trace-events
index 747e6baf75..ed06aee2ec 100644
--- a/util/trace-events
+++ b/util/trace-events
@@ -1,5 +1,24 @@
 # See docs/tracing.txt for syntax documentation.
 
+# util/buffer.c
+buffer_resize(const char *buf, size_t olen, size_t len) "%s: old %zd, new %zd"
+buffer_move_empty(const char *buf, size_t len, const char *from) "%s: %zd bytes from %s"
+buffer_move(const char *buf, size_t len, const char *from) "%s: %zd bytes from %s"
+buffer_free(const char *buf, size_t len) "%s: capacity %zd"
+
+# util/qemu-coroutine.c
+qemu_coroutine_enter(void *from, void *to, void *opaque) "from %p to %p opaque %p"
+qemu_coroutine_yield(void *from, void *to) "from %p to %p"
+qemu_coroutine_terminate(void *co) "self %p"
+
+# util/qemu-coroutine-lock.c
+qemu_co_queue_run_restart(void *co) "co %p"
+qemu_co_queue_next(void *nxt) "next %p"
+qemu_co_mutex_lock_entry(void *mutex, void *self) "mutex %p self %p"
+qemu_co_mutex_lock_return(void *mutex, void *self) "mutex %p self %p"
+qemu_co_mutex_unlock_entry(void *mutex, void *self) "mutex %p self %p"
+qemu_co_mutex_unlock_return(void *mutex, void *self) "mutex %p self %p"
+
 # util/oslib-win32.c
 # util/oslib-posix.c
 qemu_memalign(size_t alignment, size_t size, void *ptr) "alignment %zu size %zu ptr %p"
diff --git a/vl.c b/vl.c
index ab0349b0f4..f3abd99eb2 100644
--- a/vl.c
+++ b/vl.c
@@ -4660,7 +4660,6 @@ int main(int argc, char **argv, char **envp)
 
     os_setup_post();
 
-    trace_init_vcpu_events();
     main_loop();
     replay_disable_events();
     iothread_stop_all();