virtio: Fix virtio_mmio_read()/virtio_mmio_write()

Both functions don't check the personality of the interface (legacy or
modern) before accessing the configuration memory and always use
virtio_config_readX()/virtio_config_writeX().

With this patch, they now check the personality and in legacy mode
call virtio_config_readX()/virtio_config_writeX(), otherwise call
virtio_config_modern_readX()/virtio_config_modern_writeX().

This change has been tested with virtio-mmio guests (virt stretch/armhf and
virt sid/m68k) and virtio-pci guests (pseries RHEL-7.3/ppc64 and /ppc64le).

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Message-Id: <20210314200300.3259170-1-laurent@vivier.eu>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Laurent Vivier 2021-03-14 21:03:00 +01:00 committed by Michael S. Tsirkin
parent f0f20022a0
commit 0ab8c021c6
1 changed files with 52 additions and 22 deletions

View File

@ -112,15 +112,28 @@ static uint64_t virtio_mmio_read(void *opaque, hwaddr offset, unsigned size)
if (offset >= VIRTIO_MMIO_CONFIG) {
offset -= VIRTIO_MMIO_CONFIG;
switch (size) {
case 1:
return virtio_config_readb(vdev, offset);
case 2:
return virtio_config_readw(vdev, offset);
case 4:
return virtio_config_readl(vdev, offset);
default:
abort();
if (proxy->legacy) {
switch (size) {
case 1:
return virtio_config_readb(vdev, offset);
case 2:
return virtio_config_readw(vdev, offset);
case 4:
return virtio_config_readl(vdev, offset);
default:
abort();
}
} else {
switch (size) {
case 1:
return virtio_config_modern_readb(vdev, offset);
case 2:
return virtio_config_modern_readw(vdev, offset);
case 4:
return virtio_config_modern_readl(vdev, offset);
default:
abort();
}
}
}
if (size != 4) {
@ -245,20 +258,37 @@ static void virtio_mmio_write(void *opaque, hwaddr offset, uint64_t value,
if (offset >= VIRTIO_MMIO_CONFIG) {
offset -= VIRTIO_MMIO_CONFIG;
switch (size) {
case 1:
virtio_config_writeb(vdev, offset, value);
break;
case 2:
virtio_config_writew(vdev, offset, value);
break;
case 4:
virtio_config_writel(vdev, offset, value);
break;
default:
abort();
if (proxy->legacy) {
switch (size) {
case 1:
virtio_config_writeb(vdev, offset, value);
break;
case 2:
virtio_config_writew(vdev, offset, value);
break;
case 4:
virtio_config_writel(vdev, offset, value);
break;
default:
abort();
}
return;
} else {
switch (size) {
case 1:
virtio_config_modern_writeb(vdev, offset, value);
break;
case 2:
virtio_config_modern_writew(vdev, offset, value);
break;
case 4:
virtio_config_modern_writel(vdev, offset, value);
break;
default:
abort();
}
return;
}
return;
}
if (size != 4) {
qemu_log_mask(LOG_GUEST_ERROR,