pc,virtio,pci: bugfixes
Fixes all over the place. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmBl8ysPHG1zdEByZWRo YXQuY29tAAoJECgfDbjSjVRpCxMH/RKlAcKckjqq7dt3ccbdWpovuwM2C+CiDbNv uZtdZ8OGYTHmRnNWWOLL+LZql69/Go0INKiXr/r2VoRNw/prcBtvvAwLrx0uBQth a5VUXtMhFyyMzpiWL68/L3/ppMVuII5eYRlZyrmuqsk5KD5J1GtxFCtvL1scppy/ wycQpOmXUIivBL2WIgjrBD5R9otEo3Oi8l0xUkwb9NVyG93fUZcvOauxGyQyQPi6 1bgOGDfJytmwFZzV9lxohZrQb8IeFghvAcPJvj/t9ssS8a6cRD9/n5VjNtH9JTxv 7S5Yr9uaqDXDh9HrkMbUJPXdNlonWckCuQkpKTaNU9unk9Tmq04= =VAS+ -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
11577d85b1
|
@ -326,6 +326,13 @@ static void piix4_pm_reset(DeviceState *dev)
|
||||||
/* Mark SMM as already inited (until KVM supports SMM). */
|
/* Mark SMM as already inited (until KVM supports SMM). */
|
||||||
pci_conf[0x5B] = 0x02;
|
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);
|
pm_io_space_update(s);
|
||||||
acpi_pcihp_reset(&s->acpi_pci_hotplug, !s->use_acpi_root_pci_hotplug);
|
acpi_pcihp_reset(&s->acpi_pci_hotplug, !s->use_acpi_root_pci_hotplug);
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,7 +362,18 @@ static void vhost_user_blk_disconnect(DeviceState *dev)
|
||||||
vhost_dev_cleanup(&s->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)
|
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);
|
VHostUserBlk *s = VHOST_USER_BLK(vdev);
|
||||||
|
|
||||||
vhost_user_blk_disconnect(dev);
|
vhost_user_blk_disconnect(dev);
|
||||||
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event,
|
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL,
|
||||||
NULL, opaque, NULL, true);
|
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;
|
DeviceState *dev = opaque;
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||||
|
@ -389,30 +401,27 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CHR_EVENT_CLOSED:
|
case CHR_EVENT_CLOSED:
|
||||||
|
/*
|
||||||
|
* 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 (realized && !runstate_check(RUN_STATE_SHUTDOWN)) {
|
||||||
/*
|
/*
|
||||||
* A close event may happen during a read/write, but vhost
|
* A close event may happen during a read/write, but vhost
|
||||||
* code assumes the vhost_dev remains setup, so delay the
|
* code assumes the vhost_dev remains setup, so delay the
|
||||||
* stop & clear. There are two possible paths to hit this
|
* stop & clear.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
if (runstate_is_running()) {
|
|
||||||
AioContext *ctx = qemu_get_current_aio_context();
|
AioContext *ctx = qemu_get_current_aio_context();
|
||||||
|
|
||||||
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL, NULL,
|
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, NULL, NULL,
|
||||||
NULL, NULL, false);
|
NULL, NULL, false);
|
||||||
aio_bh_schedule_oneshot(ctx, vhost_user_blk_chr_closed_bh, opaque);
|
aio_bh_schedule_oneshot(ctx, vhost_user_blk_chr_closed_bh, opaque);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Move vhost device to the stopped state. The vhost-user device
|
* Move vhost device to the stopped state. The vhost-user device
|
||||||
|
@ -422,6 +431,9 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event)
|
||||||
* knowing its type (in this case vhost-user).
|
* knowing its type (in this case vhost-user).
|
||||||
*/
|
*/
|
||||||
s->dev.started = false;
|
s->dev.started = false;
|
||||||
|
} else {
|
||||||
|
vhost_user_blk_disconnect(dev);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CHR_EVENT_BREAK:
|
case CHR_EVENT_BREAK:
|
||||||
case CHR_EVENT_MUX_IN:
|
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->vhost_vqs = g_new0(struct vhost_virtqueue, s->num_queues);
|
||||||
s->connected = false;
|
s->connected = false;
|
||||||
|
|
||||||
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL, vhost_user_blk_event,
|
qemu_chr_fe_set_handlers(&s->chardev, NULL, NULL,
|
||||||
NULL, (void *)dev, NULL, true);
|
vhost_user_blk_event_realize, NULL, (void *)dev,
|
||||||
|
NULL, true);
|
||||||
|
|
||||||
reconnect:
|
reconnect:
|
||||||
if (qemu_chr_fe_wait_connected(&s->chardev, &err) < 0) {
|
if (qemu_chr_fe_wait_connected(&s->chardev, &err) < 0) {
|
||||||
|
@ -494,6 +507,10 @@ reconnect:
|
||||||
goto 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;
|
return;
|
||||||
|
|
||||||
virtio_err:
|
virtio_err:
|
||||||
|
|
|
@ -144,7 +144,18 @@ static void pm_update_sci(ViaPMState *s)
|
||||||
ACPI_BITMASK_POWER_BUTTON_ENABLE |
|
ACPI_BITMASK_POWER_BUTTON_ENABLE |
|
||||||
ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
|
ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
|
||||||
ACPI_BITMASK_TIMER_ENABLE)) != 0);
|
ACPI_BITMASK_TIMER_ENABLE)) != 0);
|
||||||
|
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);
|
pci_set_irq(&s->dev, sci_level);
|
||||||
|
}
|
||||||
/* schedule a timer interruption if needed */
|
/* schedule a timer interruption if needed */
|
||||||
acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
|
acpi_pm_tmr_update(&s->ar, (s->ar.pm1.evt.en & ACPI_BITMASK_TIMER_ENABLE) &&
|
||||||
!(pmsts & ACPI_BITMASK_TIMER_STATUS));
|
!(pmsts & ACPI_BITMASK_TIMER_STATUS));
|
||||||
|
@ -167,6 +178,11 @@ static void via_pm_reset(DeviceState *d)
|
||||||
/* SMBus IO base */
|
/* SMBus IO base */
|
||||||
pci_set_long(s->dev.config + 0x90, 1);
|
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);
|
pm_io_space_update(s);
|
||||||
smb_io_space_update(s);
|
smb_io_space_update(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1450,6 +1450,8 @@ static void pci_irq_handler(void *opaque, int irq_num, int level)
|
||||||
PCIDevice *pci_dev = opaque;
|
PCIDevice *pci_dev = opaque;
|
||||||
int change;
|
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);
|
change = level - pci_irq_state(pci_dev, irq_num);
|
||||||
if (!change)
|
if (!change)
|
||||||
return;
|
return;
|
||||||
|
@ -1469,6 +1471,7 @@ static inline int pci_intx(PCIDevice *pci_dev)
|
||||||
qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
|
qemu_irq pci_allocate_irq(PCIDevice *pci_dev)
|
||||||
{
|
{
|
||||||
int intx = pci_intx(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);
|
return qemu_allocate_irq(pci_irq_handler, pci_dev, intx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1364,9 +1364,14 @@ static uint64_t virtio_pci_isr_read(void *opaque, hwaddr addr,
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = opaque;
|
VirtIOPCIProxy *proxy = opaque;
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
uint64_t val = qatomic_xchg(&vdev->isr, 0);
|
uint64_t val;
|
||||||
pci_irq_deassert(&proxy->pci_dev);
|
|
||||||
|
|
||||||
|
if (vdev == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = qatomic_xchg(&vdev->isr, 0);
|
||||||
|
pci_irq_deassert(&proxy->pci_dev);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1380,10 +1385,10 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr,
|
||||||
{
|
{
|
||||||
VirtIOPCIProxy *proxy = opaque;
|
VirtIOPCIProxy *proxy = opaque;
|
||||||
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
|
||||||
uint64_t val = 0;
|
uint64_t val;
|
||||||
|
|
||||||
if (vdev == NULL) {
|
if (vdev == NULL) {
|
||||||
return val;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
@ -1396,6 +1401,9 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr,
|
||||||
case 4:
|
case 4:
|
||||||
val = virtio_config_modern_readl(vdev, addr);
|
val = virtio_config_modern_readl(vdev, addr);
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
val = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue