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