Message ID | 20230228093937.2515-4-longpeng2@huawei.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | virtio-pci: optimize set_guest_notifier | expand |
On Tue, Feb 28, 2023 at 05:39:37PM +0800, Longpeng(Mike) wrote: > From: Longpeng <longpeng2@huawei.com> > > All unmasked vectors will be setup in msix_set_vector_notifiers(), which > is a time-consuming operation because each vector need to be submit to > KVM once. It's even worse if the VM has several devices and each devices > has dozens of vectors. > > We can defer and commit the vectors in batch, just like the commit dc580d51f7 > ("vfio: defer to commit kvm irq routing when enable msi/msix"), > > The can reduce 80% of the time spending on virtio_pci_set_guest_notifiers(). cover letter also refers to 80%. what about patch 1 then? does it contribute some of this gain? > Signed-off-by: Longpeng <longpeng2@huawei.com> In the age of language models there's no longer any excuse to post agrammatical commit messages. Please just give your text to one of these to correct. I prompted: "please correct grammar in the following text" and got back: All unmasked vectors will be set up in msix_set_vector_notifiers(), which is a time-consuming operation because each vector needs to be submitted to KVM once. It's even worse if the VM has several devices and each device has dozens of vectors. We can defer and commit the vectors in batches, just like the commit dc580d51f7 ("vfio: defer to commit kvm irq routing when enabling msi/msix"). This can reduce the time spent on virtio_pci_set_guest_notifiers() by 80%. > --- > hw/virtio/virtio-pci.c | 113 ++++++++++++++++++++++++++++++++----- > include/hw/virtio/virtio.h | 1 + > 2 files changed, 99 insertions(+), 15 deletions(-) > > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c > index 5fd02b7cb8..13f9c31009 100644 > --- a/hw/virtio/virtio-pci.c > +++ b/hw/virtio/virtio-pci.c > @@ -51,15 +51,22 @@ > > /* Protected by the BQL */ > static KVMRouteChange virtio_pci_route_change; > +static unsigned virtio_pci_route_change_depth; > > static inline void virtio_pci_begin_route_changes(void) > { > - virtio_pci_route_change = kvm_irqchip_begin_route_changes(kvm_state); > + if (!virtio_pci_route_change_depth) { > + virtio_pci_route_change = kvm_irqchip_begin_route_changes(kvm_state); > + } > + virtio_pci_route_change_depth++; > } > > static inline void virtio_pci_commit_route_changes(void) > { > - kvm_irqchip_commit_route_changes(&virtio_pci_route_change); > + virtio_pci_route_change_depth--; > + if (!virtio_pci_route_change_depth) { > + kvm_irqchip_commit_route_changes(&virtio_pci_route_change); > + } > } > > static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, > @@ -976,6 +983,88 @@ static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) > kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); > } > > +static int virtio_pci_vector_do_unmask(VirtIOPCIProxy *proxy, > + unsigned int queue_no, > + unsigned int vector, > + EventNotifier *n) > +{ > + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); > + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); > + int ret = 0; > + > + /* > + * If guest supports masking, irqfd is already setup, unmask it. > + * Otherwise, set it up now. > + */ > + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { > + k->guest_notifier_mask(vdev, queue_no, false); > + /* Test after unmasking to avoid losing events. */ > + if (k->guest_notifier_pending && > + k->guest_notifier_pending(vdev, queue_no)) { > + event_notifier_set(n); > + } > + } else { > + ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); > + } > + > + return ret; > +} > + > +static void virtio_pci_prepare_kvm_msi_virq_batch(VirtIOPCIProxy *proxy) > +{ > + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); > + > + assert(!vdev->defer_kvm_irq_routing); > + vdev->defer_kvm_irq_routing = true; > + virtio_pci_begin_route_changes(); move this out of here please - otherwise it's not clear each begin is matched by commit. in fact just open code this function. > +} > + > +static void virtio_pci_commit_kvm_msi_virq_batch(VirtIOPCIProxy *proxy) > +{ > + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); > + PCIDevice *dev = &proxy->pci_dev; > + VirtQueue *vq; > + EventNotifier *n; > + int vector, index; > + int ret; > + > + assert(vdev->defer_kvm_irq_routing); > + virtio_pci_commit_route_changes(); > + vdev->defer_kvm_irq_routing = false; > + > + if (!msix_enabled(dev)) { > + return; > + } > + > + /* Unmask all unmasked vectors */ > + for (vector = 0; vector < dev->msix_entries_nr; vector++) { > + if (msix_is_masked(dev, vector)) { > + continue; > + } > + > + vq = virtio_vector_first_queue(vdev, vector); > + while (vq) { > + index = virtio_get_queue_index(vq); > + if (!virtio_queue_get_num(vdev, index)) { > + break; > + } > + if (index < proxy->nvqs_with_notifiers) { > + n = virtio_queue_get_guest_notifier(vq); > + ret = virtio_pci_vector_do_unmask(proxy, index, vector, n); > + assert(ret >= 0); > + } > + vq = virtio_vector_next_queue(vq); > + } > + > + if (vector == vdev->config_vector) { > + n = virtio_config_get_guest_notifier(vdev); > + ret = virtio_pci_vector_do_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, > + vector, n); > + assert(ret >= 0); > + } > + } > +} > + > static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, > unsigned int queue_no, > unsigned int vector, > @@ -983,7 +1072,6 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, > EventNotifier *n) > { > VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); > - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); > VirtIOIRQFD *irqfd; > int ret = 0; > > @@ -1002,19 +1090,10 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, > } > } > > - /* If guest supports masking, irqfd is already setup, unmask it. > - * Otherwise, set it up now. > - */ > - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { > - k->guest_notifier_mask(vdev, queue_no, false); > - /* Test after unmasking to avoid losing events. */ > - if (k->guest_notifier_pending && > - k->guest_notifier_pending(vdev, queue_no)) { > - event_notifier_set(n); > - } > - } else { > - ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); > + if (!vdev->defer_kvm_irq_routing) { > + ret = virtio_pci_vector_do_unmask(proxy, queue_no, vector, n); > } > + > return ret; > } > > @@ -1284,12 +1363,16 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) > } > } > > + virtio_pci_prepare_kvm_msi_virq_batch(proxy); > + > r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, > virtio_pci_vector_mask, > virtio_pci_vector_poll); > if (r < 0) { > goto notifiers_error; > } > + > + virtio_pci_commit_kvm_msi_virq_batch(proxy); > } > > return 0; > diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h > index 77c6c55929..9d82831350 100644 > --- a/include/hw/virtio/virtio.h > +++ b/include/hw/virtio/virtio.h > @@ -147,6 +147,7 @@ struct VirtIODevice > bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */ > bool disable_legacy_check; > bool vhost_started; > + bool defer_kvm_irq_routing; Can't we avoid leaking kvm things all over the place? What does this flag even mean? > VMChangeStateEntry *vmstate; > char *bus_name; > uint8_t device_endian; > -- > 2.23.0
On Tue, Feb 28, 2023 at 05:40:33AM -0500, Michael S. Tsirkin wrote: > On Tue, Feb 28, 2023 at 05:39:37PM +0800, Longpeng(Mike) wrote: > > From: Longpeng <longpeng2@huawei.com> > > > > All unmasked vectors will be setup in msix_set_vector_notifiers(), which > > is a time-consuming operation because each vector need to be submit to > > KVM once. It's even worse if the VM has several devices and each devices > > has dozens of vectors. > > > > We can defer and commit the vectors in batch, just like the commit dc580d51f7 > > ("vfio: defer to commit kvm irq routing when enable msi/msix"), > > > > The can reduce 80% of the time spending on virtio_pci_set_guest_notifiers(). > > cover letter also refers to 80%. what about patch 1 then? does it > contribute some of this gain? > > > Signed-off-by: Longpeng <longpeng2@huawei.com> > > In the age of language models there's no longer any excuse to post > agrammatical commit messages. IMHO it is not appropriate to criticize the writing of people who may not have English as a first language. > Please just give your text to one of these > to correct. I'd really rather we don't suggest our contributors feed stuff through such systems. You might have an example where its output made sense, but there's plenty of demonstrations of such tools outputting obvious garbage, or worse stuff that superficially looks OK but is subtly changing the meaning. The latter is going to be especially hard to spot for contributors without English as a first language. IMHO it is better to have explanations directly written by the contributor so it accurately reflects their own understanding of the patch, even if not grammatically perfect. And that's ignoring the unsettled legal questions around the licensing of output from these systems. Personally I'd suggest our coding guidelines should explicitly reject any usage of so called "AI" systems for QEMU contributions because of legal uncertainty alone. With regards, Daniel
在 2023/2/28 18:40, Michael S. Tsirkin 写道: > On Tue, Feb 28, 2023 at 05:39:37PM +0800, Longpeng(Mike) wrote: >> From: Longpeng <longpeng2@huawei.com> >> >> All unmasked vectors will be setup in msix_set_vector_notifiers(), which >> is a time-consuming operation because each vector need to be submit to >> KVM once. It's even worse if the VM has several devices and each devices >> has dozens of vectors. >> >> We can defer and commit the vectors in batch, just like the commit dc580d51f7 >> ("vfio: defer to commit kvm irq routing when enable msi/msix"), >> >> The can reduce 80% of the time spending on virtio_pci_set_guest_notifiers(). > > cover letter also refers to 80%. what about patch 1 then? does it > contribute some of this gain? > Sorry, it's a clerical error, patch 3 reduces 50% in actually. In my test, patch 1 can reduce 37%(160ms->101ms) and patch 3 can reduce 50%(101ms->21ms, 80/160). >> Signed-off-by: Longpeng <longpeng2@huawei.com> > > In the age of language models there's no longer any excuse to post > agrammatical commit messages. Please just give your text to one of these > to correct. > Oh, I really envy you because I can not use it in my workspace. Thank you for your correction. > I prompted: "please correct grammar in the following text" > and got back: > > All unmasked vectors will be set up in > msix_set_vector_notifiers(), which is a time-consuming operation because > each vector needs to be submitted to KVM once. It's even worse if the VM > has several devices and each device has dozens of vectors. > > We can defer and commit the vectors in batches, just like the > commit dc580d51f7 ("vfio: defer to commit kvm irq routing when enabling > msi/msix"). > > This can reduce the time spent on virtio_pci_set_guest_notifiers() by 80%. > > > > >> --- >> hw/virtio/virtio-pci.c | 113 ++++++++++++++++++++++++++++++++----- >> include/hw/virtio/virtio.h | 1 + >> 2 files changed, 99 insertions(+), 15 deletions(-) >> >> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c >> index 5fd02b7cb8..13f9c31009 100644 >> --- a/hw/virtio/virtio-pci.c >> +++ b/hw/virtio/virtio-pci.c >> @@ -51,15 +51,22 @@ >> >> /* Protected by the BQL */ >> static KVMRouteChange virtio_pci_route_change; >> +static unsigned virtio_pci_route_change_depth; >> >> static inline void virtio_pci_begin_route_changes(void) >> { >> - virtio_pci_route_change = kvm_irqchip_begin_route_changes(kvm_state); >> + if (!virtio_pci_route_change_depth) { >> + virtio_pci_route_change = kvm_irqchip_begin_route_changes(kvm_state); >> + } >> + virtio_pci_route_change_depth++; >> } >> >> static inline void virtio_pci_commit_route_changes(void) >> { >> - kvm_irqchip_commit_route_changes(&virtio_pci_route_change); >> + virtio_pci_route_change_depth--; >> + if (!virtio_pci_route_change_depth) { >> + kvm_irqchip_commit_route_changes(&virtio_pci_route_change); >> + } >> } >> >> static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, >> @@ -976,6 +983,88 @@ static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) >> kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); >> } >> >> +static int virtio_pci_vector_do_unmask(VirtIOPCIProxy *proxy, >> + unsigned int queue_no, >> + unsigned int vector, >> + EventNotifier *n) >> +{ >> + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); >> + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); >> + int ret = 0; >> + >> + /* >> + * If guest supports masking, irqfd is already setup, unmask it. >> + * Otherwise, set it up now. >> + */ >> + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { >> + k->guest_notifier_mask(vdev, queue_no, false); >> + /* Test after unmasking to avoid losing events. */ >> + if (k->guest_notifier_pending && >> + k->guest_notifier_pending(vdev, queue_no)) { >> + event_notifier_set(n); >> + } >> + } else { >> + ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); >> + } >> + >> + return ret; >> +} >> + >> +static void virtio_pci_prepare_kvm_msi_virq_batch(VirtIOPCIProxy *proxy) >> +{ >> + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); >> + >> + assert(!vdev->defer_kvm_irq_routing); >> + vdev->defer_kvm_irq_routing = true; >> + virtio_pci_begin_route_changes(); > > move this out of here please - otherwise it's not clear each begin > is matched by commit. in fact just open code this function. > >> +} >> + >> +static void virtio_pci_commit_kvm_msi_virq_batch(VirtIOPCIProxy *proxy) >> +{ >> + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); >> + PCIDevice *dev = &proxy->pci_dev; >> + VirtQueue *vq; >> + EventNotifier *n; >> + int vector, index; >> + int ret; >> + >> + assert(vdev->defer_kvm_irq_routing); >> + virtio_pci_commit_route_changes(); >> + vdev->defer_kvm_irq_routing = false; >> + >> + if (!msix_enabled(dev)) { >> + return; >> + } >> + >> + /* Unmask all unmasked vectors */ >> + for (vector = 0; vector < dev->msix_entries_nr; vector++) { >> + if (msix_is_masked(dev, vector)) { >> + continue; >> + } >> + >> + vq = virtio_vector_first_queue(vdev, vector); >> + while (vq) { >> + index = virtio_get_queue_index(vq); >> + if (!virtio_queue_get_num(vdev, index)) { >> + break; >> + } >> + if (index < proxy->nvqs_with_notifiers) { >> + n = virtio_queue_get_guest_notifier(vq); >> + ret = virtio_pci_vector_do_unmask(proxy, index, vector, n); >> + assert(ret >= 0); >> + } >> + vq = virtio_vector_next_queue(vq); >> + } >> + >> + if (vector == vdev->config_vector) { >> + n = virtio_config_get_guest_notifier(vdev); >> + ret = virtio_pci_vector_do_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, >> + vector, n); >> + assert(ret >= 0); >> + } >> + } >> +} >> + >> static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, >> unsigned int queue_no, >> unsigned int vector, >> @@ -983,7 +1072,6 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, >> EventNotifier *n) >> { >> VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); >> - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); >> VirtIOIRQFD *irqfd; >> int ret = 0; >> >> @@ -1002,19 +1090,10 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, >> } >> } >> >> - /* If guest supports masking, irqfd is already setup, unmask it. >> - * Otherwise, set it up now. >> - */ >> - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { >> - k->guest_notifier_mask(vdev, queue_no, false); >> - /* Test after unmasking to avoid losing events. */ >> - if (k->guest_notifier_pending && >> - k->guest_notifier_pending(vdev, queue_no)) { >> - event_notifier_set(n); >> - } >> - } else { >> - ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); >> + if (!vdev->defer_kvm_irq_routing) { >> + ret = virtio_pci_vector_do_unmask(proxy, queue_no, vector, n); >> } >> + >> return ret; >> } >> >> @@ -1284,12 +1363,16 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) >> } >> } >> >> + virtio_pci_prepare_kvm_msi_virq_batch(proxy); >> + >> r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, >> virtio_pci_vector_mask, >> virtio_pci_vector_poll); >> if (r < 0) { >> goto notifiers_error; >> } >> + >> + virtio_pci_commit_kvm_msi_virq_batch(proxy); >> } >> >> return 0; >> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h >> index 77c6c55929..9d82831350 100644 >> --- a/include/hw/virtio/virtio.h >> +++ b/include/hw/virtio/virtio.h >> @@ -147,6 +147,7 @@ struct VirtIODevice >> bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */ >> bool disable_legacy_check; >> bool vhost_started; >> + bool defer_kvm_irq_routing; > > Can't we avoid leaking kvm things all over the place? > What does this flag even mean? > >> VMChangeStateEntry *vmstate; >> char *bus_name; >> uint8_t device_endian; >> -- >> 2.23.0 > > .
On Tue, Feb 28, 2023 at 07:10:36PM +0800, Longpeng (Mike, Cloud Infrastructure Service Product Dept.) wrote: > Oh, I really envy you because I can not use it in my workspace. Thank you > for your correction. :( I keep seeing these adverts for grammarly, try this maybe :)
On Tue, Feb 28, 2023 at 11:07:21AM +0000, Daniel P. Berrangé wrote: > IMHO it is not appropriate to criticize the writing of people > who may not have English as a first language. Sorry if I offended anyone. I do want change log messages to be clear and unambigous though since they are a permanent record. Me rewriting them for contributors does not seem to scale. I was hoping a grammar checker will help but if not I don't know what to suggest then.
On Tue, Feb 28, 2023 at 07:29:42AM -0500, Michael S. Tsirkin wrote: > On Tue, Feb 28, 2023 at 11:07:21AM +0000, Daniel P. Berrangé wrote: > > IMHO it is not appropriate to criticize the writing of people > > who may not have English as a first language. > > Sorry if I offended anyone. I do want change log messages to be clear > and unambigous though since they are a permanent record. Me rewriting > them for contributors does not seem to scale. I was hoping a grammar > checker will help but if not I don't know what to suggest then. Agreed that having the maintainer frequently rewriting them isn't scalable in general, but that's not the common case I think/hope. If a commit message truely isn't easy enough to understand, it is reasonable to ask the contributor to clarify it and post a v2, giving them some hints where appropriate. If it is just sub-optimal grammar that doesn't massively impact understanding, then I'm inclined to just accept patches as is, or do very minor copy editting for obvious / simple issues. With regards, Daniel
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 5fd02b7cb8..13f9c31009 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -51,15 +51,22 @@ /* Protected by the BQL */ static KVMRouteChange virtio_pci_route_change; +static unsigned virtio_pci_route_change_depth; static inline void virtio_pci_begin_route_changes(void) { - virtio_pci_route_change = kvm_irqchip_begin_route_changes(kvm_state); + if (!virtio_pci_route_change_depth) { + virtio_pci_route_change = kvm_irqchip_begin_route_changes(kvm_state); + } + virtio_pci_route_change_depth++; } static inline void virtio_pci_commit_route_changes(void) { - kvm_irqchip_commit_route_changes(&virtio_pci_route_change); + virtio_pci_route_change_depth--; + if (!virtio_pci_route_change_depth) { + kvm_irqchip_commit_route_changes(&virtio_pci_route_change); + } } static void virtio_pci_bus_new(VirtioBusState *bus, size_t bus_size, @@ -976,6 +983,88 @@ static void kvm_virtio_pci_vector_config_release(VirtIOPCIProxy *proxy) kvm_virtio_pci_vector_release_one(proxy, VIRTIO_CONFIG_IRQ_IDX); } +static int virtio_pci_vector_do_unmask(VirtIOPCIProxy *proxy, + unsigned int queue_no, + unsigned int vector, + EventNotifier *n) +{ + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + int ret = 0; + + /* + * If guest supports masking, irqfd is already setup, unmask it. + * Otherwise, set it up now. + */ + if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { + k->guest_notifier_mask(vdev, queue_no, false); + /* Test after unmasking to avoid losing events. */ + if (k->guest_notifier_pending && + k->guest_notifier_pending(vdev, queue_no)) { + event_notifier_set(n); + } + } else { + ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + } + + return ret; +} + +static void virtio_pci_prepare_kvm_msi_virq_batch(VirtIOPCIProxy *proxy) +{ + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + + assert(!vdev->defer_kvm_irq_routing); + vdev->defer_kvm_irq_routing = true; + virtio_pci_begin_route_changes(); +} + +static void virtio_pci_commit_kvm_msi_virq_batch(VirtIOPCIProxy *proxy) +{ + VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); + PCIDevice *dev = &proxy->pci_dev; + VirtQueue *vq; + EventNotifier *n; + int vector, index; + int ret; + + assert(vdev->defer_kvm_irq_routing); + virtio_pci_commit_route_changes(); + vdev->defer_kvm_irq_routing = false; + + if (!msix_enabled(dev)) { + return; + } + + /* Unmask all unmasked vectors */ + for (vector = 0; vector < dev->msix_entries_nr; vector++) { + if (msix_is_masked(dev, vector)) { + continue; + } + + vq = virtio_vector_first_queue(vdev, vector); + while (vq) { + index = virtio_get_queue_index(vq); + if (!virtio_queue_get_num(vdev, index)) { + break; + } + if (index < proxy->nvqs_with_notifiers) { + n = virtio_queue_get_guest_notifier(vq); + ret = virtio_pci_vector_do_unmask(proxy, index, vector, n); + assert(ret >= 0); + } + vq = virtio_vector_next_queue(vq); + } + + if (vector == vdev->config_vector) { + n = virtio_config_get_guest_notifier(vdev); + ret = virtio_pci_vector_do_unmask(proxy, VIRTIO_CONFIG_IRQ_IDX, + vector, n); + assert(ret >= 0); + } + } +} + static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, unsigned int queue_no, unsigned int vector, @@ -983,7 +1072,6 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, EventNotifier *n) { VirtIODevice *vdev = virtio_bus_get_device(&proxy->bus); - VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); VirtIOIRQFD *irqfd; int ret = 0; @@ -1002,19 +1090,10 @@ static int virtio_pci_one_vector_unmask(VirtIOPCIProxy *proxy, } } - /* If guest supports masking, irqfd is already setup, unmask it. - * Otherwise, set it up now. - */ - if (vdev->use_guest_notifier_mask && k->guest_notifier_mask) { - k->guest_notifier_mask(vdev, queue_no, false); - /* Test after unmasking to avoid losing events. */ - if (k->guest_notifier_pending && - k->guest_notifier_pending(vdev, queue_no)) { - event_notifier_set(n); - } - } else { - ret = kvm_virtio_pci_irqfd_use(proxy, n, vector); + if (!vdev->defer_kvm_irq_routing) { + ret = virtio_pci_vector_do_unmask(proxy, queue_no, vector, n); } + return ret; } @@ -1284,12 +1363,16 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) } } + virtio_pci_prepare_kvm_msi_virq_batch(proxy); + r = msix_set_vector_notifiers(&proxy->pci_dev, virtio_pci_vector_unmask, virtio_pci_vector_mask, virtio_pci_vector_poll); if (r < 0) { goto notifiers_error; } + + virtio_pci_commit_kvm_msi_virq_batch(proxy); } return 0; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 77c6c55929..9d82831350 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -147,6 +147,7 @@ struct VirtIODevice bool start_on_kick; /* when virtio 1.0 feature has not been negotiated */ bool disable_legacy_check; bool vhost_started; + bool defer_kvm_irq_routing; VMChangeStateEntry *vmstate; char *bus_name; uint8_t device_endian;