We adjust CONFIG_ATOMIC128 and CONFIG_CMPXCHG128 with CONFIG_ATOMIC128_OPT in atomic128.h. It is difficult to tell when those changes have been applied with the ifdef we must use with CONFIG_CMPXCHG128. So instead use HAVE_CMPXCHG128, which triggers -Werror-undef when the proper header has not been included. Improves tcg_gen_atomic_cmpxchg_i128 for s390x host, which requires CONFIG_ATOMIC128_OPT. Without this we fall back to EXCP_ATOMIC to single-step 128-bit atomics, which is slow enough to cause some tests to time out. Reported-by: Thomas Huth <thuth@redhat.com> Tested-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
		
			
				
	
	
		
			116 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
 * Common Atomic Helper Functions
 | 
						|
 *
 | 
						|
 * This file should be included before the various instantiations of
 | 
						|
 * the atomic_template.h helpers.
 | 
						|
 *
 | 
						|
 * Copyright (c) 2019 Linaro
 | 
						|
 * Written by Alex Bennée <alex.bennee@linaro.org>
 | 
						|
 *
 | 
						|
 * SPDX-License-Identifier: GPL-2.0-or-later
 | 
						|
 *
 | 
						|
 * This work is licensed under the terms of the GNU GPL, version 2 or later.
 | 
						|
 * See the COPYING file in the top-level directory.
 | 
						|
 */
 | 
						|
 | 
						|
static void atomic_trace_rmw_post(CPUArchState *env, uint64_t addr,
 | 
						|
                                  MemOpIdx oi)
 | 
						|
{
 | 
						|
    qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_RW);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Atomic helpers callable from TCG.
 | 
						|
 * These have a common interface and all defer to cpu_atomic_*
 | 
						|
 * using the host return address from GETPC().
 | 
						|
 */
 | 
						|
 | 
						|
#define CMPXCHG_HELPER(OP, TYPE) \
 | 
						|
    TYPE HELPER(atomic_##OP)(CPUArchState *env, uint64_t addr,      \
 | 
						|
                             TYPE oldv, TYPE newv, uint32_t oi)     \
 | 
						|
    { return cpu_atomic_##OP##_mmu(env, addr, oldv, newv, oi, GETPC()); }
 | 
						|
 | 
						|
CMPXCHG_HELPER(cmpxchgb, uint32_t)
 | 
						|
CMPXCHG_HELPER(cmpxchgw_be, uint32_t)
 | 
						|
CMPXCHG_HELPER(cmpxchgw_le, uint32_t)
 | 
						|
CMPXCHG_HELPER(cmpxchgl_be, uint32_t)
 | 
						|
CMPXCHG_HELPER(cmpxchgl_le, uint32_t)
 | 
						|
 | 
						|
#ifdef CONFIG_ATOMIC64
 | 
						|
CMPXCHG_HELPER(cmpxchgq_be, uint64_t)
 | 
						|
CMPXCHG_HELPER(cmpxchgq_le, uint64_t)
 | 
						|
#endif
 | 
						|
 | 
						|
#if HAVE_CMPXCHG128
 | 
						|
CMPXCHG_HELPER(cmpxchgo_be, Int128)
 | 
						|
CMPXCHG_HELPER(cmpxchgo_le, Int128)
 | 
						|
#endif
 | 
						|
 | 
						|
#undef CMPXCHG_HELPER
 | 
						|
 | 
						|
Int128 HELPER(nonatomic_cmpxchgo)(CPUArchState *env, uint64_t addr,
 | 
						|
                                  Int128 cmpv, Int128 newv, uint32_t oi)
 | 
						|
{
 | 
						|
#if TCG_TARGET_REG_BITS == 32
 | 
						|
    uintptr_t ra = GETPC();
 | 
						|
    Int128 oldv;
 | 
						|
 | 
						|
    oldv = cpu_ld16_mmu(env, addr, oi, ra);
 | 
						|
    if (int128_eq(oldv, cmpv)) {
 | 
						|
        cpu_st16_mmu(env, addr, newv, oi, ra);
 | 
						|
    } else {
 | 
						|
        /* Even with comparison failure, still need a write cycle. */
 | 
						|
        probe_write(env, addr, 16, get_mmuidx(oi), ra);
 | 
						|
    }
 | 
						|
    return oldv;
 | 
						|
#else
 | 
						|
    g_assert_not_reached();
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
#define ATOMIC_HELPER(OP, TYPE) \
 | 
						|
    TYPE HELPER(glue(atomic_,OP))(CPUArchState *env, uint64_t addr,  \
 | 
						|
                                  TYPE val, uint32_t oi)                 \
 | 
						|
    { return glue(glue(cpu_atomic_,OP),_mmu)(env, addr, val, oi, GETPC()); }
 | 
						|
 | 
						|
#ifdef CONFIG_ATOMIC64
 | 
						|
#define GEN_ATOMIC_HELPERS(OP)              \
 | 
						|
    ATOMIC_HELPER(glue(OP,b), uint32_t)     \
 | 
						|
    ATOMIC_HELPER(glue(OP,w_be), uint32_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,w_le), uint32_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,l_be), uint32_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,l_le), uint32_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,q_be), uint64_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,q_le), uint64_t)
 | 
						|
#else
 | 
						|
#define GEN_ATOMIC_HELPERS(OP)              \
 | 
						|
    ATOMIC_HELPER(glue(OP,b), uint32_t)     \
 | 
						|
    ATOMIC_HELPER(glue(OP,w_be), uint32_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,w_le), uint32_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,l_be), uint32_t)  \
 | 
						|
    ATOMIC_HELPER(glue(OP,l_le), uint32_t)
 | 
						|
#endif
 | 
						|
 | 
						|
GEN_ATOMIC_HELPERS(fetch_add)
 | 
						|
GEN_ATOMIC_HELPERS(fetch_and)
 | 
						|
GEN_ATOMIC_HELPERS(fetch_or)
 | 
						|
GEN_ATOMIC_HELPERS(fetch_xor)
 | 
						|
GEN_ATOMIC_HELPERS(fetch_smin)
 | 
						|
GEN_ATOMIC_HELPERS(fetch_umin)
 | 
						|
GEN_ATOMIC_HELPERS(fetch_smax)
 | 
						|
GEN_ATOMIC_HELPERS(fetch_umax)
 | 
						|
 | 
						|
GEN_ATOMIC_HELPERS(add_fetch)
 | 
						|
GEN_ATOMIC_HELPERS(and_fetch)
 | 
						|
GEN_ATOMIC_HELPERS(or_fetch)
 | 
						|
GEN_ATOMIC_HELPERS(xor_fetch)
 | 
						|
GEN_ATOMIC_HELPERS(smin_fetch)
 | 
						|
GEN_ATOMIC_HELPERS(umin_fetch)
 | 
						|
GEN_ATOMIC_HELPERS(smax_fetch)
 | 
						|
GEN_ATOMIC_HELPERS(umax_fetch)
 | 
						|
 | 
						|
GEN_ATOMIC_HELPERS(xchg)
 | 
						|
 | 
						|
#undef ATOMIC_HELPER
 | 
						|
#undef GEN_ATOMIC_HELPERS
 |