qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] Atomic Instructions - comments please


From: Peter Maydell
Subject: Re: [Qemu-devel] Atomic Instructions - comments please
Date: Mon, 15 Dec 2014 14:09:44 +0000

On 15 December 2014 at 13:16, Paolo Bonzini <address@hidden> wrote:
> If not, it should not need any change to the memory API; you can do it
> entirely within cputlb.c, roughly the same as the handling of
> TLB_NOTDIRTY.  It also marks pages as I/O, but only internally within TCG.

Speaking of TLB_NOTDIRTY, I just wrote up a summary of how that
works for a private email, so I figured I might as well send it
here too so it's in the qemu-devel mail archives; it's probably
not new information to anybody involved in this immediate
conversation.

How we arrange to throw away cached translations when the guest
writes to that part of memory:

 * we have two data structures effectively tracking dirty status:
   (1) there are a set of bitmaps which track different kinds of
   dirtiness (the DIRTY_MEMORY_*); the functions for manipulating
   these are mostly in ram_addr.h. One of the bitmaps is for
   DIRTY_MEMORY_CODE.
   (2) where we have an entry in the QEMU TLB for a page which
   is backed by host RAM, we may set the TLB_NOTDIRTY bit in
   the addr_write TLB entry field (TLB_NOTDIRTY is one of
   several low order bits that can be set in what is otherwise
   a page-aligned virtual address in the TLB structure. TLB_MMIO
   is another, indicating that the entry is not RAM at all.)
   TLB entries come and go, but the bitmaps cover all of physical
   RAM. When a TLB entry is present then the NOTDIRTY flag should
   be just a cache for "at least one of the dirty bitmaps says
   this page is not dirty".
 * when we generate code we call tlb_protect_code() (from
   tb_alloc_page()): this calls cpu_physical_memory_reset_dirty(),
   which both updates the dirty bitmap data structure (marking
   the region as clean in the DIRTY_MEMORY_CODE bitmap) and also
   calls cpu_tlb_reset_dirty_all() to OR in the TLB_NOTDIRTY
   flag for any present TLB entries in the range
 * when we add an entry to the TLB, tlb_set_page() will OR in
   the TLB_NOTDIRTY bit if the bitmap says this is clean memory,
   so the two structures stay in sync
 * tlb_set_page() also calls memory_region_section_get_iotlb()
   to get an iotlb entry for this RAM, which is what will be
   used on the slow path. For RAM this will be io_mem_notdirty.
 * if the guest attempts a read, we don't do anything special
   because this uses addr_read, not addr_write
 * for a guest write, the generated code will look at addr_write;
   it takes the fast path if the low order bits are clear
   (indicating dirty host RAM). Otherwise we take the slow
   path (clean RAM, MMIO, nothing present, etc etc).
 * we then follow the slow path without special casing RAM,
   which means we'll use the iotlb entry set up when the TLB
   entry was populated, which is io_mem_notdirty.
 * notdirty_mem_write() will invalidate the cached TBs if
   the DIRTY_MEMORY_CODE bitmap says this memory is clean,
   and do the access the slow way. We then mark the TLB entry
   as dirty by calling tlb_set_dirty, so next time we'll take
   the fast path. (There's an optimisation wrinkle here:
   tb_invalidate_phys_page_fast() is complicated because it
   tries to avoid simply nuking every TB in the page. So it
   might need to keep accesses on the slow path. It only calls
   tlb_unprotect_code_phys() to update the DIRTY_MEMORY_CODE
   bitmap if every TB on the page has been invalidated. This
   is why notdirty_mem_write()'s call to tlb_set_dirty() is
   conditional.)
 * writes to already-dirty memory can take the fast path,
   which just writes to the host RAM without calling out
   or checking any dirty bits.

Note that for linux-user mode the mechanism is totally
different, because we don't have a softmmu TLB data structure;
instead we use mprotect to write-protect the page, and then
in the SIGSEGV handler we may throw away cached TBs before
un-write-protecting it.

-- PMM



reply via email to

[Prev in Thread] Current Thread [Next in Thread]