diff mbox series

virtio: Fix virtio_mmio_read()/virtio_mmio_write()

Message ID 20210314200300.3259170-1-laurent@vivier.eu (mailing list archive)
State New, archived
Headers show
Series virtio: Fix virtio_mmio_read()/virtio_mmio_write() | expand

Commit Message

Laurent Vivier March 14, 2021, 8:03 p.m. UTC
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>
---
 hw/virtio/virtio-mmio.c | 74 +++++++++++++++++++++++++++++------------
 1 file changed, 52 insertions(+), 22 deletions(-)

Comments

Laurent Vivier March 17, 2021, 2:18 p.m. UTC | #1
Hi,

could this fix be merged in QEMU 6.0?

Thanks,
Laurent

Le 14/03/2021 à 21:03, Laurent Vivier a écrit :
> 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>
> ---
>  hw/virtio/virtio-mmio.c | 74 +++++++++++++++++++++++++++++------------
>  1 file changed, 52 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
> index 6990b9879cf0..342c918ea7b7 100644
> --- a/hw/virtio/virtio-mmio.c
> +++ b/hw/virtio/virtio-mmio.c
> @@ -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,
>
Stefano Garzarella March 19, 2021, 9:24 a.m. UTC | #2
On Sun, Mar 14, 2021 at 09:03:00PM +0100, Laurent Vivier wrote:
>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>
>---
> hw/virtio/virtio-mmio.c | 74 +++++++++++++++++++++++++++++------------
> 1 file changed, 52 insertions(+), 22 deletions(-)
>

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
diff mbox series

Patch

diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
index 6990b9879cf0..342c918ea7b7 100644
--- a/hw/virtio/virtio-mmio.c
+++ b/hw/virtio/virtio-mmio.c
@@ -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,