All of lore.kernel.org
 help / color / mirror / Atom feed
From: Wen Congyang <wency@cn.fujitsu.com>
To: Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
	qemu-devel@nongnu.org
Cc: mst@redhat.com, xen devel <xen-devel@lists.xen.org>,
	Fabio Fantoni <fabio.fantoni@m2r.biz>,
	aliguori@amazon.com, anthony PERARD <anthony.perard@citrix.com>,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [Qemu-devel] virtio leaks cpu mappings, was: qemu crash with virtio on Xen domUs (backtrace included)
Date: Tue, 25 Nov 2014 09:32:17 +0800	[thread overview]
Message-ID: <5473DC21.6010709@cn.fujitsu.com> (raw)
In-Reply-To: <alpine.DEB.2.02.1411241816040.2675@kaball.uk.xensource.com>

On 11/25/2014 02:44 AM, Stefano Stabellini wrote:
> On Mon, 24 Nov 2014, Stefano Stabellini wrote:
>> On Mon, 24 Nov 2014, Stefano Stabellini wrote:
>>> CC'ing Paolo.
>>>
>>>
>>> Wen,
>>> thanks for the logs.
>>>
>>> I investigated a little bit and it seems to me that the bug occurs when
>>> QEMU tries to unmap only a portion of a memory region previously mapped.
>>> That doesn't work with xen-mapcache.
>>>
>>> See these logs for example:
>>>
>>> DEBUG address_space_map phys_addr=78ed8b44 vaddr=7fab50afbb68 len=0xa
>>> DEBUG address_space_unmap vaddr=7fab50afbb68 len=0x6
>>
>> Sorry the logs don't quite match, it was supposed to be:
>>
>> DEBUG address_space_map phys_addr=78ed8b44 vaddr=7fab50afbb64 len=0xa
>> DEBUG address_space_unmap vaddr=7fab50afbb68 len=0x6
> 
> It looks like the problem is caused by iov_discard_front, called by
> virtio_net_handle_ctrl. By changing iov_base after the sg has already
> been mapped (cpu_physical_memory_map), it causes a leak in the mapping
> because the corresponding cpu_physical_memory_unmap will only unmap a
> portion of the original sg.  On Xen the problem is worse because
> xen-mapcache aborts.

This patch works for me.

Thanks
Wen Congyang

> 
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 2ac6ce5..b2b5c2d 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -775,7 +775,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
>      struct iovec *iov;
>      unsigned int iov_cnt;
>  
> -    while (virtqueue_pop(vq, &elem)) {
> +    while (virtqueue_pop_nomap(vq, &elem)) {
>          if (iov_size(elem.in_sg, elem.in_num) < sizeof(status) ||
>              iov_size(elem.out_sg, elem.out_num) < sizeof(ctrl)) {
>              error_report("virtio-net ctrl missing headers");
> @@ -784,8 +784,12 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
>  
>          iov = elem.out_sg;
>          iov_cnt = elem.out_num;
> -        s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
>          iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
> +
> +        virtqueue_map_sg(elem.in_sg, elem.in_addr, elem.in_num, 1);
> +        virtqueue_map_sg(elem.out_sg, elem.out_addr, elem.out_num, 0);
> +
> +        s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
>          if (s != sizeof(ctrl)) {
>              status = VIRTIO_NET_ERR;
>          } else if (ctrl.class == VIRTIO_NET_CTRL_RX) {
> diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
> index 3e4b70c..6a4bd3a 100644
> --- a/hw/virtio/virtio.c
> +++ b/hw/virtio/virtio.c
> @@ -446,7 +446,7 @@ void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
>      }
>  }
>  
> -int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
> +int virtqueue_pop_nomap(VirtQueue *vq, VirtQueueElement *elem)
>  {
>      unsigned int i, head, max;
>      hwaddr desc_pa = vq->vring.desc;
> @@ -505,9 +505,6 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
>          }
>      } while ((i = virtqueue_next_desc(desc_pa, i, max)) != max);
>  
> -    /* Now map what we have collected */
> -    virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1);
> -    virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0);
>  
>      elem->index = head;
>  
> @@ -517,6 +514,16 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
>      return elem->in_num + elem->out_num;
>  }
>  
> +int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
> +{
> +    int rc = virtqueue_pop_nomap(vq, elem);
> +    if (rc > 0) {
> +        virtqueue_map_sg(elem->in_sg, elem->in_addr, elem->in_num, 1);
> +        virtqueue_map_sg(elem->out_sg, elem->out_addr, elem->out_num, 0);
> +    }
> +    return rc;
> +}
> +
>  /* virtio device */
>  static void virtio_notify_vector(VirtIODevice *vdev, uint16_t vector)
>  {
> diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
> index 3e54e90..40a3977 100644
> --- a/include/hw/virtio/virtio.h
> +++ b/include/hw/virtio/virtio.h
> @@ -174,6 +174,7 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
>  void virtqueue_map_sg(struct iovec *sg, hwaddr *addr,
>      size_t num_sg, int is_write);
>  int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);
> +int virtqueue_pop_nomap(VirtQueue *vq, VirtQueueElement *elem);
>  int virtqueue_avail_bytes(VirtQueue *vq, unsigned int in_bytes,
>                            unsigned int out_bytes);
>  void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
> .
> 

  parent reply	other threads:[~2014-11-25  1:30 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-24  1:58 virtio on Xen cannot work Wen Congyang
2014-11-24  8:52 ` qemu crash with virtio on Xen domUs (backtrace included) Fabio Fantoni
2014-11-24  8:52 ` [Qemu-devel] " Fabio Fantoni
2014-11-24  9:25   ` Wen Congyang
2014-11-24 15:23     ` Stefano Stabellini
2014-11-24 17:32       ` Stefano Stabellini
2014-11-24 17:32       ` [Qemu-devel] [Xen-devel] " Stefano Stabellini
2014-11-24 18:44         ` [Qemu-devel] virtio leaks cpu mappings, was: " Stefano Stabellini
2014-11-24 18:52           ` Konrad Rzeszutek Wilk
2014-11-24 18:52           ` [Qemu-devel] [Xen-devel] " Konrad Rzeszutek Wilk
2014-11-24 19:01             ` Stefano Stabellini
2014-11-24 19:01             ` Stefano Stabellini
2014-11-25  1:32           ` Wen Congyang
2014-11-25  1:32           ` Wen Congyang [this message]
2014-11-25  6:16           ` [Qemu-devel] [Xen-devel] " Jason Wang
2014-11-25 13:53             ` Stefano Stabellini
2014-11-25 13:53             ` [Qemu-devel] [Xen-devel] " Stefano Stabellini
2014-11-26  5:23               ` Jason Wang
2014-11-26  5:23               ` [Qemu-devel] [Xen-devel] " Jason Wang
2014-11-26 10:53                 ` Stefano Stabellini
2014-11-26 10:53                   ` Stefano Stabellini
2014-11-27  5:01                   ` Jason Wang
2014-11-27  5:01                   ` [Qemu-devel] [Xen-devel] " Jason Wang
2014-11-25  6:16           ` Jason Wang
2014-11-24 18:44         ` Stefano Stabellini
2014-11-24 15:23     ` Stefano Stabellini
2014-11-24  9:25   ` Wen Congyang

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=5473DC21.6010709@cn.fujitsu.com \
    --to=wency@cn.fujitsu.com \
    --cc=aliguori@amazon.com \
    --cc=anthony.perard@citrix.com \
    --cc=fabio.fantoni@m2r.biz \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xen.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.