qemu/include
Emilio G. Cota f3ced3c592 tcg: consistently access cpu->tb_jmp_cache atomically
Some code paths can lead to atomic accesses racing with memset()
on cpu->tb_jmp_cache, which can result in torn reads/writes
and is undefined behaviour in C11.

These torn accesses are unlikely to show up as bugs, but from code
inspection they seem possible. For example, tb_phys_invalidate does:
    /* remove the TB from the hash list */
    h = tb_jmp_cache_hash_func(tb->pc);
    CPU_FOREACH(cpu) {
        if (atomic_read(&cpu->tb_jmp_cache[h]) == tb) {
            atomic_set(&cpu->tb_jmp_cache[h], NULL);
        }
    }
Here atomic_set might race with a concurrent memset (such as the
ones scheduled via "unsafe" async work, e.g. tlb_flush_page) and
therefore we might end up with a torn pointer (or who knows what,
because we are under undefined behaviour).

This patch converts parallel accesses to cpu->tb_jmp_cache to use
atomic primitives, thereby bringing these accesses back to defined
behaviour. The price to pay is to potentially execute more instructions
when clearing cpu->tb_jmp_cache, but given how infrequently they happen
and the small size of the cache, the performance impact I have measured
is within noise range when booting debian-arm.

Note that under "safe async" work (e.g. do_tb_flush) we could use memset
because no other vcpus are running. However I'm keeping these accesses
atomic as well to keep things simple and to avoid confusing analysis
tools such as ThreadSanitizer.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Emilio G. Cota <cota@braap.org>
Message-Id: <1497486973-25845-1-git-send-email-cota@braap.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
2017-06-30 11:40:59 -07:00
..
block block: Add BDRV_BLOCK_EOF to bdrv_get_block_status() 2017-06-30 21:48:06 +08:00
chardev char: fix alias devices regression 2017-06-08 17:57:36 +04:00
crypto crypto: qcrypto_random_bytes() now works on windows w/o any other crypto libs 2017-05-09 14:41:47 +01:00
disas
exec gen-icount: use tcg_ctx.tcg_env instead of cpu_env 2017-06-30 11:40:59 -07:00
fpu softfloat: define floatx80_round() 2017-06-29 20:27:39 +02:00
hw spapr: Clean up DRC set_isolation_state() path 2017-06-30 14:03:32 +10:00
io trivial patches for 2017-05-10 2017-05-10 12:31:19 -04:00
libdecnumber
migration vmstate: error hint for failed equal checks 2017-06-28 11:18:44 +02:00
monitor qmp: Dumb down how we run QMP command registration 2017-03-05 09:02:10 +01:00
net slirp: add a fake NC-SI backend 2017-04-25 19:17:25 +08:00
qapi qnum: add uint type 2017-06-20 14:31:31 +02:00
qemu ps2: add and use PS2State typedef 2017-06-23 11:51:50 +02:00
qom tcg: consistently access cpu->tb_jmp_cache atomically 2017-06-30 11:40:59 -07:00
standard-headers linux-headers: update 2017-05-19 12:29:01 +02:00
sysemu migration: move only_migratable to MigrationState 2017-06-28 11:18:38 +02:00
ui gtk: use framebuffer helper functions. 2017-06-21 14:23:16 +02:00
elf.h
glib-compat.h qga: Add 'guest-get-users' command 2017-04-26 23:57:45 -05:00
qemu-common.h utils: provide size_to_str() 2017-05-17 17:30:45 +01:00
qemu-io.h
trace-tcg.h