qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: qemu-devel@nongnu.org,
	Richard Henderson <richard.henderson@linaro.org>,
	 "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Subject: Re: [Qemu-devel] [PULL 15/36] memory: fix race between TCG and accesses to dirty bitmap
Date: Tue, 2 Aug 2022 17:17:27 +0100	[thread overview]
Message-ID: <CAFEAcA-hV9BERt=4wP0hdb7HemrzpFC1v8UrmypKFYV4DPw-Bw@mail.gmail.com> (raw)
In-Reply-To: <1566284395-30287-16-git-send-email-pbonzini@redhat.com>

On Tue, 20 Aug 2019 at 08:12, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> There is a race between TCG and accesses to the dirty log:
>
>       vCPU thread                  reader thread
>       -----------------------      -----------------------
>       TLB check -> slow path
>         notdirty_mem_write
>           write to RAM
>           set dirty flag
>                                    clear dirty flag
>       TLB check -> fast path
>                                    read memory
>         write to RAM
>
> Fortunately, in order to fix it, no change is required to the
> vCPU thread.  However, the reader thread must delay the read after
> the vCPU thread has finished the write.  This can be approximated
> conservatively by run_on_cpu, which waits for the end of the current
> translation block.
>
> A similar technique is used by KVM, which has to do a synchronous TLB
> flush after doing a test-and-clear of the dirty-page flags.
>
> Reported-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>


> +static void tcg_log_global_after_sync(MemoryListener *listener)
> +{
> +    CPUAddressSpace *cpuas;
> +
> +    /* Wait for the CPU to end the current TB.  This avoids the following
> +     * incorrect race:
> +     *
> +     *      vCPU                         migration
> +     *      ----------------------       -------------------------
> +     *      TLB check -> slow path
> +     *        notdirty_mem_write
> +     *          write to RAM
> +     *          mark dirty
> +     *                                   clear dirty flag
> +     *      TLB check -> fast path
> +     *                                   read memory
> +     *        write to RAM
> +     *
> +     * by pushing the migration thread's memory read after the vCPU thread has
> +     * written the memory.
> +     */
> +    cpuas = container_of(listener, CPUAddressSpace, tcg_as_listener);
> +    run_on_cpu(cpuas->cpu, do_nothing, RUN_ON_CPU_NULL);
> +}

So I think this implementation has two problems that we've only just
noticed:

(1) if memory_global_after_dirty_log_sync() is called in a context
where the caller holds the BQL, then the implementation here will
temporarily drop the BQL inside run_on_cpu(). That breaks
assumptions in pretty much all the graphics device models which
call memory_region_snapshot_and_clear_dirty() and assume that
things they'd determined before the call stay valid (pointers
into DisplaySurfaces, information about size and location of
the framebuffer in guest memory, etc).

(2) if memory_global_after_dirty_log_sync() is called in a context
where the caller does *not* hold the BQL, this is undefined
behaviour, because run_on_cpu() calls qemu_cond_wait() passing
it the BKL, and at least for the posix implementation that
ends up being posix_cond_wait() and calling that without the
mutex held is undefined behaviour. This happens for the migration
code for everything except the final iteration.

Does anybody have any bright ideas for fixing these? (2) I guess
we could handle just by having the migration code (or this
code right here) grab the BQL if it doesn't already have it.
(1) is much harder: you kind of conceptually want to do a "go back
and restart the update-display operation", but there's no clear
way to tell if you need to do that. You can postpone some things
(like "get the current UI display surface") until after the
call to memory_region_snapshot_and_clear_dirty(), and you could
have a "check a flag to see if the guest re-entered the display
device while we were inside memory_region_snapshot_and_clear_dirty()"
test, but some things the guest might do could potentially invalidate
things in a non-obvious action-at-a-distance way that doesn't
require an access to the display device. (e.g. a display device that
lets the guest program the FB to be anywhere in the address map,
plus the ability for the guest to cause remapping of RAM banks
or similar -- the display device can't tell if the RAM banks
got remapped or not, that's handled by a different device.)

thanks
-- PMM


  parent reply	other threads:[~2022-08-02 16:22 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-20  6:59 [Qemu-devel] [PULL 00/36] QEMU patches for 2018-08-20 Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 01/36] kvm: i386: halt poll control MSR support Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 02/36] target-i386: adds PV_SCHED_YIELD CPUID feature bit Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 03/36] loader: Handle memory-mapped ELFs Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 04/36] elf-ops.h: Map into memory the ELF to load Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 05/36] hw/i386/pc: Map into memory the initrd Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 06/36] memory: assert on out of scope notification Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 07/36] configure: Define target access alignment in configure Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 08/36] block: fix NetBSD qemu-iotests failure Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 09/36] 9p: simplify source file selection Paolo Bonzini
2020-11-03 20:31   ` Philippe Mathieu-Daudé
2019-08-20  6:59 ` [Qemu-devel] [PULL 10/36] target-i386: kvm: 'kvm_get_supported_msrs' cleanup Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 11/36] test-throttle: Fix uninitialized use of burst_length Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 12/36] tests: Fix uninitialized byte in test_visitor_in_fuzz Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 13/36] i386/kvm: initialize struct at full before ioctl call Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 14/36] target/i386: Return 'indefinite integer value' for invalid SSE fp->int conversions Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 15/36] memory: fix race between TCG and accesses to dirty bitmap Paolo Bonzini
2019-08-26 12:19   ` dovgaluk
2019-09-12  6:54     ` Pavel Dovgalyuk
2019-09-12 17:43       ` Richard Henderson
2019-09-12 22:16         ` Paolo Bonzini
2019-09-12 12:45     ` Paolo Bonzini
2022-08-02 16:17   ` Peter Maydell [this message]
2019-08-20  6:59 ` [Qemu-devel] [PULL 16/36] mc146818rtc: Remove reset notifiers Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 17/36] timer: " Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 18/36] replay: Remove host_clock_last Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 19/36] timer: last, remove last bits of last Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 20/36] kconfig: do not select VMMOUSE Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 21/36] replay: add missing fix for internal function Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 22/36] replay: document development rules Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 23/36] util/qemu-timer: refactor deadline calculation for external timers Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 24/36] replay: fix replay shutdown Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 25/36] replay: refine replay-time module Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 26/36] replay: rename step-related variables and functions Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 27/36] icount: clean up cpu_can_io at the entry to the block Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 28/36] icount: remove unnecessary gen_io_end calls Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 29/36] cpus-common: nuke finish_safe_work Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 30/36] cpus-common: assert BQL nesting within cpu-exclusive sections Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 31/36] kvm: vmxcap: Enhance with latest features Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 32/36] HACKING: Document 'struct' keyword usage Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 33/36] migration: do not rom_reset() during incoming migration Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 34/36] test-bitmap: test set 1 bit case for bitmap_set Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 35/36] scsi: lsi: exit infinite loop while executing script (CVE-2019-12068) Paolo Bonzini
2019-08-20  6:59 ` [Qemu-devel] [PULL 36/36] x86: Intel AVX512_BF16 feature enabling Paolo Bonzini
2019-08-20  7:42 ` [Qemu-devel] [PULL 00/36] QEMU patches for 2018-08-20 no-reply
2019-08-20  9:26 ` Peter Maydell
2019-08-20 23:42 ` no-reply

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='CAFEAcA-hV9BERt=4wP0hdb7HemrzpFC1v8UrmypKFYV4DPw-Bw@mail.gmail.com' \
    --to=peter.maydell@linaro.org \
    --cc=dgilbert@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.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 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).