summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2024-04-09 09:51:07 +0100
committerPeter Maydell <peter.maydell@linaro.org>2024-04-09 09:51:07 +0100
commitbc0cd4ae881dff47e81581a8fea93a50b1d1dbe7 (patch)
tree39863f95cf5ef3daa9e34332d75efc47ff2f2423
parent98cd02f39321a8669691fdf62940ac15be89f4f2 (diff)
parente1999904a960c33b68fedf26dfb7b8e00abab8f2 (diff)
downloadfocaccia-qemu-bc0cd4ae881dff47e81581a8fea93a50b1d1dbe7.tar.gz
focaccia-qemu-bc0cd4ae881dff47e81581a8fea93a50b1d1dbe7.zip
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging
virtio,pc,pci: bugfixes

Tiny fixes: important but mostly obvious ones.  Revert VDPA network sim
for this release as there are questions around it's maintainatiblity.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# -----BEGIN PGP SIGNATURE-----
#
# iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmYU7qcPHG1zdEByZWRo
# YXQuY29tAAoJECgfDbjSjVRpn/cIAJBWRN67BS5ysdHjK0Hmw1zumbLpK+85wlAv
# dTfmJmUnIV6Ft5yaFFXCpxVH0/lh/vhG2ra5+lu53mX+GMtwjdqk4Sufvo4TukXu
# uweHUqlb4pdL37Yf7Q9N6kSX4Ay3ITEC7N18IvlBU8be5gRhidejMWlKq/gW/1rk
# +mnWeD5Qxs91Lh2pxShcnsRah0D4UY47dNu3VnglC9wYb4fupukGgj0qOnqYDF2K
# tG9Us0grU/qF1FgqWwbrlhOUO1Ntlp4uYn4JNOFhswAFDPm2XXIJRIPUhoYEi9G2
# HhxGSpDjJm8I9BBbllDnQVpIbBFxoG/EiQRT64Nt+rw+Tq01sPA=
# =AZIl
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 09 Apr 2024 08:30:47 BST
# gpg:                using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469
# gpg:                issuer "mst@redhat.com"
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu:
  qdev-monitor: fix error message in find_device_state()
  vhost-user-blk: simplify and fix vhost_user_blk_handle_config_change
  vdpa-dev: Fix the issue of device status not updating when configuration interruption is triggered
  hw/virtio: Fix packed virtqueue flush used_idx
  virtio-snd: rewrite invalid tx/rx message handling
  virtio-snd: Enhance error handling for invalid transfers
  Revert "hw/virtio: Add support for VDPA network simulation devices"

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS5
-rw-r--r--docs/system/device-emulation.rst1
-rw-r--r--docs/system/devices/vdpa-net.rst121
-rw-r--r--hw/audio/virtio-snd.c129
-rw-r--r--hw/block/vhost-user-blk.c11
-rw-r--r--hw/net/virtio-net.c16
-rw-r--r--hw/virtio/vdpa-dev.c7
-rw-r--r--hw/virtio/virtio-pci.c189
-rw-r--r--hw/virtio/virtio.c51
-rw-r--r--include/hw/audio/virtio-snd.h16
-rw-r--r--include/hw/virtio/virtio-pci.h5
-rw-r--r--include/hw/virtio/virtio.h19
-rw-r--r--include/standard-headers/linux/virtio_pci.h7
-rw-r--r--system/qdev-monitor.c2
14 files changed, 97 insertions, 482 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index d3fc2a06e3..f1f6922025 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2371,11 +2371,6 @@ F: hw/virtio/vhost-user-scmi*
 F: include/hw/virtio/vhost-user-scmi.h
 F: tests/qtest/libqos/virtio-scmi.*
 
-vdpa-net
-M: Hao Chen <chenh@yusur.tech>
-S: Maintained
-F: docs/system/devices/vdpa-net.rst
-
 virtio-crypto
 M: Gonglei <arei.gonglei@huawei.com>
 S: Supported
diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst
index e4a27f53c8..f19777411c 100644
--- a/docs/system/device-emulation.rst
+++ b/docs/system/device-emulation.rst
@@ -99,4 +99,3 @@ Emulated Devices
    devices/canokey.rst
    devices/usb-u2f.rst
    devices/igb.rst
