[PATCH v2 4/4] hw/pci/msix: fix error handling for msix_init callers

Trieu Huynh posted 4 patches 3 weeks, 6 days ago
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Helge Deller <deller@gmx.de>, "Maciej S. Szmigiero" <maciej.szmigiero@oracle.com>, Corey Minyard <minyard@acm.org>, Thomas Huth <th.huth+qemu@posteo.eu>, Laurent Vivier <laurent@vivier.eu>, "Edgar E. Iglesias" <edgar.iglesias@gmail.com>, Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>, Sriram Yagnaraman <sriram.yagnaraman@ericsson.com>, Jason Wang <jasowang@redhat.com>, Jiri Pirko <jiri@resnulli.us>, "Michael S. Tsirkin" <mst@redhat.com>, Marcel Apfelbaum <marcel.apfelbaum@gmail.com>, Elena Ufimtseva <elena.ufimtseva@oracle.com>, Jagannathan Raman <jag.raman@oracle.com>, Paolo Bonzini <pbonzini@redhat.com>, Fam Zheng <fam@euphon.net>, "Clément Chigot" <chigot@adacore.com>, Frederic Konrad <konrad.frederic@yahoo.fr>, Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>, Artyom Tarasenko <atar4qemu@gmail.com>, Tony Krowiak <akrowiak@linux.ibm.com>, Halil Pasic <pasic@linux.ibm.com>, Jason Herne <jjherne@linux.ibm.com>, Cornelia Huck <cohuck@redhat.com>, Eric Farman <farman@linux.ibm.com>, Matthew Rosato <mjrosato@linux.ibm.com>, Alex Williamson <alex@shazbot.org>, "Cédric Le Goater" <clg@redhat.com>, Stefano Garzarella <sgarzare@redhat.com>
There is a newer version of this series
[PATCH v2 4/4] hw/pci/msix: fix error handling for msix_init callers
Posted by Trieu Huynh 3 weeks, 6 days ago
From: Trieu Huynh <vikingtc4@gmail.com>

Check return value of msix_init() and return early on
failure instead of continuing with invalid state.
- Use ret < 0 to handle negative return value.
- Use errp parameter to handle failure instead of NULL.
- No functional changes.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/413
Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>

---
v2:
- Use errp parameter to handle failure instead of NULL.
---
 hw/net/igbvf.c         |  2 +-
 hw/net/rocker/rocker.c |  2 +-
 hw/pci/msix.c          |  2 +-
 hw/scsi/megasas.c      | 18 +++++++++++++-----
 hw/usb/hcd-xhci-pci.c  | 19 ++++++++++++++-----
 5 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/hw/net/igbvf.c b/hw/net/igbvf.c
index 48d56e43ac..9a165c7063 100644
--- a/hw/net/igbvf.c
+++ b/hw/net/igbvf.c
@@ -260,7 +260,7 @@ static void igbvf_pci_realize(PCIDevice *dev, Error **errp)
 
     ret = msix_init(dev, IGBVF_MSIX_VEC_NUM, &s->msix, IGBVF_MSIX_BAR_IDX, 0,
         &s->msix, IGBVF_MSIX_BAR_IDX, 0x2000, 0x70, errp);
-    if (ret) {
+    if (ret < 0) {
         return;
     }
 
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 4a7056bd45..910dce901b 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -1228,7 +1228,7 @@ static int rocker_msix_init(Rocker *r, Error **errp)
                     &r->msix_bar,
                     ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_PBA_OFFSET,
                     0, errp);
