From: Jason Wang <jasowang@redhat.com>
To: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: mst@redhat.com, qemu-devel@nongnu.org,
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] [Xen-devel] virtio leaks cpu mappings, was: qemu crash with virtio on Xen domUs (backtrace included)
Date: Wed, 26 Nov 2014 13:23:50 +0800 [thread overview]
Message-ID: <547563E6.2090505@redhat.com> (raw)
In-Reply-To: <alpine.DEB.2.02.1411251249380.2675@kaball.uk.xensource.com>
On 11/25/2014 09:53 PM, Stefano Stabellini wrote:
> On Tue, 25 Nov 2014, Jason Wang wrote:
>> 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.
>>>
>>> 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));
>> Does this really work?
> It seems to work here, as in it doesn't crash QEMU and I am able to boot
> a guest with network. I didn't try any MAC related commands.
>
It was because the guest (not a recent kernel?) never issue commands
through control vq.
We'd better hide the implementation details such as virtqueue_map_sg()
in virtio core instead of letting device call it directly.
>> The code in fact skips the location that contains
>> virtio_net_ctrl_hdr. And virtio_net_handle_mac() still calls
>> iov_discard_front().
>>
>> How about copy iov to a temp variable and use it in this function?
> That would only work if I moved the cpu_physical_memory_unmap call
> outside of virtqueue_fill, so that we can pass different iov to them.
> We need to unmap the same iov that was previously mapped by
> virtqueue_pop.
>
I mean something like following or just passing the offset of iov to
virtio_net_handle_*().
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 9b88775..fdb4edd 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -798,7 +798,7 @@ static void virtio_net_handle_ctrl(VirtIODevice
*vdev, VirtQueue *vq)
virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
VirtQueueElement elem;
size_t s;
- struct iovec *iov;
+ struct iovec *iov, *iov2;
unsigned int iov_cnt;
while (virtqueue_pop(vq, &elem)) {
@@ -808,8 +808,12 @@ static void virtio_net_handle_ctrl(VirtIODevice
*vdev, VirtQueue *vq)
exit(1);
}
- iov = elem.out_sg;
iov_cnt = elem.out_num;
+ s = sizeof(struct iovec) * elem.out_num;
+ iov = g_malloc(s);
+ memcpy(iov, elem.out_sg, s);
+ iov2 = iov;
+
s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
iov_discard_front(&iov, &iov_cnt, sizeof(ctrl));
if (s != sizeof(ctrl)) {
@@ -833,6 +837,7 @@ static void virtio_net_handle_ctrl(VirtIODevice
*vdev, VirtQueue *vq)
virtqueue_push(vq, &elem, sizeof(status));
virtio_notify(vdev, vq);
+ g_free(iov2);
}
}
next prev parent reply other threads:[~2014-11-26 5:24 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-devel] qemu crash with virtio on Xen domUs (backtrace included) Fabio Fantoni
2014-11-24 9:25 ` Wen Congyang
2014-11-24 15:23 ` Stefano Stabellini
2014-11-24 15:23 ` [Qemu-devel] " Stefano Stabellini
2014-11-24 17:32 ` [Qemu-devel] [Xen-devel] " Stefano Stabellini
2014-11-24 18:44 ` virtio leaks cpu mappings, was: " Stefano Stabellini
2014-11-24 18:44 ` [Qemu-devel] " Stefano Stabellini
2014-11-24 18:52 ` [Qemu-devel] [Xen-devel] " Konrad Rzeszutek Wilk
2014-11-24 19:01 ` Stefano Stabellini
2014-11-24 19:01 ` [Qemu-devel] [Xen-devel] " Stefano Stabellini
2014-11-24 18:52 ` Konrad Rzeszutek Wilk
2014-11-25 1:32 ` [Qemu-devel] " Wen Congyang
2014-11-25 1:32 ` Wen Congyang
2014-11-25 6:16 ` [Qemu-devel] [Xen-devel] " Jason Wang
2014-11-25 13:53 ` Stefano Stabellini
2014-11-26 5:23 ` Jason Wang [this message]
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-26 5:23 ` Jason Wang
2014-11-25 13:53 ` Stefano Stabellini
2014-11-25 6:16 ` Jason Wang
2014-11-24 17:32 ` Stefano Stabellini
2014-11-24 9:25 ` Wen Congyang
2014-11-24 8:52 ` Fabio Fantoni
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=547563E6.2090505@redhat.com \
--to=jasowang@redhat.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.