diff --git a/qemu/configure b/qemu/configure index ace25010..c04e4071 100755 --- a/qemu/configure +++ b/qemu/configure @@ -175,6 +175,7 @@ solaris="no" softmmu="yes" pie="" tcg="yes" +membarrier="" cpuid_h="no" avx2_opt="no" @@ -562,6 +563,10 @@ for opt do ;; --disable-stack-protector) stack_protector="no" ;; + --disable-membarrier) membarrier="no" + ;; + --enable-membarrier) membarrier="yes" + ;; *) echo "ERROR: unknown option $opt" echo "Try '$0 --help' for more information" @@ -1181,6 +1186,37 @@ if compile_prog "" "" ; then vector16=yes fi +########################################## +# check for usable membarrier system call +if test "$membarrier" = "yes"; then + have_membarrier=no + if test "$mingw32" = "yes" ; then + have_membarrier=yes + elif test "$linux" = "yes" ; then + cat > $TMPC << EOF + #include + #include + #include + #include + int main(void) { + syscall(__NR_membarrier, MEMBARRIER_CMD_QUERY, 0); + syscall(__NR_membarrier, MEMBARRIER_CMD_SHARED, 0); + exit(0); + } +EOF + if compile_prog "" "" ; then + have_membarrier=yes + fi + fi + if test "$have_membarrier" = "no"; then + feature_not_found "membarrier" "membarrier system call not available" + fi +else + # Do not enable it by default even for Mingw32, because it doesn't + # work on Wine. + membarrier=no +fi + ######################################### # See if 128-bit atomic operations are supported. @@ -1323,6 +1359,7 @@ if test -n "$sparc_cpu"; then echo "Target Sparc Arch $sparc_cpu" fi echo "PIE $pie" +echo "membarrier $membarrier" echo "TCG support $tcg" if test "$tcg" = "yes" ; then echo "TCG debug enabled $debug_tcg" @@ -1408,6 +1445,9 @@ fi if test "$bswap_h" = "yes" ; then echo "CONFIG_MACHINE_BSWAP_H=y" >> $config_host_mak fi +if test "$membarrier" = "yes" ; then + echo "CONFIG_MEMBARRIER=y" >> $config_host_mak +fi if test "$tcg" = "yes"; then echo "CONFIG_TCG=y" >> $config_host_mak if test "$tcg_interpreter" = "yes" ; then diff --git a/qemu/include/qemu/sys_membarrier.h b/qemu/include/qemu/sys_membarrier.h index 9ce7f521..316e3dc4 100644 --- a/qemu/include/qemu/sys_membarrier.h +++ b/qemu/include/qemu/sys_membarrier.h @@ -9,9 +9,19 @@ #ifndef QEMU_SYS_MEMBARRIER_H #define QEMU_SYS_MEMBARRIER_H 1 +#ifdef CONFIG_MEMBARRIER +/* Only block reordering at the compiler level in the performance-critical + * side. The slow side forces processor-level ordering on all other cores + * through a system call. + */ +extern void smp_mb_global_init(void); +extern void smp_mb_global(void); +#define smp_mb_placeholder() barrier() +#else /* Keep it simple, execute a real memory barrier on both sides. */ static inline void smp_mb_global_init(void) {} #define smp_mb_global() smp_mb() #define smp_mb_placeholder() smp_mb() +#endif #endif diff --git a/qemu/util/Makefile.objs b/qemu/util/Makefile.objs index ef48ee35..fe3e0c34 100644 --- a/qemu/util/Makefile.objs +++ b/qemu/util/Makefile.objs @@ -11,3 +11,4 @@ util-obj-y += host-utils.o util-obj-y += getauxval.o util-obj-y += log.o util-obj-y += range.o +util-obj-$(CONFIG_MEMBARRIER) += sys_membarrier.o diff --git a/qemu/util/sys_membarrier.c b/qemu/util/sys_membarrier.c new file mode 100644 index 00000000..8c8cc907 --- /dev/null +++ b/qemu/util/sys_membarrier.c @@ -0,0 +1,49 @@ +/* + * Process-global memory barriers + * + * Copyright (c) 2018 Red Hat, Inc. + * + * Author: Paolo Bonzini + */ + +#include +#include + +#ifdef CONFIG_LINUX +#include +#include + +static int +membarrier(int cmd, int flags) +{ + return syscall(__NR_membarrier, cmd, flags); +} +#endif + +void smp_mb_global(void) +{ +#if defined CONFIG_WIN32 + FlushProcessWriteBuffers(); +#elif defined CONFIG_LINUX + membarrier(MEMBARRIER_CMD_SHARED, 0); +#else +#error --enable-membarrier is not supported on this operating system. +#endif +} + +void smp_mb_global_init(void) +{ +#ifdef CONFIG_LINUX + int ret = membarrier(MEMBARRIER_CMD_QUERY, 0); + if (ret < 0) { + //error_report("This QEMU binary requires the membarrier system call."); + //error_report("Please upgrade your system to a newer version of Linux"); + exit(1); + } + if (!(ret & MEMBARRIER_CMD_SHARED)) { + //error_report("This QEMU binary requires MEMBARRIER_CMD_SHARED support."); + //error_report("Please upgrade your system to a newer version of Linux"); + exit(1); + } +#endif +}