Hi Stefano,

I’ve implemented the version based on your suggestion. The core logic
now looks like this:
if (k->query_guest_notifiers &&
    !k->query_guest_notifiers(qbus->parent) &&
    virtio_queue_vector(vdev, idx) == VIRTIO_NO_VECTOR) {
    ...
}

And in virtio_pci_query_guest_notifiers():
if (msix_enabled(&proxy->pci_dev)) {
    return false;
} else {
    return !pci_irq_disabled(&proxy->pci_dev);
}

Although this works and preserves the original interface, I personally
find the logic less intuitive to read.
if you're fine with this version, I’ll go ahead and send v3 based on it.

Thanks.
Huaitong Han

Stefano Garzarella <sgarz...@redhat.com> 于2025年5月20日周二 20:53写道:
>
> On Tue, May 20, 2025 at 08:30:39PM +0800, Huaitong Han wrote:
> >Stefano Garzarella <sgarz...@redhat.com> 于2025年5月20日周二 19:41写道:
> >>
> >> On Tue, May 13, 2025 at 07:28:25PM +0800, oen...@gmail.com wrote:
> >> >From: Huaitong Han <han...@chinatelecom.cn>
> >> >
> >> >The vring call fd is set even when the guest does not use MSI-X (e.g., in 
> >> >the
> >> >case of virtio PMD), leading to unnecessary CPU overhead for processing
> >> >interrupts.
> >> >
> >> >The commit 96a3d98d2c("vhost: don't set vring call if no vector") 
> >> >optimized the
> >> >case where MSI-X is enabled but the queue vector is unset. However, 
> >> >there's an
> >> >additional case where the guest uses INTx and the INTx_DISABLED bit in 
> >> >the PCI
> >> >config is set, meaning that no interrupt notifier will actually be used.
> >> >
> >> >In such cases, the vring call fd should also be cleared to avoid redundant
> >> >interrupt handling.
> >> >
> >> >Fixes: 96a3d98d2c("vhost: don't set vring call if no vector")
> >>                    ^
> >> nit: there should be a space here.
> >>
> >> If you need to resend, I think you can fix also the one in the
> >> description.
> >>
> >> >Reported-by: Zhiyuan Yuan <yuanzhiy...@chinatelecom.cn>
> >> >Signed-off-by: Jidong Xia <xi...@chinatelecom.cn>
> >> >Signed-off-by: Huaitong Han <han...@chinatelecom.cn>
> >> >---
> >> >V2:
> >> >- Retain the name `query_guest_notifiers`
> >> >- All qtest/unit test cases pass
> >> >- Fix V1 patch style problems
> >> >
> >> > hw/pci/pci.c                   |  2 +-
> >> > hw/s390x/virtio-ccw.c          |  7 +++++--
> >> > hw/virtio/vhost.c              |  3 +--
> >> > hw/virtio/virtio-pci.c         | 10 ++++++++--
> >> > include/hw/pci/pci.h           |  1 +
> >> > include/hw/virtio/virtio-bus.h |  2 +-
> >> > 6 files changed, 17 insertions(+), 8 deletions(-)
> >> >
> >> >diff --git a/hw/pci/pci.c b/hw/pci/pci.c
> >> >index 352b3d12c8..45b491412a 100644
> >> >--- a/hw/pci/pci.c
> >> >+++ b/hw/pci/pci.c
> >> >@@ -1712,7 +1712,7 @@ static void pci_update_mappings(PCIDevice *d)
> >> >     pci_update_vga(d);
> >> > }
> >> >
> >> >-static inline int pci_irq_disabled(PCIDevice *d)
> >> >+int pci_irq_disabled(PCIDevice *d)
> >> > {
> >> >     return pci_get_word(d->config + PCI_COMMAND) & 
> >> > PCI_COMMAND_INTX_DISABLE;
> >> > }
> >> >diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
> >> >index d2f85b39f3..632708ba4d 100644
> >> >--- a/hw/s390x/virtio-ccw.c
> >> >+++ b/hw/s390x/virtio-ccw.c
> >> >@@ -936,11 +936,14 @@ static void virtio_ccw_vmstate_change(DeviceState 
> >> >*d, bool running)
> >> >     }
> >> > }
> >> >
> >> >-static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
> >> >+static bool virtio_ccw_query_guest_notifiers(DeviceState *d, int n)
> >> > {
> >> >     CcwDevice *dev = CCW_DEVICE(d);
> >> >+    VirtioCcwDevice *vdev = VIRTIO_CCW_DEVICE(d);
> >> >+    VirtIODevice *virtio_dev = virtio_bus_get_device(&vdev->bus);
> >> >
> >> >-    return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
> >> >+    return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA)
> >> >+            && virtio_queue_vector(virtio_dev, n) != VIRTIO_NO_VECTOR;
> >> > }
> >> >
> >> > static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
> >> >diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> >> >index 4cae7c1664..2a9a839763 100644
> >> >--- a/hw/virtio/vhost.c
> >> >+++ b/hw/virtio/vhost.c
> >> >@@ -1341,8 +1341,7 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
> >> >     }
> >> >
> >> >     if (k->query_guest_notifiers &&
> >> >-        k->query_guest_notifiers(qbus->parent) &&
> >> >-        virtio_queue_vector(vdev, idx) == VIRTIO_NO_VECTOR) {
> >> >+        !k->query_guest_notifiers(qbus->parent, idx)) {
> >> >         file.fd = -1;
> >> >         r = dev->vhost_ops->vhost_set_vring_call(dev, &file);
> >> >         if (r) {
> >> >diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> >> >index 0fa8fe4955..d62e199489 100644
> >> >--- a/hw/virtio/virtio-pci.c
> >> >+++ b/hw/virtio/virtio-pci.c
> >> >@@ -1212,10 +1212,16 @@ static int 
> >> >virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
> >> >     return 0;
> >> > }
> >> >
> >> >-static bool virtio_pci_query_guest_notifiers(DeviceState *d)
> >> >+static bool virtio_pci_query_guest_notifiers(DeviceState *d, int n)
> >> > {
> >> >     VirtIOPCIProxy *proxy = to_virtio_pci_proxy(d);
> >> >-    return msix_enabled(&proxy->pci_dev);
> >> >+    VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus);
> >> >+
> >> >+    if (msix_enabled(&proxy->pci_dev)) {
> >> >+        return virtio_queue_vector(vdev, n) != VIRTIO_NO_VECTOR;
> >>
> >> Why are we moving this check in every callback, can't we leave it as
> >> before in vhost.c and here return true?
> >>
> >> I mean here:
> >>      if (msix_enabled(&proxy->pci_dev)) {
> >>          return true;
> >>      } else {
> >>          return !pci_irq_disabled(&proxy->pci_dev);
> >>      }
> >>
> >> and leave vhost.c untouched.
> >>
> >
> >Thanks for the suggestion — your approach indeed achieves the same
> >effect while keeping the interface unchanged.
> >However, I feel it might lead to some misunderstanding of the intended
> >semantics of query_guest_notifiers. My original intent was for this
> >callback to represent whether interrupts are actually in use by the
> >guest, and in that sense, checking whether the queue uses a vector is
> >part of that definition.
>
> Okay, but IMHO these should be 2 patches, one that fixes the problem you
> mentioned (to be backported to stable, so with the Fixes tag),
> minimizing the changes. And another patch where you change the
> semantics.
>
> >By splitting the logic — checking msix_enabled and pci_irq_disabled
> >inside the bus callback, and virtio_queue_vector() separately in
> >vhost.c — the semantic boundary becomes less clear. While it works
> >logically, it can reduce readability — particularly because the
> >virtio_queue_vector() check semantically belongs under the
> >msix_enabled() branch, and combining it with the pci_irq_disabled()
> >case (INTx) could make the logic less clear to future readers.
> >Additionally, the set_host_notifier_mr interface already includes an
> >int n parameter, so adding it to query_guest_notifiers is accepted.
>
> I'm not sure that delegating the call to virtio_queue_vector() to each
> bus is an improvement honestly. But we can discuss it on the patch.
>
> Thanks,
> Stefano
>

Reply via email to