qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Pavel Dovgalyuk <Pavel.Dovgaluk@gmail.com>
Cc: vsementsov@virtuozzo.com, qemu-devel@nongnu.org,
	mreitz@redhat.com, dovgaluk@ispras.ru, pavel.dovgaluk@ispras.ru,
	jsnow@redhat.com
Subject: Re: [PATCH v2] icount: make dma reads deterministic
Date: Tue, 2 Jun 2020 17:54:40 +0200	[thread overview]
Message-ID: <20200602155440.GK5940@linux.fritz.box> (raw)
In-Reply-To: <158823737122.27545.13132967751052120169.stgit@pasha-ThinkPad-X280>

Am 30.04.2020 um 11:02 hat Pavel Dovgalyuk geschrieben:
> From: Pavel Dovgalyuk <pavel.dovgaluk@gmail.com>
> 
> Windows guest sometimes makes DMA requests with overlapping
> target addresses. This leads to the following structure of iov for
> the block driver:
> 
> addr size1
> addr size2
> addr size3
> 
> It means that three adjacent disk blocks should be read into the same
> memory buffer. Windows does not expects anything from these bytes
> (should it be data from the first block, or the last one, or some mix),
> but uses them somehow. It leads to non-determinism of the guest execution,
> because block driver does not preserve any order of reading.
> 
> This situation was discusses in the mailing list at least twice:
> https://lists.gnu.org/archive/html/qemu-devel/2010-09/msg01996.html
> https://lists.gnu.org/archive/html/qemu-devel/2020-02/msg05185.html
> 
> This patch makes such disk reads deterministic in icount mode.
> It splits the whole request into several parts. Parts may overlap,
> but SGs inside one part do not overlap.
> Parts that are processed later overwrite the prior ones in case
> of overlapping.
> 
> Examples for different SG part sequences:
> 
> 1)
> A1 1000
> A2 1000
> A1 1000
> A3 1000
> ->
> One request is split into two.
> A1 1000
> A2 1000
> --
> A1 1000
> A3 1000
> 
> 2)
> A1 800
> A2 1000
> A1 1000
> ->
> A1 800
> A2 1000
> --
> A1 1000
> 
> Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
> 
> --
> 
> v2:
>  - Rewritten the loop to split the request instead of skipping the parts
>    (suggested by Kevin Wolf)
> ---
>  dma-helpers.c |   20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/dma-helpers.c b/dma-helpers.c
> index e8a26e81e1..a49f9a0e34 100644
> --- a/dma-helpers.c
> +++ b/dma-helpers.c
> @@ -13,6 +13,8 @@
>  #include "trace-root.h"
>  #include "qemu/thread.h"
>  #include "qemu/main-loop.h"
> +#include "sysemu/cpus.h"
> +#include "qemu/range.h"
>  
>  /* #define DEBUG_IOMMU */
>  
> @@ -142,6 +144,24 @@ static void dma_blk_cb(void *opaque, int ret)
>          cur_addr = dbs->sg->sg[dbs->sg_cur_index].base + dbs->sg_cur_byte;
>          cur_len = dbs->sg->sg[dbs->sg_cur_index].len - dbs->sg_cur_byte;
>          mem = dma_memory_map(dbs->sg->as, cur_addr, &cur_len, dbs->dir);
> +        /*
> +         * Make reads deterministic in icount mode. Windows sometimes issues
> +         * disk read requests with overlapping SGs. It leads
> +         * to non-determinism, because resulting buffer contents may be mixed
> +         * from several sectors. This code splits all SGs into several
> +         * groups. SGs in every group do not overlap.
> +         */
> +        if (use_icount && dbs->dir == DMA_DIRECTION_FROM_DEVICE) {
> +            int i;
> +            for (i = 0 ; i < dbs->iov.niov ; ++i) {
> +                if (ranges_overlap((intptr_t)dbs->iov.iov[i].iov_base,
> +                                   dbs->iov.iov[i].iov_len, (intptr_t)mem,
> +                                   cur_len)) {
> +                    mem = NULL;

Doesn't this leak mem, i.e. should we call dma_memory_unmap()?

Did you verify that it is guaranteed that mapping the same guest memory
twice results in the same host address? v1 compared the SG list (which
has guest addresses) rather than the resulting QEMUIOVector (which has
host addresses).

> +                    break;
> +                }
> +            }
> +        }
>          if (!mem)
>              break;
>          qemu_iovec_add(&dbs->iov, mem, cur_len);

Kevin



  parent reply	other threads:[~2020-06-02 15:56 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-30  9:02 [PATCH v2] icount: make dma reads deterministic Pavel Dovgalyuk
2020-06-01 10:36 ` Pavel Dovgalyuk
2020-06-02 15:54 ` Kevin Wolf [this message]
2020-06-03  5:57   ` Pavel Dovgalyuk
2020-06-03  8:15     ` Kevin Wolf
2020-06-03  8:56       ` Pavel Dovgalyuk
2020-06-03  9:37       ` Pavel Dovgalyuk
  -- strict thread matches above, loose matches on Subject: below --
2020-03-03 12:26 Pavel Dovgalyuk
2020-03-11 12:42 ` Pavel Dovgalyuk

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=20200602155440.GK5940@linux.fritz.box \
    --to=kwolf@redhat.com \
    --cc=Pavel.Dovgaluk@gmail.com \
    --cc=dovgaluk@ispras.ru \
    --cc=jsnow@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=pavel.dovgaluk@ispras.ru \
    --cc=qemu-devel@nongnu.org \
    --cc=vsementsov@virtuozzo.com \
    /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 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).