[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 14/35] tcg: Add atomic128 helpers
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PATCH v4 14/35] tcg: Add atomic128 helpers |
Date: |
Fri, 16 Sep 2016 10:46:36 -0700 |
Force the use of cmpxchg16b on x86_64.
Wikipedia suggests that only very old AMD64 (circa 2004) did not have
this instruction. Further, it's required by Windows 8 so no new cpus
will ever omit it.
If we truely care about these, then we could check this at startup time
and then avoid executing paths that use it.
Signed-off-by: Richard Henderson <address@hidden>
---
atomic_template.h | 40 +++++++++++++++++++++++++++++++++++++++-
configure | 29 ++++++++++++++++++++++++++++-
cputlb.c | 5 +++++
include/qemu/int128.h | 6 ++++++
tcg-runtime.c | 20 +++++++++++++++++++-
tcg/tcg.h | 24 +++++++++++++++++++++++-
6 files changed, 120 insertions(+), 4 deletions(-)
diff --git a/atomic_template.h b/atomic_template.h
index d2c8a08..4fdf722 100644
--- a/atomic_template.h
+++ b/atomic_template.h
@@ -18,7 +18,11 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
-#if DATA_SIZE == 8
+#if DATA_SIZE == 16
+# define SUFFIX o
+# define DATA_TYPE Int128
+# define BSWAP bswap128
+#elif DATA_SIZE == 8
# define SUFFIX q
# define DATA_TYPE uint64_t
# define BSWAP bswap64
@@ -59,6 +63,21 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env,
target_ulong addr,
return atomic_cmpxchg__nocheck(haddr, cmpv, newv);
}
+#if DATA_SIZE >= 16
+ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
+{
+ DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
+ __atomic_load(haddr, &val, __ATOMIC_RELAXED);
+ return val;
+}
+
+void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
+ ABI_TYPE val EXTRA_ARGS)
+{
+ DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
+ __atomic_store(haddr, &val, __ATOMIC_RELAXED);
+}
+#else
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
ABI_TYPE val EXTRA_ARGS)
{
@@ -84,6 +103,8 @@ GEN_ATOMIC_HELPER(or_fetch)
GEN_ATOMIC_HELPER(xor_fetch)
#undef GEN_ATOMIC_HELPER
+#endif /* DATA SIZE >= 16 */
+
#undef END
#if DATA_SIZE > 1
@@ -101,6 +122,22 @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env,
target_ulong addr,
return BSWAP(atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv)));
}
+#if DATA_SIZE >= 16
+ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
+{
+ DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
+ __atomic_load(haddr, &val, __ATOMIC_RELAXED);
+ return BSWAP(val);
+}
+
+void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
+ ABI_TYPE val EXTRA_ARGS)
+{
+ DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
+ val = BSWAP(val);
+ __atomic_store(haddr, &val, __ATOMIC_RELAXED);
+}
+#else
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
ABI_TYPE val EXTRA_ARGS)
{
@@ -162,6 +199,7 @@ ABI_TYPE ATOMIC_NAME(add_fetch)(CPUArchState *env,
target_ulong addr,
ldo = ldn;
}
}
+#endif /* DATA_SIZE >= 16 */
#undef END
#endif /* DATA_SIZE > 1 */
diff --git a/configure b/configure
index 7d083bd..b4d3f90 100755
--- a/configure
+++ b/configure
@@ -1217,7 +1217,10 @@ case "$cpu" in
cc_i386='$(CC) -m32'
;;
x86_64)
- CPU_CFLAGS="-m64"
+ # ??? Only extremely old AMD cpus do not have cmpxchg16b.
+ # If we truly care, we should simply detect this case at
+ # runtime and generate the fallback to serial emulation.
+ CPU_CFLAGS="-m64 -mcx16"
LDFLAGS="-m64 $LDFLAGS"
cc_i386='$(CC) -m32'
;;
@@ -4456,6 +4459,26 @@ if compile_prog "" "" ; then
int128=yes
fi
+#########################################
+# See if 128-bit atomic operations are supported.
+
+atomic128=no
+if test "$int128" = "yes"; then
+ cat > $TMPC << EOF
+int main(void)
+{
+ unsigned __int128 x = 0, y = 0;
+ y = __atomic_load_16(&x, 0);
+ __atomic_store_16(&x, y, 0);
+ __atomic_compare_exchange_16(&x, &y, x, 0, 0, 0);
+ return 0;
+}
+EOF
+ if compile_prog "" "" ; then
+ atomic128=yes
+ fi
+fi
+
########################################
# check if getauxval is available.
@@ -5410,6 +5433,10 @@ if test "$int128" = "yes" ; then
echo "CONFIG_INT128=y" >> $config_host_mak
fi
+if test "$atomic128" = "yes" ; then
+ echo "CONFIG_ATOMIC128=y" >> $config_host_mak
+fi
+
if test "$getauxval" = "yes" ; then
echo "CONFIG_GETAUXVAL=y" >> $config_host_mak
fi
diff --git a/cputlb.c b/cputlb.c
index 4f2c500..845b2a7 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -690,6 +690,11 @@ static void *atomic_mmu_lookup(CPUArchState *env,
target_ulong addr,
#define DATA_SIZE 8
#include "atomic_template.h"
+#ifdef CONFIG_ATOMIC128
+#define DATA_SIZE 16
+#include "atomic_template.h"
+#endif
+
/* Second set of helpers are directly callable from TCG as helpers. */
#undef EXTRA_ARGS
diff --git a/include/qemu/int128.h b/include/qemu/int128.h
index 67440fa..261b55f 100644
--- a/include/qemu/int128.h
+++ b/include/qemu/int128.h
@@ -2,6 +2,7 @@
#define INT128_H
#ifdef CONFIG_INT128
+#include "qemu/bswap.h"
typedef __int128 Int128;
@@ -137,6 +138,11 @@ static inline void int128_subfrom(Int128 *a, Int128 b)
*a -= b;
}
+static inline Int128 bswap128(Int128 a)
+{
+ return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a)));
+}
+
#else /* !CONFIG_INT128 */
typedef struct Int128 Int128;
diff --git a/tcg-runtime.c b/tcg-runtime.c
index aa55d12..0c97cdf 100644
--- a/tcg-runtime.c
+++ b/tcg-runtime.c
@@ -118,8 +118,8 @@ static void *atomic_mmu_lookup(CPUArchState *env,
target_ulong addr,
/* Macro to call the above, with local variables from the use context. */
#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, GETPC())
-#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
#define EXTRA_ARGS
+#define ATOMIC_NAME(X) HELPER(glue(glue(atomic_ ## X, SUFFIX), END))
#define DATA_SIZE 1
#include "atomic_template.h"
@@ -133,4 +133,22 @@ static void *atomic_mmu_lookup(CPUArchState *env,
target_ulong addr,
#define DATA_SIZE 8
#include "atomic_template.h"
+/* The following is only callable from other helpers, and matches up
+ with the softmmu version. */
+
+#ifdef CONFIG_ATOMIC128
+
+#undef EXTRA_ARGS
+#undef ATOMIC_NAME
+#undef ATOMIC_MMU_LOOKUP
+
+#define EXTRA_ARGS , TCGMemOpIdx oi, uintptr_t retaddr
+#define ATOMIC_NAME(X) \
+ HELPER(glue(glue(glue(atomic_ ## X, SUFFIX), END), _mmu))
+#define ATOMIC_MMU_LOOKUP atomic_mmu_lookup(env, addr, DATA_SIZE, retaddr)
+
+#define DATA_SIZE 16
+#include "atomic_template.h"
+#endif /* CONFIG_ATOMIC128 */
+
#endif /* !CONFIG_SOFTMMU */
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5931965..bc3ea7a 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -1229,7 +1229,29 @@ GEN_ATOMIC_HELPER_ALL(xchg)
#undef GEN_ATOMIC_HELPER_ALL
#undef GEN_ATOMIC_HELPER
-
#endif /* CONFIG_SOFTMMU */
+#ifdef CONFIG_ATOMIC128
+#include "qemu/int128.h"
+
+/* These aren't really a "proper" helpers because TCG cannot manage Int128.
+ However, use the same format as the others, for use by the backends. */
+Int128 helper_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr,
+ Int128 cmpv, Int128 newv,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+Int128 helper_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr,
+ Int128 cmpv, Int128 newv,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+
+Int128 helper_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+Int128 helper_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+void helper_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+void helper_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
+ TCGMemOpIdx oi, uintptr_t retaddr);
+
+#endif /* CONFIG_ATOMIC128 */
+
#endif /* TCG_H */
--
2.5.5
- [Qemu-devel] [PATCH v4 07/35] HACK: Always enable parallel_cpus, (continued)
- [Qemu-devel] [PATCH v4 07/35] HACK: Always enable parallel_cpus, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 08/35] cputlb: Replace SHIFT with DATA_SIZE, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 10/35] cputlb: Remove includes from softmmu_template.h, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 09/35] cputlb: Move probe_write out of softmmu_template.h, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 12/35] cputlb: Tidy some macros, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 16/35] tcg: Emit barriers with parallel_cpus, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 11/35] cputlb: Move most of iotlb code out of line, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 17/35] target-i386: emulate LOCK'ed cmpxchg using cmpxchg helpers, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 19/35] target-i386: emulate LOCK'ed INC using atomic helper, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 15/35] tcg: Add CONFIG_ATOMIC64, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 14/35] tcg: Add atomic128 helpers,
Richard Henderson <=
- [Qemu-devel] [PATCH v4 24/35] target-i386: emulate XCHG using atomic helper, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 23/35] target-i386: emulate LOCK'ed BTX ops using atomic helpers, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 25/35] target-i386: remove helper_lock(), Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 26/35] tests: add atomic_add-bench, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 13/35] tcg: Add atomic helpers, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 18/35] target-i386: emulate LOCK'ed OP instructions using atomic helpers, Richard Henderson, 2016/09/16
- [Qemu-devel] [PATCH v4 20/35] target-i386: emulate LOCK'ed NOT using atomic helper, Richard Henderson, 2016/09/16