Skip to content

Commit feb2ca4

Browse files
committed
virtio: break and reset virtio devices on device_shutdown()
JIRA: https://issues.redhat.com/browse/RHEL-331 Conflicts: contextual conflict in drivers/virtio/virtio.c as we don't have commit 2b666ee ("virtio: make virtio_bus const") downstream Hongyu reported a hang on kexec in a VM. QEMU reported invalid memory accesses during the hang. Invalid read at addr 0x102877002, size 2, region '(null)', reason: rejected Invalid write at addr 0x102877A44, size 2, region '(null)', reason: rejected ... It was traced down to virtio-console. Kexec works fine if virtio-console is not in use. The issue is that virtio-console continues to write to the MMIO even after underlying virtio-pci device is reset. Additionally, Eric noticed that IOMMUs are reset before devices, if devices are not reset on shutdown they continue to poke at guest memory and get errors from the IOMMU. Some devices get wedged then. The problem can be solved by breaking all virtio devices on virtio bus shutdown, then resetting them. Reported-by: Eric Auger <eauger@redhat.com> Reported-by: Hongyu Ning <hongyu.ning@linux.intel.com> Message-ID: <c1dbc7dbad9b445245d3348f19e6742b0be07347.1740094946.git.mst@redhat.com> Tested-by: Eric Auger <eric.auger@redhat.com> Acked-by: Jason Wang <jasowang@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> (cherry picked from commit 8bd2fa0) Signed-off-by: Eric Auger <eric.auger@redhat.com>
1 parent 153ef7c commit feb2ca4

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

drivers/virtio/virtio.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,34 @@ static const struct cpumask *virtio_irq_get_affinity(struct device *_d,
347347
return dev->config->get_vq_affinity(dev, irq_vec);
348348
}
349349

350+
static void virtio_dev_shutdown(struct device *_d)
351+
{
352+
struct virtio_device *dev = dev_to_virtio(_d);
353+
struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
354+
355+
/*
356+
* Stop accesses to or from the device.
357+
* We only need to do it if there's a driver - no accesses otherwise.
358+
*/
359+
if (!drv)
360+
return;
361+
362+
/*
363+
* Some devices get wedged if you kick them after they are
364+
* reset. Mark all vqs as broken to make sure we don't.
365+
*/
366+
virtio_break_device(dev);
367+
/*
368+
* Guarantee that any callback will see vq->broken as true.
369+
*/
370+
virtio_synchronize_cbs(dev);
371+
/*
372+
* As IOMMUs are reset on shutdown, this will block device access to memory.
373+
* Some devices get wedged if this happens, so reset to make sure it does not.
374+
*/
375+
dev->config->reset(dev);
376+
}
377+
350378
static struct bus_type virtio_bus = {
351379
.name = "virtio",
352380
.match = virtio_dev_match,
@@ -355,6 +383,7 @@ static struct bus_type virtio_bus = {
355383
.probe = virtio_dev_probe,
356384
.remove = virtio_dev_remove,
357385
.irq_get_affinity = virtio_irq_get_affinity,
386+
.shutdown = virtio_dev_shutdown,
358387
};
359388

360389
int register_virtio_driver(struct virtio_driver *driver)

0 commit comments

Comments
 (0)