-    if (err) {
+    if (err < 0) {
         return err;
     }
 
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index b35476d057..1b23eaf100 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -432,7 +432,7 @@ int msix_init_exclusive_bar(PCIDevice *dev, uint32_t nentries,
                     0, &dev->msix_exclusive_bar,
                     bar_nr, bar_pba_offset,
                     0, errp);
-    if (ret) {
+    if (ret < 0) {
         return ret;
     }
 
diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
index f62e420a91..b237ba7656 100644
--- a/hw/scsi/megasas.c
+++ b/hw/scsi/megasas.c
@@ -2380,11 +2380,19 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
     memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,
                           "megasas-queue", 0x40000);
 
-    if (megasas_use_msix(s) &&
-        msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,
-                  &s->mmio_io, b->mmio_bar, 0x3800, 0x68, NULL)) {
-        /* TODO: check msix_init's error, and should fail on msix=on */
-        s->msix = ON_OFF_AUTO_OFF;
+    if (megasas_use_msix(s)) {
+        Error *local_err = NULL;
+        ret = msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,
+                        &s->mmio_io, b->mmio_bar, 0x3800, 0x68, &local_err);
+
+        if (ret < 0) {
+            if (s->msix == ON_OFF_AUTO_ON) {
+                error_propagate(errp, local_err);
+                return;
+            }
+            error_free(local_err);
+            s->msix = ON_OFF_AUTO_OFF;
+        }
     }
 
     if (pci_is_express(dev)) {
diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
index aa570506fc..3bdde9b64a 100644
--- a/hw/usb/hcd-xhci-pci.c
+++ b/hw/usb/hcd-xhci-pci.c
@@ -173,11 +173,20 @@ static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp)
     }
 
     if (s->msix != ON_OFF_AUTO_OFF) {
-        /* TODO check for errors, and should fail when msix=on */
-        msix_init(dev, s->xhci.numintrs,
-                  &s->xhci.mem, 0, OFF_MSIX_TABLE,
-                  &s->xhci.mem, 0, OFF_MSIX_PBA,
-                  0x90, NULL);
+        Error *local_err = NULL;
+        ret = msix_init(dev, s->xhci.numintrs,
+                        &s->xhci.mem, 0, OFF_MSIX_TABLE,
+                        &s->xhci.mem, 0, OFF_MSIX_PBA,
+                        0x90, &local_err);
+
+        if (ret < 0) {
+            if (s->msix == ON_OFF_AUTO_ON) {
+                error_propagate(errp, local_err);
+                return;
+            }
+            error_free(local_err);
+            s->msix = ON_OFF_AUTO_OFF;
+        }
     }
     s->xhci.as = pci_get_address_space(dev);
 }
