From: "Alex Bennée" <alex.bennee@linaro.org>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: MTTCG Devel <mttcg@greensocs.com>,
QEMU Developers <qemu-devel@nongnu.org>,
Richard Henderson <rth@twiddle.net>,
Sergey Fedorov <serge.fdrv@gmail.com>,
"Emilio G. Cota" <cota@braap.org>,
Frederic Konrad <fred.konrad@greensocs.com>,
a.rigo@virtualopensystems.com
Subject: Re: [Qemu-devel] Making cputlb.c operations safe for MTTCG
Date: Tue, 02 Aug 2016 07:37:10 +0100 [thread overview]
Message-ID: <87eg677k2x.fsf@linaro.org> (raw)
In-Reply-To: <f9d2b151-3a79-547b-b8d2-db6a4650936b@redhat.com>
Paolo Bonzini <pbonzini@redhat.com> writes:
> On 26/07/2016 14:09, Alex Bennée wrote:
>>
>> As the eventual operation is the setting of a flag I'm wondering if we
>> can simply use atomic primitives to ensure we don't corrupt the lookup
>> address when setting the TLB_NOTDIRTY flag?
>
> In theory tlb_reset_dirty and tlb_set_dirty1 can use atomic_* on
> tlb_entry->addr_write, but careful because:
>
> - you need to order reads and writes to tlb_entry->addr_write and
> tlb_entry->addend properly
>
> - addr_write cannot be written atomically for 32-bit host/64-bit target.
> Probably you can use something like
>
> union {
> target_ulong addr_write;
> #if TARGET_LONG_BITS == 32
> struct { uint32_t lo_and_lfags; } addr_write_w;
> #elif defined HOST_WORDS_BIGENDIAN
> struct { uint32_t hi, lo_and_flags; } addr_write_w;
> #else
> struct { uint32_t lo_and_flags, hi; } addr_write_w;
> #endif
> };
This will work but I wonder if it is time to call it a day for 32 on 64
support? I mean all this can be worked around but I wonder if it is
worth the effort if no one actually uses this combination.
I might prepare a patch for the next dev cycle to promote discussion.
>
> IIRC "foreign" accesses only set TLB_NOTDIRTY, so they can use a cmpxchg
> on lo_and_flags (worst case you end up with an unnecessary call to
> notdirty_mem_write).
Yeah I used a cmpxchg in the RFC patch. AFAICT you wouldn't see a change
to addend that didn't involve addr_write changing. So as long as
addr_write was always the last thing written things should be fine.
>
> - When removing TLB_NOTDIRTY from a TLB entry
> (notdirty_mem_write/tlb_unprotect_code), as well as filling in a TLB
> entry without TLB_NOTDIRTY (tlb_set_page_with_attrs) you need to protect
> from a concurrent tb_alloc_page and hence take the tb_lock.
tlb_set_page_with_attrs is also only ever filled by the vCPU in question
so I just ensured the final addr_write was calculated and written in one
go at the end, after all other entries had been updated.
>
> In particular:
>
> - in notdirty_mem_write, care must be put in the ordering of
> tb_invalidate_phys_page_fast (which itself calls tlb_unprotect_code and
> takes the tb_lock in tb_invalidate_phys_page_range) and tlb_set_dirty.
> At least it seems to me that the call to tb_invalidate_phys_page_fast
> should be after the write, but that's not all. Perhaps merge this part
> of notdirty_mem_write:
>
> /* Set both VGA and migration bits for simplicity and to remove
> * the notdirty callback faster.
> */
> cpu_physical_memory_set_dirty_range(ram_addr, size,
> DIRTY_CLIENTS_NOCODE);
> /* we remove the notdirty callback only if the code has been
> flushed */
> if (!cpu_physical_memory_is_clean(ram_addr)) {
> tlb_set_dirty(current_cpu, current_cpu->mem_io_vaddr);
> }
>
> into tlb_unprotect_code?!? Or perhaps do tlb_set_dirty _first_, and
> then add back the callback if cpu_physical_memory_is_clean(ram_addr) is
> true. I haven't put much thought into it.
I'll have a closer look at these bits.
>
> - tlb_set_page_with_attrs is also hard-ish to get right, but perhaps the
> same idea of adding the callback last would work:
>
> /* First set addr_write so that concurrent tlb_reset_dirty_range
> * finds a match.
> */
> te->addr_write = address;
> if (memory_region_is_ram(section->mr)) {
> if (cpu_physical_memory_is_clean(
> memory_region_get_ram_addr(section->mr) + xlat)) {
> te->addr_write = address | TLB_NOTDIRTY;
> }
> }
Why not just write addr_write completely at the end?
>
> Paolo
>
>> Of course the TLB structure itself covers a number of values but AFAICT
>> erroneously setting TLB_NOTDIRTY on a entry that gets updated to a new
>> address wouldn't cause a problem except triggering an additional
>> slow-path write. If we are careful about the filling of the TLB entries
>> can we be sure we are always safe?
--
Alex Bennée
next prev parent reply other threads:[~2016-08-02 6:37 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-26 12:09 [Qemu-devel] Making cputlb.c operations safe for MTTCG Alex Bennée
2016-07-26 14:03 ` [Qemu-devel] [PATCH] cputlb: make tlb_reset_dirty " Alex Bennée
2016-08-01 14:54 ` [Qemu-devel] Making cputlb.c operations " Paolo Bonzini
2016-08-02 6:37 ` Alex Bennée [this message]
2016-08-02 10:26 ` Paolo Bonzini
2016-08-03 17:25 ` Richard Henderson
2016-08-03 20:56 ` Paolo Bonzini
2016-09-27 16:16 ` Paolo Bonzini
2016-09-27 22:15 ` Alex Bennée
2016-09-27 22:29 ` Emilio G. Cota
2016-09-27 23:04 ` Alex Bennée
2016-09-27 23:05 ` Richard Henderson
2016-09-27 23:32 ` Alex Bennée
2016-09-28 0:34 ` Richard Henderson
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=87eg677k2x.fsf@linaro.org \
--to=alex.bennee@linaro.org \
--cc=a.rigo@virtualopensystems.com \
--cc=cota@braap.org \
--cc=fred.konrad@greensocs.com \
--cc=mttcg@greensocs.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
--cc=serge.fdrv@gmail.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 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.