[PATCH 2/2] virtio_pci_modern: avoid infinite loop in vp_reset() on invalid status
Abhin Parekadan Jose <[email protected]> Sun, 2 Aug 2026 17:40:59 +0000
| Newsgroups | dev.linux.lists.virtualization,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
vp_reset() polls device_status in a tight loop, waiting for it to read back as 0 after the reset write. device_status is read via MMIO from the common configuration structure, which requires the PCI_COMMAND Memory Space Enable bit to be set. If that bit is cleared while the device is bound -- e.g. by writing 0x0000 to PCI_COMMAND (config space offset 4) -- the MMIO read no longer reaches the device and returns the bus's synthesized all-ones response instead. Since that value can never legitimately clear to 0, the loop spins forever and hangs the caller. Use VIRTIO_STATUS_ERROR() to recognize such values and bail out of the poll loop instead of looping indefinitely. Signed-off-by: Abhin Parekadan Jose <[email protected]> --- drivers/virtio/virtio_pci_modern.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c index 6d8ae2a6a8ca..209fa3b36c90 100644 --- a/drivers/virtio/virtio_pci_modern.c +++ b/drivers/virtio/virtio_pci_modern.c @@ -547,6 +547,7 @@ static void vp_reset(struct virtio_device *vdev) { struct virtio_pci_device *vp_dev = to_vp_device(vdev); struct virtio_pci_modern_device *mdev = &vp_dev->mdev; + u8 status; /* 0 status means a reset. */ vp_modern_set_status(mdev, 0); @@ -555,8 +556,11 @@ static void vp_reset(struct virtio_device *vdev) * This will flush out the status write, and flush in device writes, * including MSI-X interrupts, if any. */ - while (vp_modern_get_status(mdev)) + while ((status = vp_modern_get_status(mdev))) { + if (VIRTIO_STATUS_ERROR(status)) + break; msleep(1); + } vp_modern_avq_cleanup(vdev); -- 2.51.1