diff options
author | Jean-Philippe Brucker <jean-philippe.brucker@arm.com> | 2019-01-10 14:12:43 +0000 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2019-01-22 06:55:26 +0000 |
commit | eb34a8c274ba8c4e42f35252c80b57723c35e2ad (patch) | |
tree | 16fdde31cea72aaf29b2fc32594d65f633e20c4d | |
parent | ad346c2e67a13fb7abd1534864168b16423fb20b (diff) | |
download | kvmtool-eb34a8c274ba8c4e42f35252c80b57723c35e2ad.tar.gz |
virtio: Add reset() callback
When the guest writes a status of 0, the device should be reset. Add a
reset() callback for the transport layer to reset all queues and their
ioeventfd.
Signed-off-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Signed-off-by: Julien Thierry <julien.thierry@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | include/kvm/virtio-mmio.h | 1 | ||||
-rw-r--r-- | include/kvm/virtio-pci.h | 1 | ||||
-rw-r--r-- | include/kvm/virtio.h | 1 | ||||
-rw-r--r-- | virtio/core.c | 9 | ||||
-rw-r--r-- | virtio/mmio.c | 16 | ||||
-rw-r--r-- | virtio/pci.c | 20 |
6 files changed, 37 insertions, 11 deletions
diff --git a/include/kvm/virtio-mmio.h b/include/kvm/virtio-mmio.h index 835f421b..0528947a 100644 --- a/include/kvm/virtio-mmio.h +++ b/include/kvm/virtio-mmio.h @@ -54,6 +54,7 @@ struct virtio_mmio { int virtio_mmio_signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq); int virtio_mmio_signal_config(struct kvm *kvm, struct virtio_device *vdev); int virtio_mmio_exit(struct kvm *kvm, struct virtio_device *vdev); +int virtio_mmio_reset(struct kvm *kvm, struct virtio_device *vdev); int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, int device_id, int subsys_id, int class); void virtio_mmio_assign_irq(struct device_header *dev_hdr); diff --git a/include/kvm/virtio-pci.h b/include/kvm/virtio-pci.h index b70cadd8..278a2595 100644 --- a/include/kvm/virtio-pci.h +++ b/include/kvm/virtio-pci.h @@ -55,6 +55,7 @@ struct virtio_pci { int virtio_pci__signal_vq(struct kvm *kvm, struct virtio_device *vdev, u32 vq); int virtio_pci__signal_config(struct kvm *kvm, struct virtio_device *vdev); int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev); +int virtio_pci__reset(struct kvm *kvm, struct virtio_device *vdev); int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev, int device_id, int subsys_id, int class); diff --git a/include/kvm/virtio.h b/include/kvm/virtio.h index f35c74df..19b91373 100644 --- a/include/kvm/virtio.h +++ b/include/kvm/virtio.h @@ -201,6 +201,7 @@ struct virtio_ops { int (*init)(struct kvm *kvm, void *dev, struct virtio_device *vdev, int device_id, int subsys_id, int class); int (*exit)(struct kvm *kvm, struct virtio_device *vdev); + int (*reset)(struct kvm *kvm, struct virtio_device *vdev); }; int virtio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, diff --git a/virtio/core.c b/virtio/core.c index 67d41142..e10ec362 100644 --- a/virtio/core.c +++ b/virtio/core.c @@ -241,6 +241,13 @@ void virtio_notify_status(struct kvm *kvm, struct virtio_device *vdev, } else if (!status && (vdev->status & VIRTIO__STATUS_START)) { vdev->status &= ~VIRTIO__STATUS_START; ext_status |= VIRTIO__STATUS_STOP; + + /* + * Reset virtqueues and stop all traffic now, so that the device + * can safely reset the backend in notify_status(). + */ + if (ext_status & VIRTIO__STATUS_STOP) + vdev->ops->reset(kvm, vdev); } if (vdev->ops->notify_status) @@ -264,6 +271,7 @@ int virtio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, vdev->ops->signal_config = virtio_pci__signal_config; vdev->ops->init = virtio_pci__init; vdev->ops->exit = virtio_pci__exit; + vdev->ops->reset = virtio_pci__reset; vdev->ops->init(kvm, dev, vdev, device_id, subsys_id, class); break; case VIRTIO_MMIO: @@ -276,6 +284,7 @@ int virtio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, vdev->ops->signal_config = virtio_mmio_signal_config; vdev->ops->init = virtio_mmio_init; vdev->ops->exit = virtio_mmio_exit; + vdev->ops->reset = virtio_mmio_reset; vdev->ops->init(kvm, dev, vdev, device_id, subsys_id, class); break; default: diff --git a/virtio/mmio.c b/virtio/mmio.c index 4b8c20ec..eff147aa 100644 --- a/virtio/mmio.c +++ b/virtio/mmio.c @@ -326,15 +326,23 @@ int virtio_mmio_init(struct kvm *kvm, void *dev, struct virtio_device *vdev, return 0; } +int virtio_mmio_reset(struct kvm *kvm, struct virtio_device *vdev) +{ + int vq; + struct virtio_mmio *vmmio = vdev->virtio; + + for (vq = 0; vq < vdev->ops->get_vq_count(kvm, vmmio->dev); vq++) + virtio_mmio_exit_vq(kvm, vdev, vq); + + return 0; +} + int virtio_mmio_exit(struct kvm *kvm, struct virtio_device *vdev) { struct virtio_mmio *vmmio = vdev->virtio; - int i; + virtio_mmio_reset(kvm, vdev); kvm__deregister_mmio(kvm, vmmio->addr); - for (i = 0; i < VIRTIO_MMIO_MAX_VQ; i++) - ioeventfd__del_event(vmmio->addr + VIRTIO_MMIO_QUEUE_NOTIFY, i); - return 0; } diff --git a/virtio/pci.c b/virtio/pci.c index 2da2d3f8..99653cad 100644 --- a/virtio/pci.c +++ b/virtio/pci.c @@ -77,8 +77,8 @@ static void virtio_pci_exit_vq(struct kvm *kvm, struct virtio_device *vdev, { struct virtio_pci *vpci = vdev->virtio; - ioeventfd__del_event(vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY, vq); ioeventfd__del_event(vpci->mmio_addr + VIRTIO_PCI_QUEUE_NOTIFY, vq); + ioeventfd__del_event(vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY, vq); virtio_exit_vq(kvm, vdev, vpci->dev, vq); } @@ -522,19 +522,25 @@ free_ioport: return r; } +int virtio_pci__reset(struct kvm *kvm, struct virtio_device *vdev) +{ + int vq; + struct virtio_pci *vpci = vdev->virtio; + + for (vq = 0; vq < vdev->ops->get_vq_count(kvm, vpci->dev); vq++) + virtio_pci_exit_vq(kvm, vdev, vq); + + return 0; +} + int virtio_pci__exit(struct kvm *kvm, struct virtio_device *vdev) { struct virtio_pci *vpci = vdev->virtio; - int i; + virtio_pci__reset(kvm, vdev); kvm__deregister_mmio(kvm, vpci->mmio_addr); kvm__deregister_mmio(kvm, vpci->msix_io_block); ioport__unregister(kvm, vpci->port_addr); - for (i = 0; i < VIRTIO_PCI_MAX_VQ; i++) { - ioeventfd__del_event(vpci->port_addr + VIRTIO_PCI_QUEUE_NOTIFY, i); - ioeventfd__del_event(vpci->mmio_addr + VIRTIO_PCI_QUEUE_NOTIFY, i); - } - return 0; } |