diff options
author | Eugenio Pérez <eperezma@redhat.com> | 2022-07-22 10:26:30 +0200 |
---|---|---|
committer | Jason Wang <jasowang@redhat.com> | 2022-07-26 16:24:19 +0800 |
commit | 75a8ce64f6e37513698857fb4284170da163ed06 (patch) | |
tree | 713d7f6acf5f851cc721ea0e37bc7c1e0d27792b /hw/virtio | |
parent | 2fdac348fd3d243bb964937236af3cc27ae7af2b (diff) | |
download | qemu-75a8ce64f6e37513698857fb4284170da163ed06.zip qemu-75a8ce64f6e37513698857fb4284170da163ed06.tar.gz qemu-75a8ce64f6e37513698857fb4284170da163ed06.tar.bz2 |
vdpa: Fix memory listener deletions of iova tree
vhost_vdpa_listener_region_del is always deleting the first iova entry
of the tree, since it's using the needle iova instead of the result's
one.
This was detected using a vga virtual device in the VM using vdpa SVQ.
It makes some extra memory adding and deleting, so the wrong one was
mapped / unmapped. This was undetected before since all the memory was
mappend and unmapped totally without that device, but other conditions
could trigger it too:
* mem_region was with .iova = 0, .translated_addr = (correct GPA).
* iova_tree_find_iova returned right result, but does not update
mem_region.
* iova_tree_remove always removed region with .iova = 0. Right iova were
sent to the device.
* Next map will fill the first region with .iova = 0, causing a mapping
with the same iova and device complains, if the next action is a map.
* Next unmap will cause to try to unmap again iova = 0, causing the
device to complain that no region was mapped at iova = 0.
Fixes: 34e3c94edaef ("vdpa: Add custom IOTLB translations to SVQ")
Reported-by: Lei Yang <leiyang@redhat.com>
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
Diffstat (limited to 'hw/virtio')
-rw-r--r-- | hw/virtio/vhost-vdpa.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index bce64f4..3ff9ce3 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -290,7 +290,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, result = vhost_iova_tree_find_iova(v->iova_tree, &mem_region); iova = result->iova; - vhost_iova_tree_remove(v->iova_tree, &mem_region); + vhost_iova_tree_remove(v->iova_tree, result); } vhost_vdpa_iotlb_batch_begin_once(v); ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); |