diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2021-04-02 11:53:18 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2021-04-02 11:53:19 +0100 |
commit | 11577d85b1a6939380bd16ed9a861653194de044 (patch) | |
tree | 34bc6d68a0b62f096b10fd1660d99b4ef358d441 | |
parent | 50a9b4499ca99a439b400f715f9475b1702f4e87 (diff) | |
parent | 8ddf54324858ce5e35272efa449f27fc0a19f957 (diff) |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc,virtio,pci: bugfixes
Fixes all over the place.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Thu 01 Apr 2021 17:22:03 BST
# gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469
# gpg: issuer "mst@redhat.com"
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67
# Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469
* remotes/mst/tags/for_upstream:
pci: sprinkle assert in PCI pin number
isa/v582c686: Reinitialize ACPI PM device on reset
vt82c686.c: don't raise SCI when PCI_INTERRUPT_PIN isn't setup
acpi/piix4: reinitialize acpi PM device on reset
virtio-pci: remove explicit initialization of val
virtio-pci: add check for vdev in virtio_pci_isr_read
vhost-user-blk: add immediate cleanup on shutdown
vhost-user-blk: perform immediate cleanup if disconnect on initialization
vhost-user-blk: use different event handlers on initialization
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | hw/acpi/piix4.c | 7 | ||||
-rw-r--r-- | hw/block/vhost-user-blk.c | 79 | ||||
-rw-r--r-- | hw/isa/vt82c686.c | 18 | ||||
-rw-r--r-- | hw/pci/pci.c | 3 | ||||
-rw-r--r-- | hw/virtio/virtio-pci.c | 16 |
5 files changed, 87 insertions, 36 deletions
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 6056d51667..8f8b0e95e5 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -326,6 +326,13 @@ static void piix4_pm_reset(DeviceState *dev) /* Mark SMM as already inited (until KVM supports SMM). */ pci_conf[0x5B] = 0x02; } + + acpi_pm1_evt_reset(&s->ar); + acpi_pm1_cnt_reset(&s->ar); + acpi_pm_tmr_reset(&s->ar); + acpi_gpe_reset(&s->ar); + acpi_update_sci(&s->ar, s->irq); + pm_io_space_update(s); acpi_pcihp_reset(&s->acpi_pci_hotplug, !s->use_acpi_root_pci_hotplug); } diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index b870a50e6b..0b5b9d44cd 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -362,7 +362,18 @@ static void vhost_user_blk_disconnect(DeviceState *dev) vhost_dev_cleanup(&s->dev); } -static void vhost_user_blk_event(void *opaque, QEMUChrEvent event); +static void vhost_user_blk_event(void *opaque, QEMUChrEvent event, + bool realized); + +static void vhost_user_blk_event_realize(void *opaque, QEMUChrEvent event) +{ + vhost_user_blk_event(opaque, event, false); +} + +static void vhost_user_blk_event_oper(void *opaque, QEMUChrEvent event) +{ + vhost_user_blk_event(opaque, event, true); +} static void vhost_user_blk_chr_closed_bh(void *opaque) { @@ -371,11 +382,12 @@ static void vhost_user_blk_chr_closed_bh(void *opaque) VHostUserBlk *s = VHOST_USER_BLK(vdev); vhost_user_blk_disconnect(dev); - qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event, - NULL, opaque, NULL, true); + qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, + vhost_user_blk_event_oper, NULL, opaque, NULL, true); } -static void vhost_user_blk_event(void *opaque, QEMUChrEvent event) +static void vhost_user_blk_event(void *opaque, QEMUChrEvent event, + bool realized) { DeviceState *dev = opaque; VirtIODevice *vdev = VIRTIO_DEVICE(dev); @@ -390,38 +402,38 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event) break; case CHR_EVENT_CLOSED: /* - * A close event may happen during a read/write, but vhost - * code assumes the vhost_dev remains setup, so delay the - * stop & clear. There are two possible paths to hit this - * disconnect event: - * 1. When VM is in the RUN_STATE_PRELAUNCH state. The - * vhost_user_blk_device_realize() is a caller. - * 2. In tha main loop phase after VM start. - * - * For p2 the disconnect event will be delayed. We can't - * do the same for p1, because we are not running the loop - * at this moment. So just skip this step and perform - * disconnect in the caller function. - * - * TODO: maybe it is a good idea to make the same fix - * for other vhost-user devices. + * Closing the connection should happen differently on device + * initialization and operation stages. + * On initalization, we want to re-start vhost_dev initialization + * from the very beginning right away when the connection is closed, + * so we clean up vhost_dev on each connection closing. + * On operation, we want to postpone vhost_dev cleanup to let the + * other code perform its own cleanup sequence using vhost_dev data + * (e.g. vhost_dev_set_log). */ - if (runstate_is_running()) { + if (realized && !runstate_check(RUN_STATE_SHUTDOWN)) { + /* + * A close event may happen during a read/write, but vhost + * code assumes the vhost_dev remains setup, so delay the + * stop & clear. + */ AioContext *ctx = qemu_get_current_aio_context(); qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL, NULL, NULL, NULL, false); aio_bh_schedule_oneshot(ctx, vhost_user_blk_chr_closed_bh, opaque); - } - /* - * Move vhost device to the stopped state. The vhost-user device - * will be clean up and disconnected in BH. This can be useful in - * the vhost migration code. If disconnect was caught there is an - * option for the general vhost code to get the dev state without - * knowing its type (in this case vhost-user). - */ - s->dev.started = false; + /* + * Move vhost device to the stopped state. The vhost-user device + * will be clean up and disconnected in BH. This can be useful in + * the vhost migration code. If disconnect was caught there is an + * option for the general vhost code to get the dev state without + * knowing its type (in this case vhost-user). + */ + s->dev.started = false; + } else { + vhost_user_blk_disconnect(dev); + } break; case CHR_EVENT_BREAK: case CHR_EVENT_MUX_IN: @@ -473,8 +485,9 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) s->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues); s->connected = false; - qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event, - NULL, (void *)dev, NULL, true); + qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, + vhost_user_blk_event_realize, NULL, (void *)dev, + NULL, true); reconnect: if (qemu_chr_fe_wait_connected(&s->chardev, &err) < 0) { @@ -494,6 +507,10 @@ reconnect: goto reconnect; } + /* we're fully initialized, now we can operate, so change the handler */ + qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, + vhost_user_blk_event_oper, NULL, (void *)dev, + NULL, true); return; virtio_err: diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 05d084f698..98325bb32b 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -144,7 +144,18 @@ static void pm_update_sci(ViaPMState *s) ACPI_BITMASK_POWER_BUTTON_ENABLE | ACPI_BITMASK_GLOBAL_LOCK_ENABLE | ACPI_BITMASK_TIMER_ENABLE)) != 0); - pci_set_irq(&s->dev, sci_level); + if (pci_get_byte(s->dev.config + PCI_INTERRUPT_PIN)) { + /* + * FIXME: + * Fix device model that realizes this PM device and remove + * this work around. + * The device model should wire SCI and setup + * PCI_INTERRUPT_PIN properly. + * If PIN# = 0(interrupt pin isn't used), don't raise SCI as + * work around. + */ + pci_set_irq(&s->dev, 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)); @@ -167,6 +178,11 @@ static void via_pm_reset(DeviceState *d) /* SMBus IO base */ pci_set_long(s->dev.config + 0x90, 1); + acpi_pm1_evt_reset(&s->ar); + acpi_pm1_cnt_reset(&s->ar); + acpi_pm_tmr_reset(&s->ar); + pm_update_sci(s); + pm_io_space_update(s); smb_io_space_update(s); } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index ac9a24889c..8f35e13a0c 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1450,6 +1450,8 @@ static void pci_irq_handler(void *opaque, int irq_num, int level) PCIDevice *pci_dev = opaque; int change; + assert(0 <= irq_num && irq_num < PCI_NUM_PINS); + assert(level == 0 || level == 1); change = level - pci_irq_state(pci_dev, irq_num); if (!change) return; @@ -1469,6 +1471,7 @@ static inline int pci_intx(PCIDevice *pci_dev) qemu_irq pci_allocate_irq(PCIDevice *pci_dev) { int intx = pci_intx(pci_dev); + assert(0 <= intx && intx < PCI_NUM_PINS); return qemu_allocate_irq(pci_irq_handler, pci_dev, intx); } diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 883045a223..c1b67cf6fc 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1364,9 +1364,14 @@ static uint64_t virtio_pci_isr_read(void *opaque, hwaddr addr, { VirtIOPCIProxy *proxy = opaque; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - uint64_t val = qatomic_xchg(&vdev->isr, 0); - pci_irq_deassert(&proxy->pci_dev); + uint64_t val; + + if (vdev == NULL) { + return 0; + } + val = qatomic_xchg(&vdev->isr, 0); + pci_irq_deassert(&proxy->pci_dev); return val; } @@ -1380,10 +1385,10 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, { VirtIOPCIProxy *proxy = opaque; VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - uint64_t val = 0; + uint64_t val; if (vdev == NULL) { - return val; + return 0; } switch (size) { @@ -1396,6 +1401,9 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, case 4: val = virtio_config_modern_readl(vdev, addr); break; + default: + val = 0; + break; } return val; } |