-   devices/vdpa-net.rst
diff --git a/docs/system/devices/vdpa-net.rst b/docs/system/devices/vdpa-net.rst
deleted file mode 100644
index 323d8c926a..0000000000
--- a/docs/system/devices/vdpa-net.rst
+++ /dev/null
@@ -1,121 +0,0 @@
-vdpa net
-============
-
-This document explains the setup and usage of the vdpa network device.
-The vdpa network device is a paravirtualized vdpa emulate device.
-
-Description
------------
-
-VDPA net devices support dirty page bitmap mark and vring state saving and recovery.
-
-Users can use this VDPA device for live migration simulation testing in a nested virtualization environment.
-
-Registers layout
-----------------
-
-The vdpa device add live migrate registers layout as follow::
-
-  Offset       Register Name	        Bitwidth     Associated vq
-  0x0          LM_LOGGING_CTRL          4bits
-  0x10         LM_BASE_ADDR_LOW         32bits
-  0x14         LM_BASE_ADDR_HIGH        32bits
-  0x18         LM_END_ADDR_LOW          32bits
-  0x1c         LM_END_ADDR_HIGH         32bits
-  0x20         LM_RING_STATE_OFFSET	32bits       vq0
-  0x24         LM_RING_STATE_OFFSET	32bits       vq1
-  0x28         LM_RING_STATE_OFFSET	32bits       vq2
-  ......
-  0x20+1023*4  LM_RING_STATE_OFFSET     32bits       vq1023
-
-These registers are extended at the end of the notify bar space.
-
-Architecture diagram
---------------------
-::
-
-  |------------------------------------------------------------------------|
-  | guest-L1-user-space                                                    |
-  |                                                                        |
-  |                               |----------------------------------------|
-  |                               |       [virtio-net driver]              |
-  |                               |              ^  guest-L2-src(iommu=on) |
-  |                               |--------------|-------------------------|
-  |                               |              |  qemu-L2-src(viommu)    |
-  | [dpdk-vdpa]<->[vhost socket]<-+->[vhost-user backend(iommu=on)]        |
-  --------------------------------------------------------------------------
-  --------------------------------------------------------------------------
-  |       ^                             guest-L1-kernel-space              |
-  |       |                                                                |
-  |    [VFIO]                                                              |
-  |       ^                                                                |
-  |       |                             guest-L1-src(iommu=on)             |
-  --------|-----------------------------------------------------------------
-  --------|-----------------------------------------------------------------
-  | [vdpa net device(iommu=on)]        [manager nic device]                |
-  |          |                                    |                        |
-  |          |                                    |                        |
-  |     [tap device]     qemu-L1-src(viommu)      |                        |
-  ------------------------------------------------+-------------------------
-                                                  |
-                                                  |
-                        ---------------------     |
-                        | kernel net bridge |<-----
-                        |     virbr0        |<----------------------------------
-                        ---------------------                                  |
-                                                                               |
-                                                                               |
-  --------------------------------------------------------------------------   |
-  | guest-L1-user-space                                                    |   |
-  |                                                                        |   |
-  |                               |----------------------------------------|   |
-  |                               |       [virtio-net driver]              |   |
-  |                               |              ^  guest-L2-dst(iommu=on) |   |
-  |                               |--------------|-------------------------|   |
-  |                               |              |  qemu-L2-dst(viommu)    |   |
-  | [dpdk-vdpa]<->[vhost socket]<-+->[vhost-user backend(iommu=on)]        |   |
-  --------------------------------------------------------------------------   |
-  --------------------------------------------------------------------------   |
-  |       ^                             guest-L1-kernel-space              |   |
-  |       |                                                                |   |
-  |    [VFIO]                                                              |   |
-  |       ^                                                                |   |
-  |       |                             guest-L1-dst(iommu=on)             |   |
-  --------|-----------------------------------------------------------------   |
-  --------|-----------------------------------------------------------------   |
-  | [vdpa net device(iommu=on)]        [manager nic device]----------------+----
-  |          |                                                             |
-  |          |                                                             |
-  |     [tap device]     qemu-L1-dst(viommu)                               |
-  --------------------------------------------------------------------------
-
-
-Device properties
------------------
-
-The Virtio vdpa device can be configured with the following properties:
-
- * ``vdpa=on`` open vdpa device emulated.
-
-Usages
---------
-This patch add virtio sriov support and vdpa live migrate support.
-You can open vdpa by set xml file as follow::
-
-  <qemu:commandline  xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
-  <qemu:arg value='-device'/>
-  <qemu:arg value='intel-iommu,intremap=on,device-iotlb=on,aw-bits=48'/>
-  <qemu:arg value='-netdev'/>
-  <qemu:arg value='tap,id=hostnet1,script=no,downscript=no,vhost=off'/>
-  <qemu:arg value='-device'/>
-  <qemu:arg value='virtio-net-pci,netdev=hostnet1,id=net1,mac=56:4a:b7:4f:4d:a9,bus=pci.6,addr=0x0,iommu_platform=on,ats=on,vdpa=on'/>
-  </qemu:commandline>
-
-Limitations
------------
-1. Dependent on tap device with param ``vhost=off``.
-2. Nested virtualization environment only supports ``q35`` machines.
-3. Current only support split vring live migrate.
-
-
-
diff --git a/hw/audio/virtio-snd.c b/hw/audio/virtio-snd.c
index e604d8f30c..90d9a2796e 100644
--- a/hw/audio/virtio-snd.c
+++ b/hw/audio/virtio-snd.c
@@ -456,7 +456,6 @@ static uint32_t virtio_snd_pcm_prepare(VirtIOSound *s, uint32_t stream_id)
         stream->s = s;
         qemu_mutex_init(&stream->queue_mutex);
         QSIMPLEQ_INIT(&stream->queue);