-- 
2.43.0
Re: [PATCH v2 4/4] hw/pci/msix: fix error handling for msix_init callers
Posted by Akihiko Odaki 3 weeks, 4 days ago
On 2026/03/12 3:34, Trieu Huynh wrote:
> From: Trieu Huynh <vikingtc4@gmail.com>
> 
> Check return value of msix_init() and return early on
> failure instead of continuing with invalid state.
> - Use ret < 0 to handle negative return value.
> - Use errp parameter to handle failure instead of NULL.
> - No functional changes.
> 
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/413
> Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>
> 
> ---
> v2:
> - Use errp parameter to handle failure instead of NULL.
> ---
>   hw/net/igbvf.c         |  2 +-
>   hw/net/rocker/rocker.c |  2 +-
>   hw/pci/msix.c          |  2 +-
>   hw/scsi/megasas.c      | 18 +++++++++++++-----
>   hw/usb/hcd-xhci-pci.c  | 19 ++++++++++++++-----
>   5 files changed, 30 insertions(+), 13 deletions(-)
> 
> diff --git a/hw/net/igbvf.c b/hw/net/igbvf.c
> index 48d56e43ac..9a165c7063 100644
> --- a/hw/net/igbvf.c
> +++ b/hw/net/igbvf.c
> @@ -260,7 +260,7 @@ static void igbvf_pci_realize(PCIDevice *dev, Error **errp)
>   
>       ret = msix_init(dev, IGBVF_MSIX_VEC_NUM, &s->msix, IGBVF_MSIX_BAR_IDX, 0,
>           &s->msix, IGBVF_MSIX_BAR_IDX, 0x2000, 0x70, errp);
> -    if (ret) {
> +    if (ret < 0) {
>           return;
>       }
>   
> diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
> index 4a7056bd45..910dce901b 100644
> --- a/hw/net/rocker/rocker.c
> +++ b/hw/net/rocker/rocker.c
> @@ -1228,7 +1228,7 @@ static int rocker_msix_init(Rocker *r, Error **errp)
>                       &r->msix_bar,
>                       ROCKER_PCI_MSIX_BAR_IDX, ROCKER_PCI_MSIX_PBA_OFFSET,
>                       0, errp);
> -    if (err) {
> +    if (err < 0) {
>           return err;
>       }
>   
> diff --git a/hw/pci/msix.c b/hw/pci/msix.c
> index b35476d057..1b23eaf100 100644
> --- a/hw/pci/msix.c
> +++ b/hw/pci/msix.c
> @@ -432,7 +432,7 @@ int msix_init_exclusive_bar(PCIDevice *dev, uint32_t nentries,
>                       0, &dev->msix_exclusive_bar,
>                       bar_nr, bar_pba_offset,
>                       0, errp);
> -    if (ret) {
> +    if (ret < 0) {
>           return ret;
>       }
>   
> diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c
> index f62e420a91..b237ba7656 100644
> --- a/hw/scsi/megasas.c
> +++ b/hw/scsi/megasas.c
> @@ -2380,11 +2380,19 @@ static void megasas_scsi_realize(PCIDevice *dev, Error **errp)
>       memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s,
>                             "megasas-queue", 0x40000);
>   
> -    if (megasas_use_msix(s) &&
> -        msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,
> -                  &s->mmio_io, b->mmio_bar, 0x3800, 0x68, NULL)) {
> -        /* TODO: check msix_init's error, and should fail on msix=on */
> -        s->msix = ON_OFF_AUTO_OFF;
> +    if (megasas_use_msix(s)) {
> +        Error *local_err = NULL;
> +        ret = msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000,
> +                        &s->mmio_io, b->mmio_bar, 0x3800, 0x68, &local_err);
> +
> +        if (ret < 0) {
> +            if (s->msix == ON_OFF_AUTO_ON) {
> +                error_propagate(errp, local_err);

error_propagate() is discouraged in include/qapi/error.h because 
ERRP_GUARD() exists as an alternative so I thought of using it, but 
perhaps it may be a better to avoid having a local error variable 
altogether.

Instead, you can pass (s->msix == ON_OF_AUTO_ON ? errp : NULL) to 
msix_init() as the errp parameter.

Regards,
Akihiko Odaki

> +                return;
> +            }
> +            error_free(local_err);
> +            s->msix = ON_OFF_AUTO_OFF;
> +        }
>       }
>   
>       if (pci_is_express(dev)) {
> diff --git a/hw/usb/hcd-xhci-pci.c b/hw/usb/hcd-xhci-pci.c
> index aa570506fc..3bdde9b64a 100644
> --- a/hw/usb/hcd-xhci-pci.c
> +++ b/hw/usb/hcd-xhci-pci.c
> @@ -173,11 +173,20 @@ static void usb_xhci_pci_realize(struct PCIDevice *dev, Error **errp)
>       }
>   
>       if (s->msix != ON_OFF_AUTO_OFF) {
> -        /* TODO check for errors, and should fail when msix=on */
> -        msix_init(dev, s->xhci.numintrs,
> -                  &s->xhci.mem, 0, OFF_MSIX_TABLE,
> -                  &s->xhci.mem, 0, OFF_MSIX_PBA,
> -                  0x90, NULL);
> +        Error *local_err = NULL;
> +        ret = msix_init(dev, s->xhci.numintrs,
> +                        &s->xhci.mem, 0, OFF_MSIX_TABLE,
> +                        &s->xhci.mem, 0, OFF_MSIX_PBA,
> +                        0x90, &local_err);
> +
> +        if (ret < 0) {
> +            if (s->msix == ON_OFF_AUTO_ON) {
> +                error_propagate(errp, local_err);
> +                return;
> +            }
> +            error_free(local_err);
> +            s->msix = ON_OFF_AUTO_OFF;
> +        }
>       }
>       s->xhci.as = pci_get_address_space(dev);
>   }