Skip to contentSkip to conversation

qemu: ioeventfd for virtio-ccw.

RFC PATCH Superseded Cornelia Huck 1 participant 3 messages Feb 21, 2013

Subsystems (2)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover qemu: ioeventfd for virtio-ccw.

This patch series makes use of the s390 ioeventfd implementation to speed up virtio-ccw a bit.

We hook up virtio notifications via diagnose 500 as ioeventfds, specifying a subchannel id and virtqueue index combination.

ioeventfds are used by default for all virtio devices; there's an ioeventfd property that can be used to turn ioeventfd usage off for a device (similar to virtio-pci).

A simple dd on a virtio-blk device
dd if=/dev/vda of=/dev/null iflag=direct bs=4k count=10000
is now twice as fast :)

(Patches are against master.)

Cornelia Huck (2):
linux-headers: Update with ioeventfd changes.
virtio-ccw: Wire up ioeventfd.

 hw/s390x/css.c            |   2 +-
 hw/s390x/css.h            |   1 +
 hw/s390x/virtio-ccw.c     | 114 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/s390x/virtio-ccw.h     |   7 +++
 linux-headers/linux/kvm.h |   4 +-
 target-s390x/cpu.h        |  16 +++++++
 target-s390x/kvm.c        |  27 +++++++++++
 7 files changed, 169 insertions(+), 2 deletions(-)
Signature · 1 line
1.7.12.4
#1 lore raw

RFC PATCH 1/2 linux-headers: Update with ioeventfd changes.

---
 linux-headers/linux/kvm.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
linux-headers/linux/kvm.h +3 -1
index 5af9357..a7f92a0 100644
@@ -448,12 +448,14 @@ enum {
 	kvm_ioeventfd_flag_nr_datamatch,
 	kvm_ioeventfd_flag_nr_pio,
 	kvm_ioeventfd_flag_nr_deassign,
+	kvm_ioeventfd_flag_nr_arch,
 	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_ARCH      (1 << kvm_ioeventfd_flag_nr_arch)
 
 #define KVM_IOEVENTFD_VALID_FLAG_MASK  ((1 << kvm_ioeventfd_flag_nr_max) - 1)
 
@@ -463,7 +465,7 @@ struct kvm_ioeventfd {
 	__u32 len;         /* 1, 2, 4, or 8 bytes    */
 	__s32 fd;
 	__u32 flags;
-	__u8  pad[36];
+	__u8  data[36];    /* for architecture-specific data */
 };
 
 /* for KVM_ENABLE_CAP */
Signature · 1 line
1.7.12.4
#2 lore raw

RFC PATCH 2/2 virtio-ccw: Wire up ioeventfd.

In reply to Cornelia Huck

On hosts that support ioeventfd, make use of it for host-to-guest notifications via diagnose 500.

---
 hw/s390x/css.c        |   2 +-
 hw/s390x/css.h        |   1 +
 hw/s390x/virtio-ccw.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/s390x/virtio-ccw.h |   7 ++++
 target-s390x/cpu.h    |  16 +++++++
 target-s390x/kvm.c    |  27 ++++++++++++
 6 files changed, 166 insertions(+), 1 deletion(-)
hw/s390x/css.c +1 -1
index 85f6f22..82e6746 100644
@@ -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;
hw/s390x/css.h +1 -0
index 85ed05d..b536ab5 100644
@@ -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);
hw/s390x/virtio-ccw.c +114 -0

217 lines not on this page · raw message

hw/s390x/virtio-ccw.h +7 -0
index 48474b3..db83e0f 100644
@@ -66,6 +66,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;
@@ -78,6 +83,8 @@ struct VirtioCcwDevice {
     virtio_net_conf net;
     VirtIOSCSIConf scsi;
     VirtioBusState bus;
+    bool ioeventfd_started;
+    uint32_t flags;
     /* Guest provided values: */
     hwaddr indicators;
     hwaddr indicators2;
target-s390x/cpu.h +16 -0
index e450db7..3e891d4 100644
@@ -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
target-s390x/kvm.c +27 -0
index 3929771..e648390 100644
@@ -847,3 +847,30 @@ void kvm_s390_enable_css_support(S390CPU *cpu)
     r = kvm_vcpu_ioctl(CPU(cpu), KVM_ENABLE_CAP, &cap);
     assert(r == 0);
 }
+
+#define KVM_S390_IOEVENTFD_VIRTIO_CCW_NOTIFY 1
+int kvm_s390_assign_subch_ioeventfd(int fd, uint32_t sch, int vq, bool assign)
+{
+    struct kvm_ioeventfd kick = {
+        .flags = KVM_IOEVENTFD_FLAG_ARCH,
+        .fd = fd,
+    };
+    struct {
+        uint8_t type;
+        uint64_t vq;
+        uint32_t sch;
+    } QEMU_PACKED payload;
+
+    if (!kvm_check_extension(kvm_state, KVM_CAP_IOEVENTFD)) {
+        return -ENOSYS;
+    }
+    payload.type = KVM_S390_IOEVENTFD_VIRTIO_CCW_NOTIFY;
+    payload.vq = vq;
+    payload.sch = sch;
+    memcpy(kick.data, &payload, sizeof(payload));
+
+    if (!assign) {
+        kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+    }
+    return kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
+}
Signature · 1 line
1.7.12.4