-        QSIMPLEQ_INIT(&stream->invalid);
 
         /*
          * stream_id >= s->snd_conf.streams was checked before so this is
@@ -611,9 +610,6 @@ static size_t virtio_snd_pcm_get_io_msgs_count(VirtIOSoundPCMStream *stream)
         QSIMPLEQ_FOREACH_SAFE(buffer, &stream->queue, entry, next) {
             count += 1;
         }
-        QSIMPLEQ_FOREACH_SAFE(buffer, &stream->invalid, entry, next) {
-            count += 1;
-        }
     }
     return count;
 }
@@ -831,47 +827,36 @@ static void virtio_snd_handle_event(VirtIODevice *vdev, VirtQueue *vq)
     trace_virtio_snd_handle_event();
 }
 
+/*
+ * Must only be called if vsnd->invalid is not empty.
+ */
 static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOSoundPCMBuffer *buffer = NULL;
-    VirtIOSoundPCMStream *stream = NULL;
     virtio_snd_pcm_status resp = { 0 };
     VirtIOSound *vsnd = VIRTIO_SND(vdev);
-    bool any = false;
 
-    for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
-        stream = vsnd->pcm->streams[i];
-        if (stream) {
-            any = false;
-            WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
-                while (!QSIMPLEQ_EMPTY(&stream->invalid)) {
-                    buffer = QSIMPLEQ_FIRST(&stream->invalid);
-                    if (buffer->vq != vq) {
-                        break;
-                    }
-                    any = true;
-                    resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
-                    iov_from_buf(buffer->elem->in_sg,
-                                 buffer->elem->in_num,
-                                 0,
-                                 &resp,
-                                 sizeof(virtio_snd_pcm_status));
-                    virtqueue_push(vq,
-                                   buffer->elem,
-                                   sizeof(virtio_snd_pcm_status));
-                    QSIMPLEQ_REMOVE_HEAD(&stream->invalid, entry);
-                    virtio_snd_pcm_buffer_free(buffer);
-                }
-                if (any) {
-                    /*
-                     * Notify vq about virtio_snd_pcm_status responses.
-                     * Buffer responses must be notified separately later.
-                     */
-                    virtio_notify(vdev, vq);
-                }
-            }
-        }
+    g_assert(!QSIMPLEQ_EMPTY(&vsnd->invalid));
+
+    while (!QSIMPLEQ_EMPTY(&vsnd->invalid)) {
+        buffer = QSIMPLEQ_FIRST(&vsnd->invalid);
+        /* If buffer->vq != vq, our logic is fundamentally wrong, so bail out */
+        g_assert(buffer->vq == vq);
+
+        resp.status = cpu_to_le32(VIRTIO_SND_S_BAD_MSG);
+        iov_from_buf(buffer->elem->in_sg,
+                     buffer->elem->in_num,
+                     0,
+                     &resp,
+                     sizeof(virtio_snd_pcm_status));
+        virtqueue_push(vq,
+                       buffer->elem,
+                       sizeof(virtio_snd_pcm_status));
+        QSIMPLEQ_REMOVE_HEAD(&vsnd->invalid, entry);
+        virtio_snd_pcm_buffer_free(buffer);
     }
+    /* Notify vq about virtio_snd_pcm_status responses. */
+    virtio_notify(vdev, vq);
 }
 
 /*
@@ -883,15 +868,14 @@ static inline void empty_invalid_queue(VirtIODevice *vdev, VirtQueue *vq)
  */
 static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOSound *s = VIRTIO_SND(vdev);
-    VirtIOSoundPCMStream *stream = NULL;
+    VirtIOSound *vsnd = VIRTIO_SND(vdev);
     VirtIOSoundPCMBuffer *buffer;
     VirtQueueElement *elem;
     size_t msg_sz, size;
     virtio_snd_pcm_xfer hdr;
     uint32_t stream_id;
     /*
-     * If any of the I/O messages are invalid, put them in stream->invalid and
+     * If any of the I/O messages are invalid, put them in vsnd->invalid and
      * return them after the for loop.
      */
     bool must_empty_invalid_queue = false;
@@ -901,7 +885,7 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
     }
     trace_virtio_snd_handle_tx_xfer();
 
