aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/core.c18
-rw-r--r--hw/acpi/ich9.c24
-rw-r--r--hw/acpi/piix4.c27
-rw-r--r--hw/core/qdev.c47
-rw-r--r--hw/i386/acpi-dsdt-cpu-hotplug.dsl1
-rw-r--r--hw/i386/pc_piix.c19
-rw-r--r--hw/i386/pc_sysfw.c105
-rw-r--r--hw/i386/q35-acpi-dsdt.dsl4
-rw-r--r--hw/pci-host/piix.c11
-rw-r--r--hw/pci/pci.c42
-rw-r--r--hw/pci/pci_bridge.c2
-rw-r--r--hw/s390x/virtio-ccw.c5
-rw-r--r--hw/virtio/virtio.c2
13 files changed, 190 insertions, 117 deletions
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index 58308a3406..79414b44c7 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -662,3 +662,21 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
return val;
}
+
+void acpi_update_sci(ACPIREGS *regs, qemu_irq irq)
+{
+ int sci_level, pm1a_sts;
+
+ pm1a_sts = acpi_pm1_evt_get_sts(regs);
+
+ sci_level = ((pm1a_sts &
+ regs->pm1.evt.en & ACPI_BITMASK_PM1_COMMON_ENABLED) != 0) ||
+ ((regs->gpe.sts[0] & regs->gpe.en[0]) != 0);
+
+ qemu_set_irq(irq, sci_level);
+
+ /* schedule a timer interruption if needed */
+ acpi_pm_tmr_update(regs,
+ (regs->pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
+ !(pm1a_sts & ACPI_BITMASK_TIMER_STATUS));
+}
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 7e0429e0f9..30f0df8713 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -44,29 +44,10 @@ do { printf("%s "fmt, __func__, ## __VA_ARGS__); } while (0)
#define ICH9_DEBUG(fmt, ...) do { } while (0)
#endif
-static void pm_update_sci(ICH9LPCPMRegs *pm)
-{
- int sci_level, pm1a_sts;
-
- pm1a_sts = acpi_pm1_evt_get_sts(&pm->acpi_regs);
-
- sci_level = (((pm1a_sts & pm->acpi_regs.pm1.evt.en) &
- (ACPI_BITMASK_RT_CLOCK_ENABLE |
- ACPI_BITMASK_POWER_BUTTON_ENABLE |
- ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
- ACPI_BITMASK_TIMER_ENABLE)) != 0);
- qemu_set_irq(pm->irq, sci_level);
-
- /* schedule a timer interruption if needed */
- acpi_pm_tmr_update(&pm->acpi_regs,
- (pm->acpi_regs.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
- !(pm1a_sts & ACPI_BITMASK_TIMER_STATUS));
-}
-
static void ich9_pm_update_sci_fn(ACPIREGS *regs)
{
ICH9LPCPMRegs *pm = container_of(regs, ICH9LPCPMRegs, acpi_regs);
- pm_update_sci(pm);
+ acpi_update_sci(&pm->acpi_regs, pm->irq);
}
static uint64_t ich9_gpe_readb(void *opaque, hwaddr addr, unsigned width)
@@ -80,6 +61,7 @@ static void ich9_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
{
ICH9LPCPMRegs *pm = opaque;
acpi_gpe_ioport_writeb(&pm->acpi_regs, addr, val);
+ acpi_update_sci(&pm->acpi_regs, pm->irq);
}
static const MemoryRegionOps ich9_gpe_ops = {
@@ -193,7 +175,7 @@ static void pm_reset(void *opaque)
pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
}
- pm_update_sci(pm);
+ acpi_update_sci(&pm->acpi_regs, pm->irq);
}
static void pm_powerdown_req(Notifier *n, void *opaque)
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 9e8a89c233..20353b983e 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -112,29 +112,10 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
#define ACPI_ENABLE 0xf1
#define ACPI_DISABLE 0xf0
-static void pm_update_sci(PIIX4PMState *s)
-{
- int sci_level, pmsts;
-
- pmsts = acpi_pm1_evt_get_sts(&s->ar);
- sci_level = (((pmsts & s->ar.pm1.evt.en) &
- (ACPI_BITMASK_RT_CLOCK_ENABLE |
- ACPI_BITMASK_POWER_BUTTON_ENABLE |
- ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
- ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
- (((s->ar.gpe.sts[0] & s->ar.gpe.en[0]) &
- (PIIX4_PCI_HOTPLUG_STATUS | PIIX4_CPU_HOTPLUG_STATUS)) != 0);
-
- qemu_set_irq(s->irq, sci_level);
- /* schedule a timer interruption if needed */
- acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
- !(pmsts & ACPI_BITMASK_TIMER_STATUS));
-}
-
static void pm_tmr_timer(ACPIREGS *ar)
{
PIIX4PMState *s = container_of(ar, PIIX4PMState, ar);
- pm_update_sci(s);
+ acpi_update_sci(&s->ar, s->irq);
}
static void apm_ctrl_changed(uint32_t val, void *arg)
@@ -582,7 +563,7 @@ static void gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
PIIX4PMState *s = opaque;
acpi_gpe_ioport_writeb(&s->ar, addr, val);
- pm_update_sci(s);
+ acpi_update_sci(&s->ar, s->irq);
PIIX4_DPRINTF("gpe write %" HWADDR_PRIx " <== %" PRIu64 "\n", addr, val);
}
@@ -698,7 +679,7 @@ static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
} else {
g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8));
}
- pm_update_sci(s);
+ acpi_update_sci(&s->ar, s->irq);
}
static void piix4_cpu_added_req(Notifier *n, void *opaque)
@@ -772,7 +753,7 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
disable_device(s, slot);
}
- pm_update_sci(s);
+ acpi_update_sci(&s->ar, s->irq);
return 0;
}
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index bbd780aad1..d6df8864dd 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -233,19 +233,19 @@ static int qbus_reset_one(BusState *bus, void *opaque)
{
BusClass *bc = BUS_GET_CLASS(bus);
if (bc->reset) {
- return bc->reset(bus);
+ bc->reset(bus);
}
return 0;
}
void qdev_reset_all(DeviceState *dev)
{
- qdev_walk_children(dev, qdev_reset_one, qbus_reset_one, NULL);
+ qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
}
void qbus_reset_all(BusState *bus)
{
- qbus_walk_children(bus, qdev_reset_one, qbus_reset_one, NULL);
+ qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL);
}
void qbus_reset_all_fn(void *opaque)
@@ -337,49 +337,70 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
return NULL;
}
-int qbus_walk_children(BusState *bus, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque)
+int qbus_walk_children(BusState *bus,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque)
{
BusChild *kid;
int err;
- if (busfn) {
- err = busfn(bus, opaque);
+ if (pre_busfn) {
+ err = pre_busfn(bus, opaque);
if (err) {
return err;
}
}
QTAILQ_FOREACH(kid, &bus->children, sibling) {
- err = qdev_walk_children(kid->child, devfn, busfn, opaque);
+ err = qdev_walk_children(kid->child,
+ pre_devfn, pre_busfn,
+ post_devfn, post_busfn, opaque);
if (err < 0) {
return err;
}
}
+ if (post_busfn) {
+ err = post_busfn(bus, opaque);
+ if (err) {
+ return err;
+ }
+ }
+
return 0;
}
-int qdev_walk_children(DeviceState *dev, qdev_walkerfn *devfn,
- qbus_walkerfn *busfn, void *opaque)
+int qdev_walk_children(DeviceState *dev,
+ qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
+ qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
+ void *opaque)
{
BusState *bus;
int err;
- if (devfn) {
- err = devfn(dev, opaque);
+ if (pre_devfn) {
+ err = pre_devfn(dev, opaque);
if (err) {
return err;
}
}
QLIST_FOREACH(bus, &dev->child_bus, sibling) {
- err = qbus_walk_children(bus, devfn, busfn, opaque);
+ err = qbus_walk_children(bus, pre_devfn, pre_busfn,
+ post_devfn, post_busfn, opaque);
if (err < 0) {
return err;
}
}
+ if (post_devfn) {
+ err = post_devfn(dev, opaque);
+ if (err) {
+ return err;
+ }
+ }
+
return 0;
}
diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
index c96ac42a31..995b415bae 100644
--- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -52,7 +52,6 @@ Scope(\_SB) {
Sleep(200)
}
- /* CPU hotplug notify method */
OperationRegion(PRST, SystemIO, 0xaf00, 32)
Field(PRST, ByteAcc, NoLock, Preserve) {
PRS, 256
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 4e0dae7981..276641436e 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -61,6 +61,11 @@ static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
static bool has_pci_info;
static bool has_acpi_build = true;
static bool smbios_type1_defaults = true;
+/* Make sure that guest addresses aligned at 1Gbyte boundaries get mapped to
+ * host addresses aligned at 1Gbyte boundaries. This way we can use 1GByte
+ * pages in the host.
+ */
+static bool gigabyte_align = true;
/* PC hardware initialisation */
static void pc_init1(QEMUMachineInitArgs *args,
@@ -106,9 +111,17 @@ static void pc_init1(QEMUMachineInitArgs *args,
kvmclock_create();
}
+ /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory).
+ * If it doesn't, we need to split it in chunks below and above 4G.
+ * In any case, try to make sure that guest addresses aligned at
+ * 1G boundaries get mapped to host addresses aligned at 1G boundaries.
+ * For old machine types, use whatever split we used historically to avoid
+ * breaking migration.
+ */
if (args->ram_size >= 0xe0000000) {
- above_4g_mem_size = args->ram_size - 0xe0000000;
- below_4g_mem_size = 0xe0000000;
+ ram_addr_t lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000;
+ above_4g_mem_size = args->ram_size - lowmem;
+ below_4g_mem_size = lowmem;
} else {
above_4g_mem_size = 0;
below_4g_mem_size = args->ram_size;
@@ -157,6 +170,7 @@ static void pc_init1(QEMUMachineInitArgs *args,
if (pci_enabled) {
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
system_memory, system_io, args->ram_size,
+ below_4g_mem_size,
above_4g_mem_size,
pci_memory, ram_memory);
} else {
@@ -245,6 +259,7 @@ static void pc_init_pci(QEMUMachineInitArgs *args)
static void pc_compat_1_7(QEMUMachineInitArgs *args)
{
smbios_type1_defaults = false;
+ gigabyte_align = false;
}
static void pc_compat_1_6(QEMUMachineInitArgs *args)
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index e917c83540..75a7ebbaa7 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -72,35 +72,102 @@ static void pc_isa_bios_init(MemoryRegion *rom_memory,
memory_region_set_readonly(isa_bios, true);
}
-static void pc_system_flash_init(MemoryRegion *rom_memory,
- DriveInfo *pflash_drv)
+#define FLASH_MAP_UNIT_MAX 2
+
+/* We don't have a theoretically justifiable exact lower bound on the base
+ * address of any flash mapping. In practice, the IO-APIC MMIO range is
+ * [0xFEE00000..0xFEE01000[ -- see IO_APIC_DEFAULT_ADDRESS --, leaving free
+ * only 18MB-4KB below 4G. For now, restrict the cumulative mapping to 8MB in
+ * size.
+ */
+#define FLASH_MAP_BASE_MIN ((hwaddr)(0x100000000ULL - 8*1024*1024))
+
+/* This function maps flash drives from 4G downward, in order of their unit
+ * numbers. The mapping starts at unit#0, with unit number increments of 1, and
+ * stops before the first missing flash drive, or before
+ * unit#FLASH_MAP_UNIT_MAX, whichever is reached first.
+ *
+ * Addressing within one flash drive is of course not reversed.
+ *
+ * An error message is printed and the process exits if:
+ * - the size of the backing file for a flash drive is non-positive, or not a
+ * multiple of the required sector size, or
+ * - the current mapping's base address would fall below FLASH_MAP_BASE_MIN.
+ *
+ * The drive with unit#0 (if available) is mapped at the highest address, and
+ * it is passed to pc_isa_bios_init(). Merging several drives for isa-bios is
+ * not supported.
+ */
+static void pc_system_flash_init(MemoryRegion *rom_memory)
{
+ int unit;
+ DriveInfo *pflash_drv;
BlockDriverState *bdrv;
int64_t size;
- hwaddr phys_addr;
+ char *fatal_errmsg = NULL;
+ hwaddr phys_addr = 0x100000000ULL;
int sector_bits, sector_size;
pflash_t *system_flash;
MemoryRegion *flash_mem;
+ char name[64];
- bdrv = pflash_drv->bdrv;
- size = bdrv_getlength(pflash_drv->bdrv);
sector_bits = 12;
sector_size = 1 << sector_bits;
- if ((size % sector_size) != 0) {
- fprintf(stderr,
- "qemu: PC system firmware (pflash) must be a multiple of 0x%x\n",
- sector_size);
- exit(1);
+ for (unit = 0;
+ (unit < FLASH_MAP_UNIT_MAX &&
+ (pflash_drv = drive_get(IF_PFLASH, 0, unit)) != NULL);
+ ++unit) {
+ bdrv = pflash_drv->bdrv;
+ size = bdrv_getlength(bdrv);
+ if (size < 0) {
+ fatal_errmsg = g_strdup_printf("failed to get backing file size");
+ } else if (size == 0) {
+ fatal_errmsg = g_strdup_printf("PC system firmware (pflash) "
+ "cannot have zero size");
+ } else if ((size % sector_size) != 0) {
+ fatal_errmsg = g_strdup_printf("PC system firmware (pflash) "
+ "must be a multiple of 0x%x", sector_size);
+ } else if (phys_addr < size || phys_addr - size < FLASH_MAP_BASE_MIN) {
+ fatal_errmsg = g_strdup_printf("oversized backing file, pflash "
+ "segments cannot be mapped under "
+ TARGET_FMT_plx, FLASH_MAP_BASE_MIN);
+ }
+ if (fatal_errmsg != NULL) {
+ Location loc;
+
+ /* push a new, "none" location on the location stack; overwrite its
+ * contents with the location saved in the option; print the error
+ * (includes location); pop the top
+ */
+ loc_push_none(&loc);
+ if (pflash_drv->opts != NULL) {
+ qemu_opts_loc_restore(pflash_drv->opts);
+ }
+ error_report("%s", fatal_errmsg);
+ loc_pop(&loc);
+ g_free(fatal_errmsg);
+ exit(1);
+ }
+
+ phys_addr -= size;
+
+ /* pflash_cfi01_register() creates a deep copy of the name */
+ snprintf(name, sizeof name, "system.flash%d", unit);
+ system_flash = pflash_cfi01_register(phys_addr, NULL /* qdev */, name,
+ size, bdrv, sector_size,
+ size >> sector_bits,
+ 1 /* width */,
+ 0x0000 /* id0 */,
+ 0x0000 /* id1 */,
+ 0x0000 /* id2 */,
+ 0x0000 /* id3 */,
+ 0 /* be */);
+ if (unit == 0) {
+ flash_mem = pflash_cfi01_get_memory(system_flash);
+ pc_isa_bios_init(rom_memory, flash_mem, size);
+ }
}
-
- phys_addr = 0x100000000ULL - size;
- system_flash = pflash_cfi01_register(phys_addr, NULL, "system.flash", size,
- bdrv, sector_size, size >> sector_bits,
- 1, 0x0000, 0x0000, 0x0000, 0x0000, 0);
- flash_mem = pflash_cfi01_get_memory(system_flash);
-
- pc_isa_bios_init(rom_memory, flash_mem, size);
}
static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
@@ -181,5 +248,5 @@ void pc_system_firmware_init(MemoryRegion *rom_memory, bool isapc_ram_fw)
exit(1);
}
- pc_system_flash_init(rom_memory, pflash_drv);
+ pc_system_flash_init(rom_memory);
}
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index 575c5d7376..7934a9ddfb 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -417,11 +417,11 @@ DefinitionBlock (
Method(_L00) {
}
Method(_L01) {
+ }
+ Method(_E02) {
// CPU hotplug event
\_SB.PRSC()
}
- Method(_L02) {
- }
Method(_L03) {
}
Method(_L04) {
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index cc97150a90..e89d5c1dfa 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -311,6 +311,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
MemoryRegion *address_space_mem,
MemoryRegion *address_space_io,
ram_addr_t ram_size,
+ ram_addr_t below_4g_mem_size,
ram_addr_t above_4g_mem_size,
MemoryRegion *pci_address_space,
MemoryRegion *ram_memory)
@@ -340,15 +341,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
f->ram_memory = ram_memory;
i440fx = I440FX_PCI_HOST_BRIDGE(dev);
- /* Set PCI window size the way seabios has always done it. */
- /* Power of 2 so bios can cover it with a single MTRR */
- if (ram_size <= 0x80000000) {
- i440fx->pci_info.w32.begin = 0x80000000;
- } else if (ram_size <= 0xc0000000) {
- i440fx->pci_info.w32.begin = 0xc0000000;
- } else {
- i440fx->pci_info.w32.begin = 0xe0000000;
- }
+ i440fx->pci_info.w32.begin = below_4g_mem_size;
/* setup pci memory mapping */
pc_pci_as_mapping_init(OBJECT(f), f->system_memory,
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 82c11ecde4..aa2a395499 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -46,7 +46,7 @@
static void pcibus_dev_print(Monitor *mon, DeviceState *dev, int indent);
static char *pcibus_get_dev_path(DeviceState *dev);
static char *pcibus_get_fw_dev_path(DeviceState *dev);
-static int pcibus_reset(BusState *qbus);
+static void pcibus_reset(BusState *qbus);
static void pci_bus_finalize(Object *obj);
static Property pci_props[] = {
@@ -167,16 +167,10 @@ void pci_device_deassert_intx(PCIDevice *dev)
}
}
-/*
- * This function is called on #RST and FLR.
- * FLR if PCI_EXP_DEVCTL_BCR_FLR is set
- */
-void pci_device_reset(PCIDevice *dev)
+static void pci_do_device_reset(PCIDevice *dev)
{
int r;
- qdev_reset_all(&dev->qdev);
-
dev->irq_state = 0;
pci_update_irq_status(dev);
pci_device_deassert_intx(dev);
@@ -209,30 +203,34 @@ void pci_device_reset(PCIDevice *dev)
}
/*
+ * This function is called on #RST and FLR.
+ * FLR if PCI_EXP_DEVCTL_BCR_FLR is set
+ */
+void pci_device_reset(PCIDevice *dev)
+{
+ qdev_reset_all(&dev->qdev);
+ pci_do_device_reset(dev);
+}
+
+/*
* Trigger pci bus reset under a given bus.
- * To be called on RST# assert.
+ * Called via qbus_reset_all on RST# assert, after the devices
+ * have been reset qdev_reset_all-ed already.
*/
-void pci_bus_reset(PCIBus *bus)
+static void pcibus_reset(BusState *qbus)
{
+ PCIBus *bus = DO_UPCAST(PCIBus, qbus, qbus);
int i;
- for (i = 0; i < bus->nirq; i++) {
- bus->irq_count[i] = 0;
- }
for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) {
if (bus->devices[i]) {
- pci_device_reset(bus->devices[i]);
+ pci_do_device_reset(bus->devices[i]);
}
}
-}
-
-static int pcibus_reset(BusState *qbus)
-{
- pci_bus_reset(DO_UPCAST(PCIBus, qbus, qbus));
- /* topology traverse is done by pci_bus_reset().
- Tell qbus/qdev walker not to traverse the tree */
- return 1;
+ for (i = 0; i < bus->nirq; i++) {
+ assert(bus->irq_count[i] == 0);
+ }
}
static void pci_host_bus_register(PCIBus *bus, DeviceState *parent)
diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c
index 355c3e1b06..4becdc14b8 100644
--- a/hw/pci/pci_bridge.c
+++ b/hw/pci/pci_bridge.c
@@ -268,7 +268,7 @@ void pci_bridge_write_config(PCIDevice *d,
newctl = pci_get_word(d->config + PCI_BRIDGE_CONTROL);
if (~oldctl & newctl & PCI_BRIDGE_CTL_BUS_RESET) {
/* Trigger hot reset on 0->1 transition. */
- pci_bus_reset(&s->sec_bus);
+ qbus_reset_all(&s->sec_bus.qbus);
}
}
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 4b6250dda9..bc8871249d 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -30,13 +30,10 @@
static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
VirtioCcwDevice *dev);
-static int virtual_css_bus_reset(BusState *qbus)
+static void virtual_css_bus_reset(BusState *qbus)
{
/* This should actually be modelled via the generic css */
css_reset();
-
- /* we dont traverse ourself, return 0 */
- return 0;
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index 144b9ca2ef..a001e668c4 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1172,6 +1172,8 @@ static void virtio_device_unrealize(DeviceState *dev, Error **errp)
VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
Error *err = NULL;
+ virtio_bus_device_unplugged(vdev);
+
if (vdc->unrealize != NULL) {
vdc->unrealize(dev, &err);
if (err != NULL) {