All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kurz <gkurz@linux.vnet.ibm.com>
To: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: virtualization@lists.linux-foundation.org, qemu-devel@nongnu.org,
	kvm@vger.kernel.org, rusty@rustcorp.com.au,
	thuth@linux.vnet.ibm.com
Subject: Re: [Qemu-devel] [PATCH RFC 07/11] dataplane: allow virtio-1 devices
Date: Tue, 28 Oct 2014 16:22:54 +0100	[thread overview]
Message-ID: <20141028162254.2a4f2cf4@bahia.local> (raw)
In-Reply-To: <1412692807-12398-8-git-send-email-cornelia.huck@de.ibm.com>

On Tue,  7 Oct 2014 16:40:03 +0200
Cornelia Huck <cornelia.huck@de.ibm.com> wrote:

> Handle endianness conversion for virtio-1 virtqueues correctly.
> 
> Note that dataplane now needs to be built per-target.
> 

It also affects hw/virtio/virtio-pci.c:

In file included from include/hw/virtio/dataplane/vring.h:23:0,
                 from include/hw/virtio/virtio-scsi.h:21,
                 from hw/virtio/virtio-pci.c:24:
include/hw/virtio/virtio-access.h: In function ‘virtio_access_is_big_endian’:
include/hw/virtio/virtio-access.h:28:15: error: attempt to use poisoned "TARGET_WORDS_BIGENDIAN"
 #elif defined(TARGET_WORDS_BIGENDIAN)
               ^

FWIW when I added endian ambivalent support to virtio, I remember *some people*
getting angry at the idea of turning common code into per-target... :)

See comment below.

> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  hw/block/dataplane/virtio-blk.c     |    3 +-
>  hw/scsi/virtio-scsi-dataplane.c     |    2 +-
>  hw/virtio/Makefile.objs             |    2 +-
>  hw/virtio/dataplane/Makefile.objs   |    2 +-
>  hw/virtio/dataplane/vring.c         |   85 +++++++++++++++++++----------------
>  include/hw/virtio/dataplane/vring.h |   64 ++++++++++++++++++++++++--
>  6 files changed, 113 insertions(+), 45 deletions(-)
> 
> diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
> index 5458f9d..eb45a3d 100644
> --- a/hw/block/dataplane/virtio-blk.c
> +++ b/hw/block/dataplane/virtio-blk.c
> @@ -16,6 +16,7 @@
>  #include "qemu/iov.h"
>  #include "qemu/thread.h"
>  #include "qemu/error-report.h"
> +#include "hw/virtio/virtio-access.h"
>  #include "hw/virtio/dataplane/vring.h"
>  #include "block/block.h"
>  #include "hw/virtio/virtio-blk.h"
> @@ -75,7 +76,7 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
>      VirtIOBlockDataPlane *s = req->dev->dataplane;
>      stb_p(&req->in->status, status);
> 
> -    vring_push(&req->dev->dataplane->vring, &req->elem,
> +    vring_push(s->vdev, &req->dev->dataplane->vring, &req->elem,
>                 req->qiov.size + sizeof(*req->in));
> 
>      /* Suppress notification to guest by BH and its scheduled
> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
> index b778e05..3e2b706 100644
> --- a/hw/scsi/virtio-scsi-dataplane.c
> +++ b/hw/scsi/virtio-scsi-dataplane.c
> @@ -81,7 +81,7 @@ VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s,
> 
>  void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
>  {
> -    vring_push(&req->vring->vring, &req->elem,
> +    vring_push((VirtIODevice *)req->dev, &req->vring->vring, &req->elem,
>                 req->qsgl.size + req->resp_iov.size);
>      event_notifier_set(&req->vring->guest_notifier);
>  }
> diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
> index d21c397..19b224a 100644
> --- a/hw/virtio/Makefile.objs
> +++ b/hw/virtio/Makefile.objs
> @@ -2,7 +2,7 @@ common-obj-y += virtio-rng.o
>  common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
>  common-obj-y += virtio-bus.o
>  common-obj-y += virtio-mmio.o
> -common-obj-$(CONFIG_VIRTIO) += dataplane/
> +obj-$(CONFIG_VIRTIO) += dataplane/
> 
>  obj-y += virtio.o virtio-balloon.o 
>  obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
> diff --git a/hw/virtio/dataplane/Makefile.objs b/hw/virtio/dataplane/Makefile.objs
> index 9a8cfc0..753a9ca 100644
> --- a/hw/virtio/dataplane/Makefile.objs
> +++ b/hw/virtio/dataplane/Makefile.objs
> @@ -1 +1 @@
> -common-obj-y += vring.o
> +obj-y += vring.o
> diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
> index b84957f..4624521 100644
> --- a/hw/virtio/dataplane/vring.c
> +++ b/hw/virtio/dataplane/vring.c
> @@ -18,6 +18,7 @@
>  #include "hw/hw.h"
>  #include "exec/memory.h"
>  #include "exec/address-spaces.h"
> +#include "hw/virtio/virtio-access.h"
>  #include "hw/virtio/dataplane/vring.h"
>  #include "qemu/error-report.h"
> 
> @@ -83,7 +84,7 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
>      vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096);
> 
>      vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n);
> -    vring->last_used_idx = vring->vr.used->idx;
> +    vring->last_used_idx = vring_get_used_idx(vdev, vring);
>      vring->signalled_used = 0;
>      vring->signalled_used_valid = false;
> 
> @@ -104,7 +105,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
>  void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
>  {
>      if (!(vdev->guest_features[0] & (1 << VIRTIO_RING_F_EVENT_IDX))) {
> -        vring->vr.used->flags |= VRING_USED_F_NO_NOTIFY;
> +        vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
>      }
>  }
> 
> @@ -117,10 +118,10 @@ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring)
>      if (vdev->guest_features[0] & (1 << VIRTIO_RING_F_EVENT_IDX)) {
>          vring_avail_event(&vring->vr) = vring->vr.avail->idx;
>      } else {
> -        vring->vr.used->flags &= ~VRING_USED_F_NO_NOTIFY;
> +        vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
>      }
>      smp_mb(); /* ensure update is seen before reading avail_idx */
> -    return !vring_more_avail(vring);
> +    return !vring_more_avail(vdev, vring);
>  }
> 
>  /* This is stolen from linux/drivers/vhost/vhost.c:vhost_notify() */
> @@ -134,12 +135,13 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring)
>      smp_mb();
> 
>      if ((vdev->guest_features[0] & VIRTIO_F_NOTIFY_ON_EMPTY) &&
> -        unlikely(vring->vr.avail->idx == vring->last_avail_idx)) {
> +        unlikely(!vring_more_avail(vdev, vring))) {
>          return true;
>      }
> 
>      if (!(vdev->guest_features[0] & VIRTIO_RING_F_EVENT_IDX)) {
> -        return !(vring->vr.avail->flags & VRING_AVAIL_F_NO_INTERRUPT);
> +        return !(vring_get_avail_flags(vdev, vring) &
> +                 VRING_AVAIL_F_NO_INTERRUPT);
>      }
>      old = vring->signalled_used;
>      v = vring->signalled_used_valid;
> @@ -154,15 +156,18 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring)
>  }
> 
> 
> -static int get_desc(Vring *vring, VirtQueueElement *elem,
> +static int get_desc(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem,
>                      struct vring_desc *desc)
>  {
>      unsigned *num;
>      struct iovec *iov;
>      hwaddr *addr;
>      MemoryRegion *mr;
> +    int is_write = virtio_tswap16(vdev, desc->flags) & VRING_DESC_F_WRITE;
> +    uint32_t len = virtio_tswap32(vdev, desc->len);
> +    uint64_t desc_addr = virtio_tswap64(vdev, desc->addr);
> 
> -    if (desc->flags & VRING_DESC_F_WRITE) {
> +    if (is_write) {
>          num = &elem->in_num;
>          iov = &elem->in_sg[*num];
>          addr = &elem->in_addr[*num];
> @@ -186,44 +191,45 @@ static int get_desc(Vring *vring, VirtQueueElement *elem,
>      }
> 
>      /* TODO handle non-contiguous memory across region boundaries */
> -    iov->iov_base = vring_map(&mr, desc->addr, desc->len,
> -                              desc->flags & VRING_DESC_F_WRITE);
> +    iov->iov_base = vring_map(&mr, desc_addr, len, is_write);
>      if (!iov->iov_base) {
>          error_report("Failed to map descriptor addr %#" PRIx64 " len %u",
> -                     (uint64_t)desc->addr, desc->len);
> +                     (uint64_t)desc_addr, len);
>          return -EFAULT;
>      }
> 
>      /* The MemoryRegion is looked up again and unref'ed later, leave the
>       * ref in place.  */
> -    iov->iov_len = desc->len;
> -    *addr = desc->addr;
> +    iov->iov_len = len;
> +    *addr = desc_addr;
>      *num += 1;
>      return 0;
>  }
> 
>  /* This is stolen from linux/drivers/vhost/vhost.c. */
> -static int get_indirect(Vring *vring, VirtQueueElement *elem,
> -                        struct vring_desc *indirect)
> +static int get_indirect(VirtIODevice *vdev, Vring *vring,
> +                        VirtQueueElement *elem, struct vring_desc *indirect)
>  {
>      struct vring_desc desc;
>      unsigned int i = 0, count, found = 0;
>      int ret;
> +    uint32_t len = virtio_tswap32(vdev, indirect->len);
> +    uint64_t addr = virtio_tswap64(vdev, indirect->addr);
> 
>      /* Sanity check */
> -    if (unlikely(indirect->len % sizeof(desc))) {
> +    if (unlikely(len % sizeof(desc))) {
>          error_report("Invalid length in indirect descriptor: "
>                       "len %#x not multiple of %#zx",
> -                     indirect->len, sizeof(desc));
> +                     len, sizeof(desc));
>          vring->broken = true;
>          return -EFAULT;
>      }
> 
> -    count = indirect->len / sizeof(desc);
> +    count = len / sizeof(desc);
>      /* Buffers are chained via a 16 bit next field, so
>       * we can have at most 2^16 of these. */
>      if (unlikely(count > USHRT_MAX + 1)) {
> -        error_report("Indirect buffer length too big: %d", indirect->len);
> +        error_report("Indirect buffer length too big: %d", len);
>          vring->broken = true;
>          return -EFAULT;
>      }
> @@ -234,12 +240,12 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem,
> 
>          /* Translate indirect descriptor */
>          desc_ptr = vring_map(&mr,
> -                             indirect->addr + found * sizeof(desc),
> +                             addr + found * sizeof(desc),
>                               sizeof(desc), false);
>          if (!desc_ptr) {
>              error_report("Failed to map indirect descriptor "
>                           "addr %#" PRIx64 " len %zu",
> -                         (uint64_t)indirect->addr + found * sizeof(desc),
> +                         (uint64_t)addr + found * sizeof(desc),
>                           sizeof(desc));
>              vring->broken = true;
>              return -EFAULT;
> @@ -257,19 +263,20 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem,
>              return -EFAULT;
>          }
> 
> -        if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) {
> +        if (unlikely(virtio_tswap16(vdev, desc.flags)
> +                     & VRING_DESC_F_INDIRECT)) {
>              error_report("Nested indirect descriptor");
>              vring->broken = true;
>              return -EFAULT;
>          }
> 
> -        ret = get_desc(vring, elem, &desc);
> +        ret = get_desc(vdev, vring, elem, &desc);
>          if (ret < 0) {
>              vring->broken |= (ret == -EFAULT);
>              return ret;
>          }
> -        i = desc.next;
> -    } while (desc.flags & VRING_DESC_F_NEXT);
> +        i = virtio_tswap16(vdev, desc.next);
> +    } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT);
>      return 0;
>  }
> 
> @@ -320,7 +327,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
> 
>      /* Check it isn't doing very strange things with descriptor numbers. */
>      last_avail_idx = vring->last_avail_idx;
> -    avail_idx = vring->vr.avail->idx;
> +    avail_idx = vring_get_avail_idx(vdev, vring);
>      barrier(); /* load indices now and not again later */
> 
>      if (unlikely((uint16_t)(avail_idx - last_avail_idx) > num)) {
> @@ -341,7 +348,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
> 
>      /* Grab the next descriptor number they're advertising, and increment
>       * the index we've seen. */
> -    head = vring->vr.avail->ring[last_avail_idx % num];
> +    head = vring_get_avail_ring(vdev, vring, last_avail_idx % num);
> 
>      elem->index = head;
> 
> @@ -374,21 +381,21 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
>          /* Ensure descriptor is loaded before accessing fields */
>          barrier();
> 
> -        if (desc.flags & VRING_DESC_F_INDIRECT) {
> -            ret = get_indirect(vring, elem, &desc);
> +        if (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_INDIRECT) {
> +            ret = get_indirect(vdev, vring, elem, &desc);
>              if (ret < 0) {
>                  goto out;
>              }
>              continue;
>          }
> 
> -        ret = get_desc(vring, elem, &desc);
> +        ret = get_desc(vdev, vring, elem, &desc);
>          if (ret < 0) {
>              goto out;
>          }
> 
> -        i = desc.next;
> -    } while (desc.flags & VRING_DESC_F_NEXT);
> +        i = virtio_tswap16(vdev, desc.next);
> +    } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT);
> 
>      /* On success, increment avail index. */
>      vring->last_avail_idx++;
> @@ -407,9 +414,9 @@ out:
>   *
>   * Stolen from linux/drivers/vhost/vhost.c.
>   */
> -void vring_push(Vring *vring, VirtQueueElement *elem, int len)
> +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem,
> +                int len)
>  {
> -    struct vring_used_elem *used;
>      unsigned int head = elem->index;
>      uint16_t new;
> 
> @@ -422,14 +429,16 @@ void vring_push(Vring *vring, VirtQueueElement *elem, int len)
> 
>      /* The virtqueue contains a ring of used buffers.  Get a pointer to the
>       * next entry in that used ring. */
> -    used = &vring->vr.used->ring[vring->last_used_idx % vring->vr.num];
> -    used->id = head;
> -    used->len = len;
> +    vring_set_used_ring_id(vdev, vring, vring->last_used_idx % vring->vr.num,
> +                           head);
> +    vring_set_used_ring_len(vdev, vring, vring->last_used_idx % vring->vr.num,
> +                            len);
> 
>      /* Make sure buffer is written before we update index. */
>      smp_wmb();
> 
> -    new = vring->vr.used->idx = ++vring->last_used_idx;
> +    new = ++vring->last_used_idx;
> +    vring_set_used_idx(vdev, vring, new);
>      if (unlikely((int16_t)(new - vring->signalled_used) < (uint16_t)1)) {
>          vring->signalled_used_valid = false;
>      }
> diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
> index d3e086a..fde15f3 100644
> --- a/ 
> +++ b/include/hw/virtio/dataplane/vring.h
> @@ -20,6 +20,7 @@
>  #include "qemu-common.h"
>  #include "hw/virtio/virtio_ring.h"
>  #include "hw/virtio/virtio.h"
> +#include "hw/virtio/virtio-access.h"
> 

Since the following commit:

commit 244e2898b7a7735b3da114c120abe206af56a167
Author: Fam Zheng <famz@redhat.com>
Date:   Wed Sep 24 15:21:41 2014 +0800

    virtio-scsi: Add VirtIOSCSIVring in VirtIOSCSIReq

The include/hw/virtio/dataplane/vring.h header is indirectly included
by hw/virtio/virtio-pci.c. Why don't you move all this target dependent
helpers to another header ?

Cheers.

--
Greg

>  typedef struct {
>      MemoryRegion *mr;               /* memory region containing the vring */
> @@ -31,15 +32,71 @@ typedef struct {
>      bool broken;                    /* was there a fatal error? */
>  } Vring;
> 
> +static inline uint16_t vring_get_used_idx(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.used->idx);
> +}
> +
> +static inline void vring_set_used_idx(VirtIODevice *vdev, Vring *vring,
> +                                      uint16_t idx)
> +{
> +    vring->vr.used->idx = virtio_tswap16(vdev, idx);
> +}
> +
> +static inline uint16_t vring_get_avail_idx(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.avail->idx);
> +}
> +
> +static inline uint16_t vring_get_avail_ring(VirtIODevice *vdev, Vring *vring,
> +                                            int i)
> +{
> +    return virtio_tswap16(vdev, vring->vr.avail->ring[i]);
> +}
> +
> +static inline void vring_set_used_ring_id(VirtIODevice *vdev, Vring *vring,
> +                                          int i, uint32_t id)
> +{
> +    vring->vr.used->ring[i].id = virtio_tswap32(vdev, id);
> +}
> +
> +static inline void vring_set_used_ring_len(VirtIODevice *vdev, Vring *vring,
> +                                          int i, uint32_t len)
> +{
> +    vring->vr.used->ring[i].len = virtio_tswap32(vdev, len);
> +}
> +
> +static inline uint16_t vring_get_used_flags(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.used->flags);
> +}
> +
> +static inline uint16_t vring_get_avail_flags(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.avail->flags);
> +}
> +
> +static inline void vring_set_used_flags(VirtIODevice *vdev, Vring *vring,
> +                                        uint16_t flags)
> +{
> +    vring->vr.used->flags |= virtio_tswap16(vdev, flags);
> +}
> +
> +static inline void vring_clear_used_flags(VirtIODevice *vdev, Vring *vring,
> +                                          uint16_t flags)
> +{
> +    vring->vr.used->flags &= virtio_tswap16(vdev, ~flags);
> +}
> +
>  static inline unsigned int vring_get_num(Vring *vring)
>  {
>      return vring->vr.num;
>  }
> 
>  /* Are there more descriptors available? */
> -static inline bool vring_more_avail(Vring *vring)
> +static inline bool vring_more_avail(VirtIODevice *vdev, Vring *vring)
>  {
> -    return vring->vr.avail->idx != vring->last_avail_idx;
> +    return vring_get_avail_idx(vdev, vring) != vring->last_avail_idx;
>  }
> 
>  /* Fail future vring_pop() and vring_push() calls until reset */
> @@ -54,6 +111,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
>  bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
>  bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
>  int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem);
> -void vring_push(Vring *vring, VirtQueueElement *elem, int len);
> +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem,
> +                int len);
> 
>  #endif /* VRING_H */


WARNING: multiple messages have this Message-ID (diff)
From: Greg Kurz <gkurz@linux.vnet.ibm.com>
To: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: thuth@linux.vnet.ibm.com, rusty@rustcorp.com.au,
	qemu-devel@nongnu.org, kvm@vger.kernel.org,
	virtualization@lists.linux-foundation.org
Subject: Re: [Qemu-devel] [PATCH RFC 07/11] dataplane: allow virtio-1 devices
Date: Tue, 28 Oct 2014 16:22:54 +0100	[thread overview]
Message-ID: <20141028162254.2a4f2cf4@bahia.local> (raw)
In-Reply-To: <1412692807-12398-8-git-send-email-cornelia.huck@de.ibm.com>

On Tue,  7 Oct 2014 16:40:03 +0200
Cornelia Huck <cornelia.huck@de.ibm.com> wrote:

> Handle endianness conversion for virtio-1 virtqueues correctly.
> 
> Note that dataplane now needs to be built per-target.
> 

It also affects hw/virtio/virtio-pci.c:

In file included from include/hw/virtio/dataplane/vring.h:23:0,
                 from include/hw/virtio/virtio-scsi.h:21,
                 from hw/virtio/virtio-pci.c:24:
include/hw/virtio/virtio-access.h: In function ‘virtio_access_is_big_endian’:
include/hw/virtio/virtio-access.h:28:15: error: attempt to use poisoned "TARGET_WORDS_BIGENDIAN"
 #elif defined(TARGET_WORDS_BIGENDIAN)
               ^