-    for (;;) {
+    for (VirtIOSoundPCMStream *stream = NULL;; stream = NULL) {
         elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
         if (!elem) {
             break;
@@ -917,12 +901,12 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
         }
         stream_id = le32_to_cpu(hdr.stream_id);
 
-        if (stream_id >= s->snd_conf.streams
-            || s->pcm->streams[stream_id] == NULL) {
+        if (stream_id >= vsnd->snd_conf.streams
+            || vsnd->pcm->streams[stream_id] == NULL) {
             goto tx_err;
         }
 
-        stream = s->pcm->streams[stream_id];
+        stream = vsnd->pcm->streams[stream_id];
         if (stream->info.direction != VIRTIO_SND_D_OUTPUT) {
             goto tx_err;
         }
@@ -942,13 +926,11 @@ static void virtio_snd_handle_tx_xfer(VirtIODevice *vdev, VirtQueue *vq)
         continue;
 
 tx_err:
-        WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
-            must_empty_invalid_queue = true;
-            buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
-            buffer->elem = elem;
-            buffer->vq = vq;
-            QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
-        }
+        must_empty_invalid_queue = true;
+        buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
+        buffer->elem = elem;
+        buffer->vq = vq;
+        QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
     }
 
     if (must_empty_invalid_queue) {
@@ -965,15 +947,14 @@ tx_err:
  */
 static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOSound *s = VIRTIO_SND(vdev);
-    VirtIOSoundPCMStream *stream = NULL;
+    VirtIOSound *vsnd = VIRTIO_SND(vdev);
     VirtIOSoundPCMBuffer *buffer;
     VirtQueueElement *elem;
     size_t msg_sz, size;
     virtio_snd_pcm_xfer hdr;
     uint32_t stream_id;
     /*
-     * if any of the I/O messages are invalid, put them in stream->invalid and
+     * if any of the I/O messages are invalid, put them in vsnd->invalid and
      * return them after the for loop.
      */
     bool must_empty_invalid_queue = false;
@@ -983,7 +964,7 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
     }
     trace_virtio_snd_handle_rx_xfer();
 
-    for (;;) {
+    for (VirtIOSoundPCMStream *stream = NULL;; stream = NULL) {
         elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
         if (!elem) {
             break;
@@ -999,12 +980,12 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
         }
         stream_id = le32_to_cpu(hdr.stream_id);
 
-        if (stream_id >= s->snd_conf.streams
-            || !s->pcm->streams[stream_id]) {
+        if (stream_id >= vsnd->snd_conf.streams
+            || !vsnd->pcm->streams[stream_id]) {
             goto rx_err;
         }
 
-        stream = s->pcm->streams[stream_id];
+        stream = vsnd->pcm->streams[stream_id];
         if (stream == NULL || stream->info.direction != VIRTIO_SND_D_INPUT) {
             goto rx_err;
         }
@@ -1021,13 +1002,11 @@ static void virtio_snd_handle_rx_xfer(VirtIODevice *vdev, VirtQueue *vq)
         continue;
 
 rx_err:
-        WITH_QEMU_LOCK_GUARD(&stream->queue_mutex) {
-            must_empty_invalid_queue = true;
-            buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
-            buffer->elem = elem;
-            buffer->vq = vq;
-            QSIMPLEQ_INSERT_TAIL(&stream->invalid, buffer, entry);
-        }
+        must_empty_invalid_queue = true;
+        buffer = g_malloc0(sizeof(VirtIOSoundPCMBuffer));
+        buffer->elem = elem;
+        buffer->vq = vq;
+        QSIMPLEQ_INSERT_TAIL(&vsnd->invalid, buffer, entry);
     }
 
     if (must_empty_invalid_queue) {
@@ -1127,6 +1106,7 @@ static void virtio_snd_realize(DeviceState *dev, Error **errp)
         virtio_add_queue(vdev, 64, virtio_snd_handle_rx_xfer);
     qemu_mutex_init(&vsnd->cmdq_mutex);
     QTAILQ_INIT(&vsnd->cmdq);
+    QSIMPLEQ_INIT(&vsnd->invalid);
 
     for (uint32_t i = 0; i < vsnd->snd_conf.streams; i++) {
         status = virtio_snd_set_pcm_params(vsnd, i, &default_params);
@@ -1376,13 +1356,20 @@ static void virtio_snd_unrealize(DeviceState *dev)
 
 static void virtio_snd_reset(VirtIODevice *vdev)
 {
-    VirtIOSound *s = VIRTIO_SND(vdev);
+    VirtIOSound *vsnd = VIRTIO_SND(vdev);
     virtio_snd_ctrl_command *cmd;
 
-    WITH_QEMU_LOCK_GUARD(&s->cmdq_mutex) {
-        while (!QTAILQ_EMPTY(&s->cmdq)) {
-            cmd = QTAILQ_FIRST(&s->cmdq);
-            QTAILQ_REMOVE(&s->cmdq, cmd, next);
+    /*
+     * Sanity check that the invalid buffer message queue is emptied at the end
+     * of every virtio_snd_handle_tx_xfer/virtio_snd_handle_rx_xfer call, and
+     * must be empty otherwise.
+     */
+    g_assert(QSIMPLEQ_EMPTY(&vsnd->invalid));
+
+    WITH_QEMU_LOCK_GUARD(&vsnd->cmdq_mutex) {
+        while (!QTAILQ_EMPTY(&vsnd->cmdq)) {
+            cmd = QTAILQ_FIRST(&vsnd->cmdq);
+            QTAILQ_REMOVE(&vsnd->cmdq, cmd, next);
             virtio_snd_ctrl_cmd_free(cmd);
         }
     }
diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c
index 6a856ad51a..9e6bbc6950 100644
--- a/hw/block/vhost-user-blk.c
+++ b/hw/block/vhost-user-blk.c
@@ -91,7 +91,6 @@ static void vhost_user_blk_set_config(VirtIODevice *vdev, const uint8_t *config)
 static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
 {
     int ret;
-    struct virtio_blk_config blkcfg;
     VirtIODevice *vdev = dev->vdev;
     VHostUserBlk *s = VHOST_USER_BLK(dev->vdev);
     Error *local_err = NULL;
@@ -100,19 +99,15 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev)
         return 0;
     }
 
-    ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg,
+    ret = vhost_dev_get_config(dev, (uint8_t *)&s->blkcfg,
                                vdev->config_len, &local_err);
     if (ret < 0) {
         error_report_err(local_err);
         return ret;
     }
 
-    /* valid for resize only */
-    if (blkcfg.capacity != s->blkcfg.capacity) {
-        s->blkcfg.capacity = blkcfg.capacity;
-        memcpy(dev->vdev->config, &s->blkcfg, vdev->config_len);
-        virtio_notify_config(dev->vdev);
-    }
+    memcpy(dev->vdev->config, &s->blkcfg, vdev->config_len);
+    virtio_notify_config(dev->vdev);
 
     return 0;
 }
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 58014a92ad..24e5e7d347 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -2039,22 +2039,6 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
             goto err;
         }
 
-        /* Mark dirty page's bitmap of guest memory */
-        if (vdev->lm_logging_ctrl == LM_ENABLE) {
-            uint64_t chunk = elem->in_addr[i] / VHOST_LOG_CHUNK;
-            /* Get chunk index */
-            BitmapMemoryRegionCaches *caches = qatomic_rcu_read(&vdev->caches);
-            uint64_t index = chunk / 8;
-            uint64_t shift = chunk % 8;
-            uint8_t val = 0;
-            address_space_read_cached(&caches->bitmap, index, &val,
-                                      sizeof(val));
-            val |= 1 << shift;
-            address_space_write_cached(&caches->bitmap, index, &val,
-                                       sizeof(val));
-            address_space_cache_invalidate(&caches->bitmap, index, sizeof(val));
-        }
-
         elems[i] = elem;
         lens[i] = total;
         i++;
diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c
index 13e87f06f6..64b96b226c 100644
--- a/hw/virtio/vdpa-dev.c
+++ b/hw/virtio/vdpa-dev.c
@@ -195,7 +195,14 @@ static void
 vhost_vdpa_device_get_config(VirtIODevice *vdev, uint8_t *config)
 {
     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
+    int ret;
 
+    ret = vhost_dev_get_config(&s->dev, s->config, s->config_size,
+                            NULL);
+    if (ret < 0) {
+        error_report("get device config space failed");
+        return;
+    }
     memcpy(config, s->config, s->config_size);
 }
 
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index eaaf86402c..cb6940fc0e 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1442,155 +1442,6 @@ int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy,
     return virtio_pci_add_mem_cap(proxy, &cap.cap);
 }
 
-/* Called within call_rcu().  */
-static void bitmap_free_region_cache(BitmapMemoryRegionCaches *caches)
-{
-    assert(caches != NULL);
-    address_space_cache_destroy(&caches->bitmap);
-    g_free(caches);
-}
-
-static void lm_disable(VirtIODevice *vdev)
-{
-    BitmapMemoryRegionCaches *caches;
-    caches = qatomic_read(&vdev->caches);
-    qatomic_rcu_set(&vdev->caches, NULL);
-    if (caches) {
-        call_rcu(caches, bitmap_free_region_cache, rcu);
-    }
-}
-
-static void lm_enable(VirtIODevice *vdev)
-{
-    BitmapMemoryRegionCaches *old = vdev->caches;
-    BitmapMemoryRegionCaches *new = NULL;
-    hwaddr addr, end, size;
-    int64_t len;
-
-    addr = vdev->lm_base_addr_low | ((hwaddr)(vdev->lm_base_addr_high) << 32);
-    end = vdev->lm_end_addr_low | ((hwaddr)(vdev->lm_end_addr_high) << 32);
-    size = end - addr;
-    if (size <= 0) {
-        error_report("Invalid lm size.");
-        return;
-    }
-
-    new = g_new0(BitmapMemoryRegionCaches, 1);
-    len = address_space_cache_init(&new->bitmap, vdev->dma_as, addr, size,
-                                   true);
-    if (len < size) {
-        virtio_error(vdev, "Cannot map bitmap");
-        goto err_bitmap;
-    }
-    qatomic_rcu_set(&vdev->caches, new);
-
-    if (old) {
-        call_rcu(old, bitmap_free_region_cache, rcu);
-    }
-
-    return;
-
-err_bitmap:
-    address_space_cache_destroy(&new->bitmap);
-    g_free(new);
-}
-
-static uint64_t virtio_pci_lm_read(void *opaque, hwaddr addr,
-                                       unsigned size)
-{
-    VirtIOPCIProxy *proxy = opaque;
-    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
-    hwaddr offset_end = LM_VRING_STATE_OFFSET +
-                        virtio_pci_queue_mem_mult(proxy) * VIRTIO_QUEUE_MAX;
-    uint32_t val;
-    int qid;
-
-    if (vdev == NULL) {
-        return UINT64_MAX;
-    }
-    switch (addr) {
-    case LM_LOGGING_CTRL:
-        val = vdev->lm_logging_ctrl;
-        break;
-    case LM_BASE_ADDR_LOW:
-        val = vdev->lm_base_addr_low;
-        break;
-    case LM_BASE_ADDR_HIGH:
-        val = vdev->lm_base_addr_high;
-        break;
-    case LM_END_ADDR_LOW:
-        val = vdev->lm_end_addr_low;
-        break;
-    case LM_END_ADDR_HIGH:
-        val = vdev->lm_end_addr_high;
-        break;
-    default:
-        if (addr >= LM_VRING_STATE_OFFSET && addr <= offset_end) {
-            qid = (addr - LM_VRING_STATE_OFFSET) /
-                  virtio_pci_queue_mem_mult(proxy);
-            val = virtio_queue_get_vring_states(vdev, qid);
-        } else
-            val = 0;
-
-        break;
-    }
-
-    return val;
-}
-
-static void virtio_pci_lm_write(void *opaque, hwaddr addr,
-                                    uint64_t val, unsigned size)
-{
-    VirtIOPCIProxy *proxy = opaque;
-    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
-    hwaddr offset_end = LM_VRING_STATE_OFFSET +
-                        virtio_pci_queue_mem_mult(proxy) * VIRTIO_QUEUE_MAX;
-    int qid;
-
-    if (vdev == NULL) {
-        return;
-    }
-
-    switch (addr) {
-    case LM_LOGGING_CTRL:
-        vdev->lm_logging_ctrl = val;
-        switch (val) {
-        case LM_DISABLE:
-            lm_disable(vdev);
-            break;
-        case LM_ENABLE:
-            lm_enable(vdev);
-            break;
-        default:
-            virtio_error(vdev, "Unsupport LM_LOGGING_CTRL value: %"PRIx64,
-                         val);
-                break;
-        };
-
-        break;
-    case LM_BASE_ADDR_LOW:
-        vdev->lm_base_addr_low = val;
-        break;
-    case LM_BASE_ADDR_HIGH:
-        vdev->lm_base_addr_high = val;
-        break;
-    case LM_END_ADDR_LOW:
-        vdev->lm_end_addr_low = val;
-        break;
-    case LM_END_ADDR_HIGH:
-        vdev->lm_end_addr_high = val;
-        break;
-    default:
-        if (addr >= LM_VRING_STATE_OFFSET && addr <= offset_end) {
-            qid = (addr - LM_VRING_STATE_OFFSET) /
-                  virtio_pci_queue_mem_mult(proxy);
-            virtio_queue_set_vring_states(vdev, qid, val);
-        } else
-            virtio_error(vdev, "Unsupport addr: %"PRIx64, addr);
-        break;
-    }
-}
-
 static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr,
                                        unsigned size)
 {
@@ -1972,15 +1823,6 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy,
         },
         .endianness = DEVICE_LITTLE_ENDIAN,
     };
-    static const MemoryRegionOps lm_ops = {
-        .read = virtio_pci_lm_read,
-        .write = virtio_pci_lm_write,
-        .impl = {
-            .min_access_size = 1,
-            .max_access_size = 4,
-        },
-        .endianness = DEVICE_LITTLE_ENDIAN,
-    };
     g_autoptr(GString) name = g_string_new(NULL);
 
     g_string_printf(name, "virtio-pci-common-%s", vdev_name);
@@ -2017,14 +1859,6 @@ static void virtio_pci_modern_regions_init(VirtIOPCIProxy *proxy,
                           proxy,
                           name->str,
                           proxy->notify_pio.size);
-    if (proxy->flags & VIRTIO_PCI_FLAG_VDPA) {
-        g_string_printf(name, "virtio-pci-lm-%s", vdev_name);
-        memory_region_init_io(&proxy->lm.mr, OBJECT(proxy),
-                          &lm_ops,
-                          proxy,
-                          name->str,
-                          proxy->lm.size);
-    }
 }
 
 static void virtio_pci_modern_region_map(VirtIOPCIProxy *proxy,
@@ -2187,10 +2021,6 @@ static void virtio_pci_device_plugged(DeviceState *d, Error **errp)
         virtio_pci_modern_mem_region_map(proxy, &proxy->isr, &cap);
         virtio_pci_modern_mem_region_map(proxy, &proxy->device, &cap);
         virtio_pci_modern_mem_region_map(proxy, &proxy->notify, &notify.cap);
-        if (proxy->flags & VIRTIO_PCI_FLAG_VDPA) {
-            memory_region_add_subregion(&proxy->modern_bar,
-                                        proxy->lm.offset, &proxy->lm.mr);
-        }
 
         if (modern_pio) {
             memory_region_init(&proxy->io_bar, OBJECT(proxy),
@@ -2260,9 +2090,6 @@ static void virtio_pci_device_unplugged(DeviceState *d)
         virtio_pci_modern_mem_region_unmap(proxy, &proxy->isr);
         virtio_pci_modern_mem_region_unmap(proxy, &proxy->device);
         virtio_pci_modern_mem_region_unmap(proxy, &proxy->notify);
-        if (proxy->flags & VIRTIO_PCI_FLAG_VDPA) {
-            memory_region_del_subregion(&proxy->modern_bar, &proxy->lm.mr);
-        }
         if (modern_pio) {
             virtio_pci_modern_io_region_unmap(proxy, &proxy->notify_pio);
         }
@@ -2317,17 +2144,9 @@ static void virtio_pci_realize(PCIDevice *pci_dev, Error **errp)
     proxy->notify_pio.type = VIRTIO_PCI_CAP_NOTIFY_CFG;
 
     /* subclasses can enforce modern, so do this unconditionally */
-    if (!(proxy->flags & VIRTIO_PCI_FLAG_VDPA)) {
-        memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci",
-                           /* PCI BAR regions must be powers of 2 */
-                           pow2ceil(proxy->notify.offset + proxy->notify.size));
-    } else {
-        proxy->lm.offset = proxy->notify.offset + proxy->notify.size;
-        proxy->lm.size = 0x20 + VIRTIO_QUEUE_MAX * 4;
-        memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci",
-                           /* PCI BAR regions must be powers of 2 */
-                           pow2ceil(proxy->lm.offset + proxy->lm.size));
-    }
+    memory_region_init(&proxy->modern_bar, OBJECT(proxy), "virtio-pci",
+                       /* PCI BAR regions must be powers of 2 */
+                       pow2ceil(proxy->notify.offset + proxy->notify.size));
 
     if (proxy->disable_legacy == ON_OFF_AUTO_AUTO) {
         proxy->disable_legacy = pcie_port ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
@@ -2482,8 +2301,6 @@ static Property virtio_pci_properties[] = {
                     VIRTIO_PCI_FLAG_INIT_FLR_BIT, true),
     DEFINE_PROP_BIT("aer", VirtIOPCIProxy, flags,
                     VIRTIO_PCI_FLAG_AER_BIT, false),
-    DEFINE_PROP_BIT("vdpa", VirtIOPCIProxy, flags,
-                    VIRTIO_PCI_FLAG_VDPA_BIT, false),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index fb6b4ccd83..c5bedca848 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -957,12 +957,20 @@ static void virtqueue_packed_flush(VirtQueue *vq, unsigned int count)
         return;
     }
 
+    /*
+     * For indirect element's 'ndescs' is 1.
+     * For all other elemment's 'ndescs' is the
+     * number of descriptors chained by NEXT (as set in virtqueue_packed_pop).
+     * So When the 'elem' be filled into the descriptor ring,
+     * The 'idx' of this 'elem' shall be
+     * the value of 'vq->used_idx' plus the 'ndescs'.
+     */
+    ndescs += vq->used_elems[0].ndescs;
     for (i = 1; i < count; i++) {
-        virtqueue_packed_fill_desc(vq, &vq->used_elems[i], i, false);
+        virtqueue_packed_fill_desc(vq, &vq->used_elems[i], ndescs, false);
         ndescs += vq->used_elems[i].ndescs;
     }
     virtqueue_packed_fill_desc(vq, &vq->used_elems[0], 0, true);
-    ndescs += vq->used_elems[0].ndescs;
 
     vq->inuse -= ndescs;
     vq->used_idx += ndescs;
@@ -3368,18 +3376,6 @@ static uint16_t virtio_queue_split_get_last_avail_idx(VirtIODevice *vdev,
     return vdev->vq[n].last_avail_idx;
 }
 
-static uint32_t virtio_queue_split_get_vring_states(VirtIODevice *vdev,
-                                                      int n)
-{
-    struct VirtQueue *vq = &vdev->vq[n];
-    uint16_t avail, used;
-
-    avail = vq->last_avail_idx;
-    used = vq->used_idx;
-
-    return avail | (uint32_t)used << 16;
-}
-
 unsigned int virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n)
 {
     if (virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
@@ -3389,33 +3385,6 @@ unsigned int virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n)
     }
 }
 
