* [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off
@ 2013-04-15 14:40 Michael S. Tsirkin
2013-04-17 12:03 ` Christian Borntraeger
2013-04-18 17:19 ` [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off Alexander Graf
0 siblings, 2 replies; 9+ messages in thread
From: Michael S. Tsirkin @ 2013-04-15 14:40 UTC (permalink / raw)
To: Alexander Graf; +Cc: qemu-devel
In response to a bug report on IRC: this should fix it I think?
Need to test properly but out of time for today,
compiled only. Hope this helps.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 8bba0f3..d0fcc6c 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -758,6 +758,10 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
event_notifier_cleanup(notifier);
}
+ if (!msix_enabled(&proxy->pci_dev) && proxy->vdev->guest_notifier_mask) {
+ proxy->vdev->guest_notifier_mask(proxy->vdev, n, !assign);
+ }
+
return 0;
}
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off
2013-04-15 14:40 [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off Michael S. Tsirkin
@ 2013-04-17 12:03 ` Christian Borntraeger
2013-04-17 13:42 ` Michael S. Tsirkin
2013-04-18 17:19 ` [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off Alexander Graf
1 sibling, 1 reply; 9+ messages in thread
From: Christian Borntraeger @ 2013-04-17 12:03 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Cornelia Huck, Alexander Graf, qemu-devel
On 15/04/13 16:40, Michael S. Tsirkin wrote:
> In response to a bug report on IRC: this should fix it I think?
> Need to test properly but out of time for today,
> compiled only. Hope this helps.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
>
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 8bba0f3..d0fcc6c 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -758,6 +758,10 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
> event_notifier_cleanup(notifier);
> }
>
> + if (!msix_enabled(&proxy->pci_dev) && proxy->vdev->guest_notifier_mask) {
> + proxy->vdev->guest_notifier_mask(proxy->vdev, n, !assign);
> + }
> +
> return 0;
> }
>
>
FYI,
actually we have done a similar thing in our private tree to repair vhost
with virtio ccw (which still has to go through qemu to inject an interrupt).
(The host notifiers are fine, but the guest notifiers are faked by reconnecting
the eventfd back to qemu, which boils down to the same problem (no msix also
has qemu irq injection if I understand that correctly)
IIRC, the problem was introduced with:
commit f56a12475ff1b8aa61210d08522c3c8aaf0e2648
Author: Michael S. Tsirkin <mst@redhat.com>
Date: Mon Dec 24 17:37:01 2012 +0200
vhost: backend masking support
Our notifier code looks like
Christian
[...]
+static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+
+ /* Stop using the generic ioeventfd, we are doing eventfd handling
+ * ourselves below */
+ dev->ioeventfd_disabled = assign;
+ if (assign) {
+ virtio_ccw_stop_ioeventfd(dev);
+ }
+ return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
+}
+
+static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
+ bool assign, bool with_irqfd)
+{
+ VirtQueue *vq = virtio_get_queue(dev->vdev, n);
+ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
+
+ if (assign) {
+ int r = event_notifier_init(notifier, 0);
+
+ if (r < 0) {
+ return r;
+ }
+ virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
+ /* We do not support irqfd for classic I/O interrupts, because the
+ * classic interrupts are intermixed with the subchannel status, that
+ * is queried with test subchannel. We want to use vhost, though.
+ * Lets make sure to have vhost running and wire up the irq fd to
+ * land in qemu (and only the irq fd) in this code.
+ */
+ if (dev->vdev->guest_notifier_mask) { <------------- Same code
+ dev->vdev->guest_notifier_mask(dev->vdev, n, false);
+ }
+ /* get lost events and re-inject */
+ if (dev->vdev->guest_notifier_pending &&
+ dev->vdev->guest_notifier_pending(dev->vdev, n)) {
+ event_notifier_set(notifier);
+ }
+ } else {
+ if (dev->vdev->guest_notifier_mask) {
+ dev->vdev->guest_notifier_mask(dev->vdev, n, true);
+ }
+ virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
+ event_notifier_cleanup(notifier);
+ }
+ return 0;
+}
+
+static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
+ bool assigned)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ VirtIODevice *vdev = dev->vdev;
+ int r, n;
+
+ for (n = 0; n < nvqs; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ break;
+ }
+ /* false -> true, as soon as irqfd works */
+ r = virtio_ccw_set_guest_notifier(dev, n, assigned, false);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ return 0;
+
+assign_error:
+ while (--n >= 0) {
+ virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
+ }
+ return r;
+}
[...]
So it might be an alternative to have a look at vhost code,which currently
requires the virtio transport to actively maintain the masking thing .
Christian
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off
2013-04-17 12:03 ` Christian Borntraeger
@ 2013-04-17 13:42 ` Michael S. Tsirkin
2013-04-18 7:55 ` Christian Borntraeger
0 siblings, 1 reply; 9+ messages in thread
From: Michael S. Tsirkin @ 2013-04-17 13:42 UTC (permalink / raw)
To: Christian Borntraeger; +Cc: Cornelia Huck, Alexander Graf, qemu-devel
On Wed, Apr 17, 2013 at 02:03:12PM +0200, Christian Borntraeger wrote:
> On 15/04/13 16:40, Michael S. Tsirkin wrote:
> > In response to a bug report on IRC: this should fix it I think?
> > Need to test properly but out of time for today,
> > compiled only. Hope this helps.
> >
> > Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> >
> > diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> > index 8bba0f3..d0fcc6c 100644
> > --- a/hw/virtio/virtio-pci.c
> > +++ b/hw/virtio/virtio-pci.c
> > @@ -758,6 +758,10 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
> > event_notifier_cleanup(notifier);
> > }
> >
> > + if (!msix_enabled(&proxy->pci_dev) && proxy->vdev->guest_notifier_mask) {
> > + proxy->vdev->guest_notifier_mask(proxy->vdev, n, !assign);
> > + }
> > +
> > return 0;
> > }
> >
> >
>
> FYI,
> actually we have done a similar thing in our private tree to repair vhost
> with virtio ccw (which still has to go through qemu to inject an interrupt).
> (The host notifiers are fine, but the guest notifiers are faked by reconnecting
> the eventfd back to qemu, which boils down to the same problem (no msix also
> has qemu irq injection if I understand that correctly)
>
> IIRC, the problem was introduced with:
>
> commit f56a12475ff1b8aa61210d08522c3c8aaf0e2648
> Author: Michael S. Tsirkin <mst@redhat.com>
> Date: Mon Dec 24 17:37:01 2012 +0200
>
> vhost: backend masking support
>
>
> Our notifier code looks like
>
> Christian
> [...]
> +static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
> +{
> + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
> +
> + /* Stop using the generic ioeventfd, we are doing eventfd handling
> + * ourselves below */
> + dev->ioeventfd_disabled = assign;
> + if (assign) {
> + virtio_ccw_stop_ioeventfd(dev);
> + }
> + return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
> +}
> +
> +static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
> + bool assign, bool with_irqfd)
> +{
> + VirtQueue *vq = virtio_get_queue(dev->vdev, n);
> + EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
> +
> + if (assign) {
> + int r = event_notifier_init(notifier, 0);
> +
> + if (r < 0) {
> + return r;
> + }
> + virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
> + /* We do not support irqfd for classic I/O interrupts, because the
> + * classic interrupts are intermixed with the subchannel status, that
> + * is queried with test subchannel. We want to use vhost, though.
> + * Lets make sure to have vhost running and wire up the irq fd to
> + * land in qemu (and only the irq fd) in this code.
Still, this is not optimal.
Isn't there some way to actually use irqfd to bypass qemu?
Is there some other kind of interrupt virtio can use that
works fine with irqfd?
> + */
> + if (dev->vdev->guest_notifier_mask) { <------------- Same code
> + dev->vdev->guest_notifier_mask(dev->vdev, n, false);
> + }
> + /* get lost events and re-inject */
> + if (dev->vdev->guest_notifier_pending &&
> + dev->vdev->guest_notifier_pending(dev->vdev, n)) {
> + event_notifier_set(notifier);
> + }
> + } else {
> + if (dev->vdev->guest_notifier_mask) {
> + dev->vdev->guest_notifier_mask(dev->vdev, n, true);
> + }
> + virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
> + event_notifier_cleanup(notifier);
> + }
> + return 0;
> +}
> +
> +static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
> + bool assigned)
> +{
> + VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
> + VirtIODevice *vdev = dev->vdev;
> + int r, n;
> +
> + for (n = 0; n < nvqs; n++) {
> + if (!virtio_queue_get_num(vdev, n)) {
> + break;
> + }
> + /* false -> true, as soon as irqfd works */
> + r = virtio_ccw_set_guest_notifier(dev, n, assigned, false);
> + if (r < 0) {
> + goto assign_error;
> + }
> + }
> + return 0;
> +
> +assign_error:
> + while (--n >= 0) {
> + virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
> + }
> + return r;
> +}
>
> [...]
>
>
> So it might be an alternative to have a look at vhost code,which currently
> requires the virtio transport to actively maintain the masking thing .
>
> Christian
I suggest we merge your code as is, then look for
similiarities with PCI to move into virtio core.
--
MST
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off
2013-04-17 13:42 ` Michael S. Tsirkin
@ 2013-04-18 7:55 ` Christian Borntraeger
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 0/3] virtio-ccw: Add notifiers support Cornelia Huck
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: Christian Borntraeger @ 2013-04-18 7:55 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: Cornelia Huck, Alexander Graf, qemu-devel
On 17/04/13 15:42, Michael S. Tsirkin wrote:
[...]
>> +static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
>> + bool assign, bool with_irqfd)
>> +{
>> + VirtQueue *vq = virtio_get_queue(dev->vdev, n);
>> + EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
>> +
>> + if (assign) {
>> + int r = event_notifier_init(notifier, 0);
>> +
>> + if (r < 0) {
>> + return r;
>> + }
>> + virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
>> + /* We do not support irqfd for classic I/O interrupts, because the
>> + * classic interrupts are intermixed with the subchannel status, that
>> + * is queried with test subchannel. We want to use vhost, though.
>> + * Lets make sure to have vhost running and wire up the irq fd to
>> + * land in qemu (and only the irq fd) in this code.
>
> Still, this is not optimal.
Correct. This is just to make vhost work.
We still get a decent performance improvement, though. (iperf gets 2.5x faster)
So it is actually a good idea to allow vhost even if there is no kernel side irq
injection as long as we have somebody listening on the eventfd for this irq.
> Isn't there some way to actually use irqfd to bypass qemu?
We had some thoughs about having irqfd for the I/O interrupts and every idea had
its downside (e.g. putting all the channel I/O code in the kernel, having
a big qemu/kernel shared memory data structure, ...). We are still looking for
some good ideas to also provide kernel I/O interrupt injection.
> Is there some other kind of interrupt virtio can use that
> works fine with irqfd?
Yes, there is a lightweight form of I/O interrupts that is also used for the
real network cards (OSA) which does not require a TSCH we are currently also
investigating this approach.
[...]
>> So it might be an alternative to have a look at vhost code,which currently
>> requires the virtio transport to actively maintain the masking thing .
>>
>> Christian
>
> I suggest we merge your code as is, then look for
> similiarities with PCI to move into virtio core.
Ok. Conny can you refresh the patches so that we can have a look?
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off
2013-04-15 14:40 [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off Michael S. Tsirkin
2013-04-17 12:03 ` Christian Borntraeger
@ 2013-04-18 17:19 ` Alexander Graf
1 sibling, 0 replies; 9+ messages in thread
From: Alexander Graf @ 2013-04-18 17:19 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: qemu-devel
On 15.04.2013, at 16:40, Michael S. Tsirkin wrote:
> In response to a bug report on IRC: this should fix it I think?
> Need to test properly but out of time for today,
> compiled only. Hope this helps.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This does indeed make level interrupts work with vhost. Thanks a lot!
Tested-by: Alexander Graf <agraf@suse.de>
Alex
>
> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
> index 8bba0f3..d0fcc6c 100644
> --- a/hw/virtio/virtio-pci.c
> +++ b/hw/virtio/virtio-pci.c
> @@ -758,6 +758,10 @@ static int virtio_pci_set_guest_notifier(DeviceState *d, int n, bool assign,
> event_notifier_cleanup(notifier);
> }
>
> + if (!msix_enabled(&proxy->pci_dev) && proxy->vdev->guest_notifier_mask) {
> + proxy->vdev->guest_notifier_mask(proxy->vdev, n, !assign);
> + }
> +
> return 0;
> }
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH RFC 0/3] virtio-ccw: Add notifiers support.
2013-04-18 7:55 ` Christian Borntraeger
@ 2013-04-22 9:11 ` Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 1/3] linux-headers: Update with ioeventfd changes Cornelia Huck
` (2 subsequent siblings)
3 siblings, 0 replies; 9+ messages in thread
From: Cornelia Huck @ 2013-04-22 9:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Alexander Graf, Michael S. Tsirkin
So here's my current patchset for adding guest/host notifiers
in virtio-ccw.
The ioeventfd support for s390 in the Linux kernel is not yet
upstream (still queued), so the first patch just adds the relevant
header changes.
Patches can also be found at
git://github.com/cohuck/qemu virtio-ccw-notifiers
Cornelia Huck (3):
linux-headers: Update with ioeventfd changes.
virtio-ccw: Wire up ioeventfd.
virtio-ccw: Wire up guest and host notifies.
hw/s390x/css.c | 2 +-
hw/s390x/css.h | 1 +
hw/s390x/virtio-ccw.c | 203 +++++++++++++++++++++++++++++++++++++++++++++
hw/s390x/virtio-ccw.h | 8 ++
linux-headers/linux/kvm.h | 3 +
target-s390x/cpu.h | 16 ++++
target-s390x/kvm.c | 19 +++++
7 files changed, 251 insertions(+), 1 deletion(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH RFC 1/3] linux-headers: Update with ioeventfd changes.
2013-04-18 7:55 ` Christian Borntraeger
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 0/3] virtio-ccw: Add notifiers support Cornelia Huck
@ 2013-04-22 9:11 ` Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 2/3] virtio-ccw: Wire up ioeventfd Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 3/3] virtio-ccw: Wire up guest and host notifies Cornelia Huck
3 siblings, 0 replies; 9+ messages in thread
From: Cornelia Huck @ 2013-04-22 9:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Alexander Graf, Michael S. Tsirkin
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
| 3 +++
1 file changed, 3 insertions(+)
--git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index caca979..eb02d8a 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -449,12 +449,15 @@ enum {
kvm_ioeventfd_flag_nr_datamatch,
kvm_ioeventfd_flag_nr_pio,
kvm_ioeventfd_flag_nr_deassign,
+ kvm_ioeventfd_flag_nr_virtio_ccw_notify,
kvm_ioeventfd_flag_nr_max,
};
#define KVM_IOEVENTFD_FLAG_DATAMATCH (1 << kvm_ioeventfd_flag_nr_datamatch)
#define KVM_IOEVENTFD_FLAG_PIO (1 << kvm_ioeventfd_flag_nr_pio)
#define KVM_IOEVENTFD_FLAG_DEASSIGN (1 << kvm_ioeventfd_flag_nr_deassign)
+#define KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY \
+ (1 << kvm_ioeventfd_flag_nr_virtio_ccw_notify)
#define KVM_IOEVENTFD_VALID_FLAG_MASK ((1 << kvm_ioeventfd_flag_nr_max) - 1)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH RFC 2/3] virtio-ccw: Wire up ioeventfd.
2013-04-18 7:55 ` Christian Borntraeger
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 0/3] virtio-ccw: Add notifiers support Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 1/3] linux-headers: Update with ioeventfd changes Cornelia Huck
@ 2013-04-22 9:11 ` Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 3/3] virtio-ccw: Wire up guest and host notifies Cornelia Huck
3 siblings, 0 replies; 9+ messages in thread
From: Cornelia Huck @ 2013-04-22 9:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Alexander Graf, Michael S. Tsirkin
On hosts that support ioeventfd, make use of it for host-to-guest
notifications via diagnose 500.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/s390x/css.c | 2 +-
hw/s390x/css.h | 1 +
hw/s390x/virtio-ccw.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/s390x/virtio-ccw.h | 7 +++
target-s390x/cpu.h | 16 +++++++
target-s390x/kvm.c | 19 +++++++++
6 files changed, 157 insertions(+), 1 deletion(-)
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index e526a1c..808404b 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -68,7 +68,7 @@ int css_create_css_image(uint8_t cssid, bool default_image)
return 0;
}
-static uint16_t css_build_subchannel_id(SubchDev *sch)
+uint16_t css_build_subchannel_id(SubchDev *sch)
{
if (channel_subsys->max_cssid > 0) {
return (sch->cssid << 8) | (1 << 3) | (sch->ssid << 1) | 1;
diff --git a/hw/s390x/css.h b/hw/s390x/css.h
index 85ed05d..b536ab5 100644
--- a/hw/s390x/css.h
+++ b/hw/s390x/css.h
@@ -90,6 +90,7 @@ bool css_devno_used(uint8_t cssid, uint8_t ssid, uint16_t devno);
void css_subch_assign(uint8_t cssid, uint8_t ssid, uint16_t schid,
uint16_t devno, SubchDev *sch);
void css_sch_build_virtual_schib(SubchDev *sch, uint8_t chpid, uint8_t type);
+uint16_t css_build_subchannel_id(SubchDev *sch);
void css_reset(void);
void css_reset_sch(SubchDev *sch);
void css_queue_crw(uint8_t rsc, uint8_t erc, int chain, uint16_t rsid);
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e9e7509..7acd39d 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -63,6 +63,84 @@ VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
return vdev;
}
+static int virtio_ccw_set_guest2host_notifier(VirtioCcwDevice *dev, int n,
+ bool assign, bool set_handler)
+{
+ VirtQueue *vq = virtio_get_queue(dev->vdev, n);
+ EventNotifier *notifier = virtio_queue_get_host_notifier(vq);
+ int r = 0;
+ SubchDev *sch = dev->sch;
+ uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
+
+ if (assign) {
+ r = event_notifier_init(notifier, 1);
+ if (r < 0) {
+ error_report("%s: unable to init event notifier: %d", __func__, r);
+ return r;
+ }
+ virtio_queue_set_host_notifier_fd_handler(vq, true, set_handler);
+ s390_assign_subch_ioeventfd(event_notifier_get_fd(notifier), sch_id,
+ n, assign);
+ } else {
+ virtio_queue_set_host_notifier_fd_handler(vq, false, false);
+ s390_assign_subch_ioeventfd(event_notifier_get_fd(notifier), sch_id,
+ n, assign);
+ event_notifier_cleanup(notifier);
+ }
+ return r;
+}
+
+static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
+{
+ int n, r;
+
+ if (!(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) ||
+ dev->ioeventfd_started) {
+ return;
+ }
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(dev->vdev, n)) {
+ continue;
+ }
+ r = virtio_ccw_set_guest2host_notifier(dev, n, true, true);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ dev->ioeventfd_started = true;
+ return;
+
+ assign_error:
+ while (--n >= 0) {
+ if (!virtio_queue_get_num(dev->vdev, n)) {
+ continue;
+ }
+ r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
+ assert(r >= 0);
+ }
+ dev->ioeventfd_started = false;
+ /* Disable ioeventfd for this device. */
+ dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
+ error_report("%s: failed. Fallback to userspace (slower).", __func__);
+}
+
+static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
+{
+ int n, r;
+
+ if (!dev->ioeventfd_started) {
+ return;
+ }
+ for (n = 0; n < VIRTIO_PCI_QUEUE_MAX; n++) {
+ if (!virtio_queue_get_num(dev->vdev, n)) {
+ continue;
+ }
+ r = virtio_ccw_set_guest2host_notifier(dev, n, false, false);
+ assert(r >= 0);
+ }
+ dev->ioeventfd_started = false;
+}
+
VirtualCssBus *virtual_css_bus_init(void)
{
VirtualCssBus *cbus;
@@ -187,6 +265,7 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
}
break;
case CCW_CMD_VDEV_RESET:
+ virtio_ccw_stop_ioeventfd(dev);
virtio_reset(dev->vdev);
ret = 0;
break;
@@ -313,10 +392,16 @@ static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
ret = -EFAULT;
} else {
status = ldub_phys(ccw.cda);
+ if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+ virtio_ccw_stop_ioeventfd(dev);
+ }
virtio_set_status(dev->vdev, status);
if (dev->vdev->status == 0) {
virtio_reset(dev->vdev);
}
+ if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
+ virtio_ccw_start_ioeventfd(dev);
+ }
sch->curr_status.scsw.count = ccw.count - sizeof(status);
ret = 0;
}
@@ -543,6 +628,7 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
{
SubchDev *sch = dev->sch;
+ virtio_ccw_stop_ioeventfd(dev);
if (sch) {
css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
g_free(sch);
@@ -707,6 +793,7 @@ static int virtio_ccw_rng_init(VirtioCcwDevice *dev)
static int virtio_ccw_rng_exit(VirtioCcwDevice *dev)
{
+ virtio_ccw_stop_ioeventfd(dev);
virtio_rng_exit(dev->vdev);
return virtio_ccw_exit(dev);
}
@@ -756,15 +843,28 @@ static void virtio_ccw_reset(DeviceState *d)
{
VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ virtio_ccw_stop_ioeventfd(dev);
virtio_reset(dev->vdev);
css_reset_sch(dev->sch);
}
+static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+
+ if (running) {
+ virtio_ccw_start_ioeventfd(dev);
+ } else {
+ virtio_ccw_stop_ioeventfd(dev);
+ }
+}
+
/**************** Virtio-ccw Bus Device Descriptions *******************/
static const VirtIOBindings virtio_ccw_bindings = {
.notify = virtio_ccw_notify,
.get_features = virtio_ccw_get_features,
+ .vmstate_change = virtio_ccw_vmstate_change,
};
static Property virtio_ccw_net_properties[] = {
@@ -772,6 +872,8 @@ static Property virtio_ccw_net_properties[] = {
DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetCcw, vdev.net_conf),
DEFINE_NIC_PROPERTIES(VirtIONetCcw, vdev.nic_conf),
+ DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+ VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -798,6 +900,8 @@ static Property virtio_ccw_blk_properties[] = {
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_VIRTIO_BLK_FEATURES(VirtioCcwDevice, host_features[0]),
DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkCcw, blk),
+ DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+ VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -824,6 +928,8 @@ static Property virtio_ccw_serial_properties[] = {
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtioSerialCcw, vdev.serial),
DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
+ DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+ VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -849,6 +955,8 @@ static const TypeInfo virtio_ccw_serial = {
static Property virtio_ccw_balloon_properties[] = {
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
+ DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+ VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -875,6 +983,8 @@ static Property virtio_ccw_scsi_properties[] = {
DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOSCSICcw, vdev.conf),
DEFINE_VIRTIO_SCSI_FEATURES(VirtioCcwDevice, host_features[0]),
+ DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+ VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -910,6 +1020,8 @@ static Property virtio_ccw_rng_properties[] = {
DEFINE_VIRTIO_COMMON_FEATURES(VirtioCcwDevice, host_features[0]),
DEFINE_PROP_UINT64("max-bytes", VirtioCcwDevice, rng.max_bytes, INT64_MAX),
DEFINE_PROP_UINT32("period", VirtioCcwDevice, rng.period_ms, 1 << 16),
+ DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags,
+ VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};
@@ -1035,6 +1147,7 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
bus_class->max_dev = 1;
k->notify = virtio_ccw_notify;
k->get_features = virtio_ccw_get_features;
+ k->vmstate_change = virtio_ccw_vmstate_change;
}
static const TypeInfo virtio_ccw_bus_info = {
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 35ab1a5..1a7a860 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -68,6 +68,11 @@ typedef struct VirtIOCCWDeviceClass {
/* Change here if we want to support more feature bits. */
#define VIRTIO_CCW_FEATURE_SIZE 1
+/* Performance improves when virtqueue kick processing is decoupled from the
+ * vcpu thread using ioeventfd for some devices. */
+#define VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT 1
+#define VIRTIO_CCW_FLAG_USE_IOEVENTFD (1 << VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT)
+
struct VirtioCcwDevice {
DeviceState parent_obj;
SubchDev *sch;
@@ -76,6 +81,8 @@ struct VirtioCcwDevice {
uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
VirtIORNGConf rng;
VirtioBusState bus;
+ bool ioeventfd_started;
+ uint32_t flags;
/* Guest provided values: */
hwaddr indicators;
hwaddr indicators2;
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e351005..f64f8f1 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -1068,6 +1068,7 @@ void kvm_s390_io_interrupt(S390CPU *cpu, uint16_t subchannel_id,
uint32_t io_int_word);
void kvm_s390_crw_mchk(S390CPU *cpu);
void kvm_s390_enable_css_support(S390CPU *cpu);
+int kvm_s390_assign_subch_ioeventfd(int fd, uint32_t sch, int vq, bool assign);
#else
static inline void kvm_s390_io_interrupt(S390CPU *cpu,
uint16_t subchannel_id,
@@ -1082,6 +1083,11 @@ static inline void kvm_s390_crw_mchk(S390CPU *cpu)
static inline void kvm_s390_enable_css_support(S390CPU *cpu)
{
}
+static inline int kvm_s390_assign_subch_ioeventfd(int fd, uint32_t sch, int vq,
+ bool assign)
+{
+ return -ENOSYS;
+}
#endif
static inline void s390_io_interrupt(S390CPU *cpu,
@@ -1108,4 +1114,14 @@ static inline void s390_crw_mchk(S390CPU *cpu)
}
}
+static inline int s390_assign_subch_ioeventfd(int fd, uint32_t sch_id, int vq,
+ bool assign)
+{
+ if (kvm_enabled()) {
+ return kvm_s390_assign_subch_ioeventfd(fd, sch_id, vq, assign);
+ } else {
+ return -ENOSYS;
+ }
+}
+
#endif
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 644f484..b7b42fb 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -841,3 +841,22 @@ void kvm_s390_enable_css_support(S390CPU *cpu)
r = kvm_vcpu_ioctl(CPU(cpu), KVM_ENABLE_CAP, &cap);
assert(r == 0);
}
+
+int kvm_s390_assign_subch_ioeventfd(int fd, uint32_t sch, int vq, bool assign)
+{
+ struct kvm_ioeventfd kick = {
+ .flags = KVM_IOEVENTFD_FLAG_VIRTIO_CCW_NOTIFY |
+ KVM_IOEVENTFD_FLAG_DATAMATCH,
+ .fd = fd,
+ .datamatch = vq,
+ .addr = sch,
+ .len = 8,
+ };
+ if (!kvm_check_extension(kvm_state, KVM_CAP_IOEVENTFD)) {
+ return -ENOSYS;
+ }
+ if (!assign) {
+ kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+ }
+ return kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
+}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [Qemu-devel] [PATCH RFC 3/3] virtio-ccw: Wire up guest and host notifies.
2013-04-18 7:55 ` Christian Borntraeger
` (2 preceding siblings ...)
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 2/3] virtio-ccw: Wire up ioeventfd Cornelia Huck
@ 2013-04-22 9:11 ` Cornelia Huck
3 siblings, 0 replies; 9+ messages in thread
From: Cornelia Huck @ 2013-04-22 9:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Christian Borntraeger, Alexander Graf, Michael S. Tsirkin
Guest and host notifiers are needed by vhost. We use ioeventfds for
the guest notifiers, but need to fall back on qemu injecting interrupts
for the host notifiers.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
hw/s390x/virtio-ccw.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++
hw/s390x/virtio-ccw.h | 1 +
2 files changed, 91 insertions(+)
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 7acd39d..89dad0d 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -95,6 +95,7 @@ static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
int n, r;
if (!(dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) ||
+ dev->ioeventfd_disabled ||
dev->ioeventfd_started) {
return;
}
@@ -859,12 +860,98 @@ static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
}
}
+static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+
+ return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
+}
+
+static int virtio_ccw_set_host_notifier(DeviceState *d, int n, bool assign)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+
+ /* Stop using the generic ioeventfd, we are doing eventfd handling
+ * ourselves below */
+ dev->ioeventfd_disabled = assign;
+ if (assign) {
+ virtio_ccw_stop_ioeventfd(dev);
+ }
+ return virtio_ccw_set_guest2host_notifier(dev, n, assign, false);
+}
+
+static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
+ bool assign, bool with_irqfd)
+{
+ VirtQueue *vq = virtio_get_queue(dev->vdev, n);
+ EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
+
+ if (assign) {
+ int r = event_notifier_init(notifier, 0);
+
+ if (r < 0) {
+ return r;
+ }
+ virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
+ /* We do not support irqfd for classic I/O interrupts, because the
+ * classic interrupts are intermixed with the subchannel status, that
+ * is queried with test subchannel. We want to use vhost, though.
+ * Lets make sure to have vhost running and wire up the irq fd to
+ * land in qemu (and only the irq fd) in this code.
+ */
+ if (dev->vdev->guest_notifier_mask) {
+ dev->vdev->guest_notifier_mask(dev->vdev, n, false);
+ }
+ /* get lost events and re-inject */
+ if (dev->vdev->guest_notifier_pending &&
+ dev->vdev->guest_notifier_pending(dev->vdev, n)) {
+ event_notifier_set(notifier);
+ }
+ } else {
+ if (dev->vdev->guest_notifier_mask) {
+ dev->vdev->guest_notifier_mask(dev->vdev, n, true);
+ }
+ virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
+ event_notifier_cleanup(notifier);
+ }
+ return 0;
+}
+
+static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
+ bool assigned)
+{
+ VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
+ VirtIODevice *vdev = dev->vdev;
+ int r, n;
+
+ for (n = 0; n < nvqs; n++) {
+ if (!virtio_queue_get_num(vdev, n)) {
+ break;
+ }
+ /* false -> true, as soon as irqfd works */
+ r = virtio_ccw_set_guest_notifier(dev, n, assigned, false);
+ if (r < 0) {
+ goto assign_error;
+ }
+ }
+ return 0;
+
+assign_error:
+ while (--n >= 0) {
+ virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
+ }
+ return r;
+}
+
/**************** Virtio-ccw Bus Device Descriptions *******************/
static const VirtIOBindings virtio_ccw_bindings = {
.notify = virtio_ccw_notify,
.get_features = virtio_ccw_get_features,
.vmstate_change = virtio_ccw_vmstate_change,
+ .query_guest_notifiers = virtio_ccw_query_guest_notifiers,
+ .set_host_notifier = virtio_ccw_set_host_notifier,
+ .set_guest_notifiers = virtio_ccw_set_guest_notifiers,
};
static Property virtio_ccw_net_properties[] = {
@@ -1148,6 +1235,9 @@ static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
k->notify = virtio_ccw_notify;
k->get_features = virtio_ccw_get_features;
k->vmstate_change = virtio_ccw_vmstate_change;
+ k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
+ k->set_host_notifier = virtio_ccw_set_host_notifier;
+ k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
}
static const TypeInfo virtio_ccw_bus_info = {
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 1a7a860..4ae01cb 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -82,6 +82,7 @@ struct VirtioCcwDevice {
VirtIORNGConf rng;
VirtioBusState bus;
bool ioeventfd_started;
+ bool ioeventfd_disabled;
uint32_t flags;
/* Guest provided values: */
hwaddr indicators;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 9+ messages in thread
end of thread, other threads:[~2013-04-22 9:12 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-15 14:40 [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off Michael S. Tsirkin
2013-04-17 12:03 ` Christian Borntraeger
2013-04-17 13:42 ` Michael S. Tsirkin
2013-04-18 7:55 ` Christian Borntraeger
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 0/3] virtio-ccw: Add notifiers support Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 1/3] linux-headers: Update with ioeventfd changes Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 2/3] virtio-ccw: Wire up ioeventfd Cornelia Huck
2013-04-22 9:11 ` [Qemu-devel] [PATCH RFC 3/3] virtio-ccw: Wire up guest and host notifies Cornelia Huck
2013-04-18 17:19 ` [Qemu-devel] [PATCH RFC] vhost: fix vhost force with msix=off Alexander Graf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).