FWIW when I added endian ambivalent support to virtio, I remember *some people*
getting angry at the idea of turning common code into per-target... :)

See comment below.

> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
> ---
>  hw/block/dataplane/virtio-blk.c     |    3 +-
>  hw/scsi/virtio-scsi-dataplane.c     |    2 +-
>  hw/virtio/Makefile.objs             |    2 +-
>  hw/virtio/dataplane/Makefile.objs   |    2 +-
>  hw/virtio/dataplane/vring.c         |   85 +++++++++++++++++++----------------
>  include/hw/virtio/dataplane/vring.h |   64 ++++++++++++++++++++++++--
>  6 files changed, 113 insertions(+), 45 deletions(-)
> 
> diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
> index 5458f9d..eb45a3d 100644
> --- a/hw/block/dataplane/virtio-blk.c
> +++ b/hw/block/dataplane/virtio-blk.c
> @@ -16,6 +16,7 @@
>  #include "qemu/iov.h"
>  #include "qemu/thread.h"
>  #include "qemu/error-report.h"
> +#include "hw/virtio/virtio-access.h"
>  #include "hw/virtio/dataplane/vring.h"
>  #include "block/block.h"
>  #include "hw/virtio/virtio-blk.h"
> @@ -75,7 +76,7 @@ static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
>      VirtIOBlockDataPlane *s = req->dev->dataplane;
>      stb_p(&req->in->status, status);
> 
> -    vring_push(&req->dev->dataplane->vring, &req->elem,
> +    vring_push(s->vdev, &req->dev->dataplane->vring, &req->elem,
>                 req->qiov.size + sizeof(*req->in));
> 
>      /* Suppress notification to guest by BH and its scheduled
> diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c
> index b778e05..3e2b706 100644
> --- a/hw/scsi/virtio-scsi-dataplane.c
> +++ b/hw/scsi/virtio-scsi-dataplane.c
> @@ -81,7 +81,7 @@ VirtIOSCSIReq *virtio_scsi_pop_req_vring(VirtIOSCSI *s,
> 
>  void virtio_scsi_vring_push_notify(VirtIOSCSIReq *req)
>  {
> -    vring_push(&req->vring->vring, &req->elem,
> +    vring_push((VirtIODevice *)req->dev, &req->vring->vring, &req->elem,
>                 req->qsgl.size + req->resp_iov.size);
>      event_notifier_set(&req->vring->guest_notifier);
>  }
> diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
> index d21c397..19b224a 100644
> --- a/hw/virtio/Makefile.objs
> +++ b/hw/virtio/Makefile.objs
> @@ -2,7 +2,7 @@ common-obj-y += virtio-rng.o
>  common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
>  common-obj-y += virtio-bus.o
>  common-obj-y += virtio-mmio.o
> -common-obj-$(CONFIG_VIRTIO) += dataplane/
> +obj-$(CONFIG_VIRTIO) += dataplane/
> 
>  obj-y += virtio.o virtio-balloon.o 
>  obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
> diff --git a/hw/virtio/dataplane/Makefile.objs b/hw/virtio/dataplane/Makefile.objs
> index 9a8cfc0..753a9ca 100644
> --- a/hw/virtio/dataplane/Makefile.objs
> +++ b/hw/virtio/dataplane/Makefile.objs
> @@ -1 +1 @@
> -common-obj-y += vring.o
> +obj-y += vring.o
> diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
> index b84957f..4624521 100644
> --- a/hw/virtio/dataplane/vring.c
> +++ b/hw/virtio/dataplane/vring.c
> @@ -18,6 +18,7 @@
>  #include "hw/hw.h"
>  #include "exec/memory.h"
>  #include "exec/address-spaces.h"
> +#include "hw/virtio/virtio-access.h"
>  #include "hw/virtio/dataplane/vring.h"
>  #include "qemu/error-report.h"
> 
> @@ -83,7 +84,7 @@ bool vring_setup(Vring *vring, VirtIODevice *vdev, int n)
>      vring_init(&vring->vr, virtio_queue_get_num(vdev, n), vring_ptr, 4096);
> 
>      vring->last_avail_idx = virtio_queue_get_last_avail_idx(vdev, n);
> -    vring->last_used_idx = vring->vr.used->idx;
> +    vring->last_used_idx = vring_get_used_idx(vdev, vring);
>      vring->signalled_used = 0;
>      vring->signalled_used_valid = false;
> 
> @@ -104,7 +105,7 @@ void vring_teardown(Vring *vring, VirtIODevice *vdev, int n)
>  void vring_disable_notification(VirtIODevice *vdev, Vring *vring)
>  {
>      if (!(vdev->guest_features[0] & (1 << VIRTIO_RING_F_EVENT_IDX))) {
> -        vring->vr.used->flags |= VRING_USED_F_NO_NOTIFY;
> +        vring_set_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
>      }
>  }
> 
> @@ -117,10 +118,10 @@ bool vring_enable_notification(VirtIODevice *vdev, Vring *vring)
>      if (vdev->guest_features[0] & (1 << VIRTIO_RING_F_EVENT_IDX)) {
>          vring_avail_event(&vring->vr) = vring->vr.avail->idx;
>      } else {
> -        vring->vr.used->flags &= ~VRING_USED_F_NO_NOTIFY;
> +        vring_clear_used_flags(vdev, vring, VRING_USED_F_NO_NOTIFY);
>      }
>      smp_mb(); /* ensure update is seen before reading avail_idx */
> -    return !vring_more_avail(vring);
> +    return !vring_more_avail(vdev, vring);
>  }
> 
>  /* This is stolen from linux/drivers/vhost/vhost.c:vhost_notify() */
> @@ -134,12 +135,13 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring)
>      smp_mb();
> 
>      if ((vdev->guest_features[0] & VIRTIO_F_NOTIFY_ON_EMPTY) &&
> -        unlikely(vring->vr.avail->idx == vring->last_avail_idx)) {
> +        unlikely(!vring_more_avail(vdev, vring))) {
>          return true;
>      }
> 
>      if (!(vdev->guest_features[0] & VIRTIO_RING_F_EVENT_IDX)) {
> -        return !(vring->vr.avail->flags & VRING_AVAIL_F_NO_INTERRUPT);
> +        return !(vring_get_avail_flags(vdev, vring) &
> +                 VRING_AVAIL_F_NO_INTERRUPT);
>      }
>      old = vring->signalled_used;
>      v = vring->signalled_used_valid;
> @@ -154,15 +156,18 @@ bool vring_should_notify(VirtIODevice *vdev, Vring *vring)
>  }
> 
> 
> -static int get_desc(Vring *vring, VirtQueueElement *elem,
> +static int get_desc(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem,
>                      struct vring_desc *desc)
>  {
>      unsigned *num;
>      struct iovec *iov;
>      hwaddr *addr;
>      MemoryRegion *mr;
> +    int is_write = virtio_tswap16(vdev, desc->flags) & VRING_DESC_F_WRITE;
> +    uint32_t len = virtio_tswap32(vdev, desc->len);
> +    uint64_t desc_addr = virtio_tswap64(vdev, desc->addr);
> 
> -    if (desc->flags & VRING_DESC_F_WRITE) {
> +    if (is_write) {
>          num = &elem->in_num;
>          iov = &elem->in_sg[*num];
>          addr = &elem->in_addr[*num];
> @@ -186,44 +191,45 @@ static int get_desc(Vring *vring, VirtQueueElement *elem,
>      }
> 
>      /* TODO handle non-contiguous memory across region boundaries */
> -    iov->iov_base = vring_map(&mr, desc->addr, desc->len,
> -                              desc->flags & VRING_DESC_F_WRITE);
> +    iov->iov_base = vring_map(&mr, desc_addr, len, is_write);
>      if (!iov->iov_base) {
>          error_report("Failed to map descriptor addr %#" PRIx64 " len %u",
> -                     (uint64_t)desc->addr, desc->len);
> +                     (uint64_t)desc_addr, len);
>          return -EFAULT;
>      }
> 
>      /* The MemoryRegion is looked up again and unref'ed later, leave the
>       * ref in place.  */
> -    iov->iov_len = desc->len;
> -    *addr = desc->addr;
> +    iov->iov_len = len;
> +    *addr = desc_addr;
>      *num += 1;
>      return 0;
>  }
> 
>  /* This is stolen from linux/drivers/vhost/vhost.c. */
> -static int get_indirect(Vring *vring, VirtQueueElement *elem,
> -                        struct vring_desc *indirect)
> +static int get_indirect(VirtIODevice *vdev, Vring *vring,
> +                        VirtQueueElement *elem, struct vring_desc *indirect)
>  {
>      struct vring_desc desc;
>      unsigned int i = 0, count, found = 0;
>      int ret;
> +    uint32_t len = virtio_tswap32(vdev, indirect->len);
> +    uint64_t addr = virtio_tswap64(vdev, indirect->addr);
> 
>      /* Sanity check */
> -    if (unlikely(indirect->len % sizeof(desc))) {
> +    if (unlikely(len % sizeof(desc))) {
>          error_report("Invalid length in indirect descriptor: "
>                       "len %#x not multiple of %#zx",
> -                     indirect->len, sizeof(desc));
> +                     len, sizeof(desc));
>          vring->broken = true;
>          return -EFAULT;
>      }
> 
> -    count = indirect->len / sizeof(desc);
> +    count = len / sizeof(desc);
>      /* Buffers are chained via a 16 bit next field, so
>       * we can have at most 2^16 of these. */
>      if (unlikely(count > USHRT_MAX + 1)) {
> -        error_report("Indirect buffer length too big: %d", indirect->len);
> +        error_report("Indirect buffer length too big: %d", len);
>          vring->broken = true;
>          return -EFAULT;
>      }
> @@ -234,12 +240,12 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem,
> 
>          /* Translate indirect descriptor */
>          desc_ptr = vring_map(&mr,
> -                             indirect->addr + found * sizeof(desc),
> +                             addr + found * sizeof(desc),
>                               sizeof(desc), false);
>          if (!desc_ptr) {
>              error_report("Failed to map indirect descriptor "
>                           "addr %#" PRIx64 " len %zu",
> -                         (uint64_t)indirect->addr + found * sizeof(desc),
> +                         (uint64_t)addr + found * sizeof(desc),
>                           sizeof(desc));
>              vring->broken = true;
>              return -EFAULT;
> @@ -257,19 +263,20 @@ static int get_indirect(Vring *vring, VirtQueueElement *elem,
>              return -EFAULT;
>          }
> 
> -        if (unlikely(desc.flags & VRING_DESC_F_INDIRECT)) {
> +        if (unlikely(virtio_tswap16(vdev, desc.flags)
> +                     & VRING_DESC_F_INDIRECT)) {
>              error_report("Nested indirect descriptor");
>              vring->broken = true;
>              return -EFAULT;
>          }
> 
> -        ret = get_desc(vring, elem, &desc);
> +        ret = get_desc(vdev, vring, elem, &desc);
>          if (ret < 0) {
>              vring->broken |= (ret == -EFAULT);
>              return ret;
>          }
> -        i = desc.next;
> -    } while (desc.flags & VRING_DESC_F_NEXT);
> +        i = virtio_tswap16(vdev, desc.next);
> +    } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT);
>      return 0;
>  }
> 
> @@ -320,7 +327,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
> 
>      /* Check it isn't doing very strange things with descriptor numbers. */
>      last_avail_idx = vring->last_avail_idx;
> -    avail_idx = vring->vr.avail->idx;
> +    avail_idx = vring_get_avail_idx(vdev, vring);
>      barrier(); /* load indices now and not again later */
> 
>      if (unlikely((uint16_t)(avail_idx - last_avail_idx) > num)) {
> @@ -341,7 +348,7 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
> 
>      /* Grab the next descriptor number they're advertising, and increment
>       * the index we've seen. */
> -    head = vring->vr.avail->ring[last_avail_idx % num];
> +    head = vring_get_avail_ring(vdev, vring, last_avail_idx % num);
> 
>      elem->index = head;
> 
> @@ -374,21 +381,21 @@ int vring_pop(VirtIODevice *vdev, Vring *vring,
>          /* Ensure descriptor is loaded before accessing fields */
>          barrier();
> 
> -        if (desc.flags & VRING_DESC_F_INDIRECT) {
> -            ret = get_indirect(vring, elem, &desc);
> +        if (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_INDIRECT) {
> +            ret = get_indirect(vdev, vring, elem, &desc);
>              if (ret < 0) {
>                  goto out;
>              }
>              continue;
>          }
> 
> -        ret = get_desc(vring, elem, &desc);
> +        ret = get_desc(vdev, vring, elem, &desc);
>          if (ret < 0) {
>              goto out;
>          }
> 
> -        i = desc.next;
> -    } while (desc.flags & VRING_DESC_F_NEXT);
> +        i = virtio_tswap16(vdev, desc.next);
> +    } while (virtio_tswap16(vdev, desc.flags) & VRING_DESC_F_NEXT);
> 
>      /* On success, increment avail index. */
>      vring->last_avail_idx++;
> @@ -407,9 +414,9 @@ out:
>   *
>   * Stolen from linux/drivers/vhost/vhost.c.
>   */
> -void vring_push(Vring *vring, VirtQueueElement *elem, int len)
> +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem,
> +                int len)
>  {
> -    struct vring_used_elem *used;
>      unsigned int head = elem->index;
>      uint16_t new;
> 
> @@ -422,14 +429,16 @@ void vring_push(Vring *vring, VirtQueueElement *elem, int len)
> 
>      /* The virtqueue contains a ring of used buffers.  Get a pointer to the
>       * next entry in that used ring. */
> -    used = &vring->vr.used->ring[vring->last_used_idx % vring->vr.num];
> -    used->id = head;
> -    used->len = len;
> +    vring_set_used_ring_id(vdev, vring, vring->last_used_idx % vring->vr.num,
> +                           head);
> +    vring_set_used_ring_len(vdev, vring, vring->last_used_idx % vring->vr.num,
> +                            len);
> 
>      /* Make sure buffer is written before we update index. */
>      smp_wmb();
> 
> -    new = vring->vr.used->idx = ++vring->last_used_idx;
> +    new = ++vring->last_used_idx;
> +    vring_set_used_idx(vdev, vring, new);
>      if (unlikely((int16_t)(new - vring->signalled_used) < (uint16_t)1)) {
>          vring->signalled_used_valid = false;
>      }
> diff --git a/include/hw/virtio/dataplane/vring.h b/include/hw/virtio/dataplane/vring.h
> index d3e086a..fde15f3 100644
> --- a/ 
> +++ b/include/hw/virtio/dataplane/vring.h
> @@ -20,6 +20,7 @@
>  #include "qemu-common.h"
>  #include "hw/virtio/virtio_ring.h"
>  #include "hw/virtio/virtio.h"
> +#include "hw/virtio/virtio-access.h"
> 

Since the following commit:

commit 244e2898b7a7735b3da114c120abe206af56a167
Author: Fam Zheng <famz@redhat.com>
Date:   Wed Sep 24 15:21:41 2014 +0800

    virtio-scsi: Add VirtIOSCSIVring in VirtIOSCSIReq

The include/hw/virtio/dataplane/vring.h header is indirectly included
by hw/virtio/virtio-pci.c. Why don't you move all this target dependent
helpers to another header ?

Cheers.

--
Greg

>  typedef struct {
>      MemoryRegion *mr;               /* memory region containing the vring */
> @@ -31,15 +32,71 @@ typedef struct {
>      bool broken;                    /* was there a fatal error? */
>  } Vring;
> 
> +static inline uint16_t vring_get_used_idx(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.used->idx);
> +}
> +
> +static inline void vring_set_used_idx(VirtIODevice *vdev, Vring *vring,
> +                                      uint16_t idx)
> +{
> +    vring->vr.used->idx = virtio_tswap16(vdev, idx);
> +}
> +
> +static inline uint16_t vring_get_avail_idx(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.avail->idx);
> +}
> +
> +static inline uint16_t vring_get_avail_ring(VirtIODevice *vdev, Vring *vring,
> +                                            int i)
> +{
> +    return virtio_tswap16(vdev, vring->vr.avail->ring[i]);
> +}
> +
> +static inline void vring_set_used_ring_id(VirtIODevice *vdev, Vring *vring,
> +                                          int i, uint32_t id)
> +{
> +    vring->vr.used->ring[i].id = virtio_tswap32(vdev, id);
> +}
> +
> +static inline void vring_set_used_ring_len(VirtIODevice *vdev, Vring *vring,
> +                                          int i, uint32_t len)
> +{
> +    vring->vr.used->ring[i].len = virtio_tswap32(vdev, len);
> +}
> +
> +static inline uint16_t vring_get_used_flags(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.used->flags);
> +}
> +
> +static inline uint16_t vring_get_avail_flags(VirtIODevice *vdev, Vring *vring)
> +{
> +    return virtio_tswap16(vdev, vring->vr.avail->flags);
> +}
> +
> +static inline void vring_set_used_flags(VirtIODevice *vdev, Vring *vring,
> +                                        uint16_t flags)
> +{
> +    vring->vr.used->flags |= virtio_tswap16(vdev, flags);
> +}
> +
> +static inline void vring_clear_used_flags(VirtIODevice *vdev, Vring *vring,
> +                                          uint16_t flags)
> +{
> +    vring->vr.used->flags &= virtio_tswap16(vdev, ~flags);
> +}
> +
>  static inline unsigned int vring_get_num(Vring *vring)
>  {
>      return vring->vr.num;
>  }
> 
>  /* Are there more descriptors available? */
> -static inline bool vring_more_avail(Vring *vring)
> +static inline bool vring_more_avail(VirtIODevice *vdev, Vring *vring)
>  {
> -    return vring->vr.avail->idx != vring->last_avail_idx;
> +    return vring_get_avail_idx(vdev, vring) != vring->last_avail_idx;
>  }
> 
>  /* Fail future vring_pop() and vring_push() calls until reset */
> @@ -54,6 +111,7 @@ void vring_disable_notification(VirtIODevice *vdev, Vring *vring);
>  bool vring_enable_notification(VirtIODevice *vdev, Vring *vring);
>  bool vring_should_notify(VirtIODevice *vdev, Vring *vring);
>  int vring_pop(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem);
> -void vring_push(Vring *vring, VirtQueueElement *elem, int len);
> +void vring_push(VirtIODevice *vdev, Vring *vring, VirtQueueElement *elem,
> +                int len);
> 
>  #endif /* VRING_H */

  reply	other threads:[~2014-10-28 15:23 UTC|newest]

Thread overview: 84+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-07 14:39 [PATCH RFC 00/11] qemu: towards virtio-1 host support Cornelia Huck
2014-10-07 14:39 ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:39 ` [PATCH RFC 01/11] linux-headers/virtio_config: Update with VIRTIO_F_VERSION_1 Cornelia Huck
2014-10-07 14:39   ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:39 ` Cornelia Huck
2014-10-07 14:39 ` [PATCH RFC 02/11] virtio: cull virtio_bus_set_vdev_features Cornelia Huck
2014-10-07 14:39 ` Cornelia Huck
2014-10-07 14:39   ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:39 ` [PATCH RFC 03/11] virtio: support more feature bits Cornelia Huck
2014-10-07 14:39 ` Cornelia Huck
2014-10-07 14:39   ` [Qemu-devel] " Cornelia Huck
2014-10-13  5:53   ` Rusty Russell
2014-10-13  5:53     ` [Qemu-devel] " Rusty Russell
2014-10-13 10:55     ` Cornelia Huck
2014-10-13 10:55       ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 04/11] s390x/virtio-ccw: fix check for WRITE_FEAT Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:40 ` Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 05/11] virtio: introduce legacy virtio devices Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-28 15:40   ` Greg Kurz
2014-10-28 15:40   ` Greg Kurz
2014-10-28 15:40     ` Greg Kurz
2014-10-30 18:02     ` Cornelia Huck
2014-10-30 18:02       ` Cornelia Huck
2014-10-30 22:29       ` Greg Kurz
2014-10-30 22:29         ` Greg Kurz
2014-11-03 11:44         ` Cornelia Huck
2014-11-03 11:44           ` Cornelia Huck
2014-11-03 11:44         ` Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 06/11] virtio: allow virtio-1 queue layout Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 07/11] dataplane: allow virtio-1 devices Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-28 15:22   ` Greg Kurz [this message]
2014-10-28 15:22     ` Greg Kurz
2014-10-30  9:18     ` Cornelia Huck
2014-10-30  9:18       ` Cornelia Huck
2014-10-28 15:22   ` Greg Kurz
2014-10-07 14:40 ` Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 08/11] s390x/css: Add a callback for when subchannel gets disabled Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:40 ` Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 09/11] s390x/virtio-ccw: add virtio set-revision call Cornelia Huck
2014-10-07 14:40 ` Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 10/11] s390x/virtio-ccw: support virtio-1 set_vq format Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-07 14:40 ` [PATCH RFC 11/11] s390x/virtio-ccw: enable virtio 1.0 Cornelia Huck
2014-10-07 14:40 ` Cornelia Huck
2014-10-07 14:40   ` [Qemu-devel] " Cornelia Huck
2014-10-08  1:24 ` [PATCH RFC 00/11] qemu: towards virtio-1 host support Andy Lutomirski
2014-10-08  1:24   ` [Qemu-devel] " Andy Lutomirski
2014-10-08  9:04   ` Cornelia Huck
2014-10-08  9:04     ` [Qemu-devel] " Cornelia Huck
2014-10-22  8:44     ` Michael S. Tsirkin
2014-10-22  8:44       ` [Qemu-devel] " Michael S. Tsirkin
2014-10-22 14:17       ` Jan Kiszka
2014-10-22 14:17         ` [Qemu-devel] " Jan Kiszka
2014-10-22 14:36         ` Michael S. Tsirkin
2014-10-22 14:36           ` [Qemu-devel] " Michael S. Tsirkin
2014-10-22 20:34         ` Benjamin Herrenschmidt
2014-10-22 20:34           ` [Qemu-devel] " Benjamin Herrenschmidt
2014-10-23  6:44           ` Jan Kiszka
2014-10-23  6:44             ` [Qemu-devel] " Jan Kiszka
2014-10-23  9:18             ` Michael S. Tsirkin
2014-10-23  9:18               ` [Qemu-devel] " Michael S. Tsirkin
2014-10-23  7:12           ` Michael S. Tsirkin
2014-10-23  7:12             ` [Qemu-devel] " Michael S. Tsirkin
2014-10-23 21:42 ` Michael S. Tsirkin
2014-10-23 21:42   ` [Qemu-devel] " Michael S. Tsirkin
2014-10-24  8:38   ` Cornelia Huck
2014-10-24  8:38   ` Cornelia Huck
2014-10-24  8:38     ` [Qemu-devel] " Cornelia Huck
2014-10-24 12:37     ` Cornelia Huck
2014-10-24 12:37       ` [Qemu-devel] " Cornelia Huck
2014-10-24 14:05       ` Michael S. Tsirkin
2014-10-24 14:05         ` [Qemu-devel] " Michael S. Tsirkin
2014-10-24 14:17     ` Michael S. Tsirkin
2014-10-24 14:17       ` [Qemu-devel] " Michael S. Tsirkin
2014-10-28  4:43     ` Michael S. Tsirkin
2014-10-28  4:43       ` [Qemu-devel] " Michael S. Tsirkin
2014-10-30 16:52       ` Cornelia Huck
2014-10-30 16:52         ` [Qemu-devel] " Cornelia Huck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141028162254.2a4f2cf4@bahia.local \
    --to=gkurz@linux.vnet.ibm.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=qemu-devel@nongnu.org \
    --cc=rusty@rustcorp.com.au \
    --cc=thuth@linux.vnet.ibm.com \
    --cc=virtualization@lists.linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.