[RFC 2/2] virtio: implement virtio control-plane suspend and resume facility

Zhu Lingshan posted 2 patches 2 weeks, 2 days ago
Maintainers: "Michael S. Tsirkin" <mst@redhat.com>, Jason Wang <jasowang@redhat.com>, Cornelia Huck <cohuck@redhat.com>, Paolo Bonzini <pbonzini@redhat.com>
[RFC 2/2] virtio: implement virtio control-plane suspend and resume facility
Posted by Zhu Lingshan 2 weeks, 2 days ago
This commit implements suspend and resume facility
of virtio control-plane according to the new spec changes,
and a reference design on virtio-net.

Signed-off-by: Zhu Lingshan <lingshan.zhu@amd.com>
---
 hw/virtio/virtio-pci.c     |  5 +++++
 hw/virtio/virtio.c         | 16 ++++++++++++++++
 include/hw/virtio/virtio.h |  1 +
 3 files changed, 22 insertions(+)

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 767216d795..bc9189746f 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1580,6 +1580,11 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
         return;
     }
 
+    /* only allow writing device status while suspended */
+    if ((vdev->status & VIRTIO_CONFIG_S_SUSPEND) && (addr != VIRTIO_PCI_COMMON_STATUS)) {
+        return;
+    }
+
     switch (addr) {
     case VIRTIO_PCI_COMMON_DFSELECT:
         proxy->dfselect = val;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index e5abbc4601..9d632d72be 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -2242,8 +2242,10 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
 {
     VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
     trace_virtio_set_status(vdev, val);
+    uint8_t old_status;
     int ret = 0;
 
+    old_status = vdev->status;
     if (virtio_vdev_has_feature(vdev, VIRTIO_F_VERSION_1)) {
         if (!(vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) &&
             val & VIRTIO_CONFIG_S_FEATURES_OK) {
@@ -2276,6 +2278,15 @@ int virtio_set_status(VirtIODevice *vdev, uint8_t val)
             vdev->status &= !VIRTIO_CONFIG_S_DRIVER_OK;
     }
 
+    /* The device has been resumed */
+    if ((!(vdev->status & VIRTIO_CONFIG_S_SUSPEND)) &&
+        (old_status & VIRTIO_CONFIG_S_SUSPEND) &&
+        (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+        (vdev->config_interrupt_pending)) {
+            virtio_notify_config(vdev);
+            vdev->config_interrupt_pending = false;
+    }
+
     return ret;
 }
 
@@ -2714,6 +2725,11 @@ void virtio_notify_config(VirtIODevice *vdev)
     if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))
         return;
 
+    if (vdev->status & VIRTIO_CONFIG_S_SUSPEND) {
+        vdev->config_interrupt_pending = true;
+        return;
+    }
+
     virtio_set_isr(vdev, 0x3);
     vdev->generation++;
     virtio_notify_vector(vdev, vdev->config_vector);
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index c594764f23..9d66076f75 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -167,6 +167,7 @@ struct VirtIODevice
      */
     EventNotifier config_notifier;
     bool device_iotlb_enabled;
+    bool config_interrupt_pending;
 };
 
 struct VirtioDeviceClass {
-- 
2.51.0