-unsigned int virtio_queue_get_vring_states(VirtIODevice *vdev, int n)
-{
-    if (virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
-        return -1;
-    } else {
-        return virtio_queue_split_get_vring_states(vdev, n);
-    }
-}
-
-static void virtio_queue_split_set_vring_states(VirtIODevice *vdev,
-                                                int n, uint32_t idx)
-{
-    struct VirtQueue *vq = &vdev->vq[n];
-    vq->last_avail_idx = (uint16_t)(idx & 0xffff);
-    vq->shadow_avail_idx = (uint16_t)(idx & 0xffff);
-    vq->used_idx = (uint16_t)(idx >> 16);
-}
-
-void virtio_queue_set_vring_states(VirtIODevice *vdev, int n, uint32_t idx)
-{
-    if (virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) {
-        return;
-    } else {
-        virtio_queue_split_set_vring_states(vdev, n, idx);
-    }
-}
-
 static void virtio_queue_packed_set_last_avail_idx(VirtIODevice *vdev,
                                                    int n, unsigned int idx)
 {
diff --git a/include/hw/audio/virtio-snd.h b/include/hw/audio/virtio-snd.h
index 3d79181364..8dafedb276 100644
--- a/include/hw/audio/virtio-snd.h
+++ b/include/hw/audio/virtio-snd.h
@@ -151,7 +151,6 @@ struct VirtIOSoundPCMStream {
     QemuMutex queue_mutex;
     bool active;
     QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) queue;
-    QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) invalid;
 };
 
 /*
@@ -223,6 +222,21 @@ struct VirtIOSound {
     QemuMutex cmdq_mutex;
     QTAILQ_HEAD(, virtio_snd_ctrl_command) cmdq;
     bool processing_cmdq;
+    /*
+     * Convenience queue to keep track of invalid tx/rx queue messages inside
+     * the tx/rx callbacks.
+     *
+     * In the callbacks as a first step we are emptying the virtqueue to handle
+     * each message and we cannot add an invalid message back to the queue: we
+     * would re-process it in subsequent loop iterations.
+     *
+     * Instead, we add them to this queue and after finishing examining every
+     * virtqueue element, we inform the guest for each invalid message.
+     *
+     * This queue must be empty at all times except for inside the tx/rx
+     * callbacks.
+     */
+    QSIMPLEQ_HEAD(, VirtIOSoundPCMBuffer) invalid;
 };
 
 struct virtio_snd_ctrl_command {
diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h
index 4d57a9c751..59d88018c1 100644
--- a/include/hw/virtio/virtio-pci.h
+++ b/include/hw/virtio/virtio-pci.h
@@ -43,7 +43,6 @@ enum {
     VIRTIO_PCI_FLAG_INIT_FLR_BIT,
     VIRTIO_PCI_FLAG_AER_BIT,
     VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT,
-    VIRTIO_PCI_FLAG_VDPA_BIT,
 };
 
 /* Need to activate work-arounds for buggy guests at vmstate load. */
@@ -90,9 +89,6 @@ enum {
 #define VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED \
   (1 << VIRTIO_PCI_FLAG_ATS_PAGE_ALIGNED_BIT)
 
-/* VDPA supported flags */
-#define VIRTIO_PCI_FLAG_VDPA (1 << VIRTIO_PCI_FLAG_VDPA_BIT)
-
 typedef struct {
     MSIMessage msg;
     int virq;
@@ -144,7 +140,6 @@ struct VirtIOPCIProxy {
         };
         VirtIOPCIRegion regs[5];
     };
-    VirtIOPCIRegion lm;
     MemoryRegion modern_bar;
     MemoryRegion io_bar;
     uint32_t legacy_io_bar_idx;
diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index b3c74a1bca..c8f72850bc 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -35,9 +35,6 @@
                                 (0x1ULL << VIRTIO_F_NOTIFY_ON_EMPTY) | \
                                 (0x1ULL << VIRTIO_F_ANY_LAYOUT))
 
-#define LM_DISABLE      0x00
-#define LM_ENABLE       0x01
-
 struct VirtQueue;
 
 static inline hwaddr vring_align(hwaddr addr,
@@ -98,11 +95,6 @@ enum virtio_device_endian {
     VIRTIO_DEVICE_ENDIAN_BIG,
 };
 
-typedef struct BitmapMemoryRegionCaches {
-    struct rcu_head rcu;
-    MemoryRegionCache bitmap;
-} BitmapMemoryRegionCaches;
-
 /**
  * struct VirtIODevice - common VirtIO structure
  * @name: name of the device
@@ -136,14 +128,6 @@ struct VirtIODevice
     uint32_t generation;
     int nvectors;
     VirtQueue *vq;
-    uint8_t lm_logging_ctrl;
-    uint32_t lm_base_addr_low;
-    uint32_t lm_base_addr_high;
-    uint32_t lm_end_addr_low;
-    uint32_t lm_end_addr_high;
-
-    BitmapMemoryRegionCaches *caches;
-
     MemoryListener listener;
     uint16_t device_id;
     /* @vm_running: current VM running state via virtio_vmstate_change() */
@@ -395,11 +379,8 @@ hwaddr virtio_queue_get_desc_size(VirtIODevice *vdev, int n);
 hwaddr virtio_queue_get_avail_size(VirtIODevice *vdev, int n);
 hwaddr virtio_queue_get_used_size(VirtIODevice *vdev, int n);
 unsigned int virtio_queue_get_last_avail_idx(VirtIODevice *vdev, int n);
-unsigned int virtio_queue_get_vring_states(VirtIODevice *vdev, int n);
 void virtio_queue_set_last_avail_idx(VirtIODevice *vdev, int n,
                                      unsigned int idx);
-void virtio_queue_set_vring_states(VirtIODevice *vdev, int n,
-                                   unsigned int idx);
 void virtio_queue_restore_last_avail_idx(VirtIODevice *vdev, int n);
 void virtio_queue_invalidate_signalled_used(VirtIODevice *vdev, int n);
 void virtio_queue_update_used_idx(VirtIODevice *vdev, int n);
diff --git a/include/standard-headers/linux/virtio_pci.h b/include/standard-headers/linux/virtio_pci.h
index 86733278ba..3e2bc2c97e 100644
--- a/include/standard-headers/linux/virtio_pci.h
+++ b/include/standard-headers/linux/virtio_pci.h
@@ -221,13 +221,6 @@ struct virtio_pci_cfg_cap {
 #define VIRTIO_PCI_COMMON_ADM_Q_IDX	60
 #define VIRTIO_PCI_COMMON_ADM_Q_NUM	62
 
-#define LM_LOGGING_CTRL                 0
-#define LM_BASE_ADDR_LOW                4
-#define LM_BASE_ADDR_HIGH               8
-#define LM_END_ADDR_LOW                 12
-#define LM_END_ADDR_HIGH                16
-#define LM_VRING_STATE_OFFSET           0x20
-
 #endif /* VIRTIO_PCI_NO_MODERN */
 
 /* Admin command status. */
diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c
index c1243891c3..840177d19f 100644
--- a/system/qdev-monitor.c
+++ b/system/qdev-monitor.c
@@ -891,7 +891,7 @@ static DeviceState *find_device_state(const char *id, Error **errp)
 
     dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
     if (!dev) {
-        error_setg(errp, "%s is not a hotpluggable device", id);
+        error_setg(errp, "%s is not a device", id);
         return NULL;
     }