mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-plugin-160620-2' into staging
Testing and plugin updates - clear up dtc warnings - add support for --enable-tsan builds - re-enable shippable cross builds - serialise cirrus check steps - fix check-tcg plugin issues - add lockstep plugin # gpg: Signature made Tue 16 Jun 2020 14:50:09 BST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-and-plugin-160620-2: (21 commits) plugins: new lockstep plugin for debugging TCG changes tests/tcg: ensure -cpu max also used for plugin run tests/tcg: build plugin list from contents of src directory cirrus.yml: serialise make check Revert ".shippable: temporaily disable some cross builds" tests: Disable select tests under TSan, which hit TSan issue. docs: Added details on TSan to testing.rst util: Added tsan annotate for thread name. include/qemu: Added tsan.h for annotations. tests/docker: Added docker build support for TSan. thread: add tsan annotations to QemuSpin translate-all: call qemu_spin_destroy for PageDesc tcg: call qemu_spin_destroy for tb->jmp_lock qht: call qemu_spin_destroy for head buckets cputlb: destroy CPUTLB with tlb_destroy thread: add qemu_spin_destroy cpu: convert queued work to a QSIMPLEQ configure: add --enable-tsan flag + fiber annotations for coroutine-ucontext Makefile: remove old compatibility gunks Makefile: dtc: update, build the libfdt target ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+3
-3
@@ -14,7 +14,7 @@ freebsd_12_task:
|
||||
- cd build
|
||||
- ../configure || { cat config.log; exit 1; }
|
||||
- gmake -j8
|
||||
- gmake -j8 V=1 check
|
||||
- gmake V=1 check
|
||||
|
||||
macos_task:
|
||||
osx_instance:
|
||||
@@ -26,7 +26,7 @@ macos_task:
|
||||
- cd build
|
||||
- ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
- gmake check -j$(sysctl -n hw.ncpu)
|
||||
- gmake check
|
||||
|
||||
macos_xcode_task:
|
||||
osx_instance:
|
||||
@@ -39,4 +39,4 @@ macos_xcode_task:
|
||||
- cd build
|
||||
- ../configure --cc=clang || { cat config.log; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
- gmake check -j$(sysctl -n hw.ncpu)
|
||||
- gmake check
|
||||
|
||||
+6
-6
@@ -5,8 +5,8 @@ env:
|
||||
global:
|
||||
- LC_ALL=C
|
||||
matrix:
|
||||
# - IMAGE=debian-amd64
|
||||
# TARGET_LIST=x86_64-softmmu,x86_64-linux-user
|
||||
- IMAGE=debian-amd64
|
||||
TARGET_LIST=x86_64-softmmu,x86_64-linux-user
|
||||
- IMAGE=debian-win32-cross
|
||||
TARGET_LIST=arm-softmmu,i386-softmmu,lm32-softmmu
|
||||
- IMAGE=debian-win64-cross
|
||||
@@ -19,10 +19,10 @@ env:
|
||||
TARGET_LIST=aarch64-softmmu,aarch64-linux-user
|
||||
- IMAGE=debian-s390x-cross
|
||||
TARGET_LIST=s390x-softmmu,s390x-linux-user
|
||||
# - IMAGE=debian-mips-cross
|
||||
# TARGET_LIST=mips-softmmu,mipsel-linux-user
|
||||
# - IMAGE=debian-mips64el-cross
|
||||
# TARGET_LIST=mips64el-softmmu,mips64el-linux-user
|
||||
- IMAGE=debian-mips-cross
|
||||
TARGET_LIST=mips-softmmu,mipsel-linux-user
|
||||
- IMAGE=debian-mips64el-cross
|
||||
TARGET_LIST=mips64el-softmmu,mips64el-linux-user
|
||||
- IMAGE=debian-ppc64el-cross
|
||||
TARGET_LIST=ppc64-softmmu,ppc64-linux-user,ppc64abi32-linux-user
|
||||
build:
|
||||
|
||||
@@ -526,13 +526,14 @@ $(SOFTMMU_FUZZ_RULES): $(edk2-decompressed)
|
||||
$(TARGET_DIRS_RULES):
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),)
|
||||
|
||||
DTC_MAKE_ARGS=-I$(SRC_PATH)/dtc VPATH=$(SRC_PATH)/dtc -C dtc V="$(V)" LIBFDT_srcdir=$(SRC_PATH)/dtc/libfdt
|
||||
# LIBFDT_lib="": avoid breaking existing trees with objects requiring -fPIC
|
||||
DTC_MAKE_ARGS=-I$(SRC_PATH)/dtc VPATH=$(SRC_PATH)/dtc -C dtc V="$(V)" LIBFDT_lib=""
|
||||
DTC_CFLAGS=$(CFLAGS) $(QEMU_CFLAGS)
|
||||
DTC_CPPFLAGS=-I$(BUILD_DIR)/dtc -I$(SRC_PATH)/dtc -I$(SRC_PATH)/dtc/libfdt
|
||||
DTC_CPPFLAGS=-I$(SRC_PATH)/dtc/libfdt
|
||||
|
||||
.PHONY: dtc/all
|
||||
dtc/all: .git-submodule-status dtc/libfdt dtc/tests
|
||||
$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CPPFLAGS)" CFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(QEMU_LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt/libfdt.a,)
|
||||
dtc/all: .git-submodule-status dtc/libfdt
|
||||
$(call quiet-command,$(MAKE) $(DTC_MAKE_ARGS) CPPFLAGS="$(DTC_CPPFLAGS)" CFLAGS="$(DTC_CFLAGS)" LDFLAGS="$(QEMU_LDFLAGS)" ARFLAGS="$(ARFLAGS)" CC="$(CC)" AR="$(AR)" LD="$(LD)" $(SUBDIR_MAKEFLAGS) libfdt,)
|
||||
|
||||
dtc/%: .git-submodule-status
|
||||
@mkdir -p $@
|
||||
@@ -561,12 +562,6 @@ slirp/all: .git-submodule-status
|
||||
CC="$(CC)" AR="$(AR)" LD="$(LD)" RANLIB="$(RANLIB)" \
|
||||
CFLAGS="$(QEMU_CFLAGS) $(CFLAGS)" LDFLAGS="$(QEMU_LDFLAGS)")
|
||||
|
||||
# Compatibility gunk to keep make working across the rename of targets
|
||||
# for recursion, to be removed some time after 4.1.
|
||||
subdir-dtc: dtc/all
|
||||
subdir-capstone: capstone/all
|
||||
subdir-slirp: slirp/all
|
||||
|
||||
$(filter %/all, $(TARGET_DIRS_RULES)): libqemuutil.a $(common-obj-y) \
|
||||
$(qom-obj-y)
|
||||
|
||||
@@ -820,7 +815,6 @@ distclean: clean
|
||||
rm -rf $$d || exit 1 ; \
|
||||
done
|
||||
rm -Rf .sdk
|
||||
if test -f dtc/version_gen.h; then $(MAKE) $(DTC_MAKE_ARGS) clean; fi
|
||||
|
||||
KEYMAPS=da en-gb et fr fr-ch is lt no pt-br sv \
|
||||
ar de en-us fi fr-be hr it lv nl pl ru th \
|
||||
|
||||
@@ -270,6 +270,21 @@ void tlb_init(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
void tlb_destroy(CPUState *cpu)
|
||||
{
|
||||
CPUArchState *env = cpu->env_ptr;
|
||||
int i;
|
||||
|
||||
qemu_spin_destroy(&env_tlb(env)->c.lock);
|
||||
for (i = 0; i < NB_MMU_MODES; i++) {
|
||||
CPUTLBDesc *desc = &env_tlb(env)->d[i];
|
||||
CPUTLBDescFast *fast = &env_tlb(env)->f[i];
|
||||
|
||||
g_free(fast->table);
|
||||
g_free(desc->iotlb);
|
||||
}
|
||||
}
|
||||
|
||||
/* flush_all_helper: run fn across all cpus
|
||||
*
|
||||
* If the wait flag is set then the src cpu's helper will be queued as
|
||||
|
||||
@@ -384,6 +384,11 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tb_destroy(TranslationBlock *tb)
|
||||
{
|
||||
qemu_spin_destroy(&tb->jmp_lock);
|
||||
}
|
||||
|
||||
bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
|
||||
{
|
||||
TranslationBlock *tb;
|
||||
@@ -413,6 +418,7 @@ bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
|
||||
/* one-shot translation, invalidate it immediately */
|
||||
tb_phys_invalidate(tb, -1);
|
||||
tcg_tb_remove(tb);
|
||||
tb_destroy(tb);
|
||||
}
|
||||
r = true;
|
||||
}
|
||||
@@ -541,6 +547,15 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc)
|
||||
#endif
|
||||
existing = atomic_cmpxchg(lp, NULL, pd);
|
||||
if (unlikely(existing)) {
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < V_L2_SIZE; i++) {
|
||||
qemu_spin_destroy(&pd[i].lock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
g_free(pd);
|
||||
pd = existing;
|
||||
}
|
||||
@@ -1886,6 +1901,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
orig_aligned -= ROUND_UP(sizeof(*tb), qemu_icache_linesize);
|
||||
atomic_set(&tcg_ctx->code_gen_ptr, (void *)orig_aligned);
|
||||
tb_destroy(tb);
|
||||
return existing_tb;
|
||||
}
|
||||
tcg_tb_insert(tb);
|
||||
@@ -2235,6 +2251,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
tb_phys_invalidate(tb->orig_tb, -1);
|
||||
}
|
||||
tcg_tb_remove(tb);
|
||||
tb_destroy(tb);
|
||||
}
|
||||
|
||||
/* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
|
||||
|
||||
@@ -395,6 +395,7 @@ gprof="no"
|
||||
debug_tcg="no"
|
||||
debug="no"
|
||||
sanitizers="no"
|
||||
tsan="no"
|
||||
fortify_source=""
|
||||
strip_opt="yes"
|
||||
tcg_interpreter="no"
|
||||
@@ -1152,6 +1153,10 @@ for opt do
|
||||
;;
|
||||
--disable-sanitizers) sanitizers="no"
|
||||
;;
|
||||
--enable-tsan) tsan="yes"
|
||||
;;
|
||||
--disable-tsan) tsan="no"
|
||||
;;
|
||||
--enable-sparse) sparse="yes"
|
||||
;;
|
||||
--disable-sparse) sparse="no"
|
||||
@@ -1764,6 +1769,7 @@ Advanced options (experts only):
|
||||
--with-pkgversion=VERS use specified string as sub-version of the package
|
||||
--enable-debug enable common debug build options
|
||||
--enable-sanitizers enable default sanitizers
|
||||
--enable-tsan enable thread sanitizer
|
||||
--disable-strip disable stripping binaries
|
||||
--disable-werror disable compilation abort on warning
|
||||
--disable-stack-protector disable compiler-provided stack protection
|
||||
@@ -4312,7 +4318,6 @@ EOF
|
||||
mkdir -p dtc
|
||||
if [ "$pwd_is_source_path" != "y" ] ; then
|
||||
symlink "$source_path/dtc/Makefile" "dtc/Makefile"
|
||||
symlink "$source_path/dtc/scripts" "dtc/scripts"
|
||||
fi
|
||||
fdt_cflags="-I\$(SRC_PATH)/dtc/libfdt"
|
||||
fdt_ldflags="-L\$(BUILD_DIR)/dtc/libfdt"
|
||||
@@ -6221,6 +6226,30 @@ if test "$fuzzing" = "yes" ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Thread sanitizer is, for now, much noisier than the other sanitizers;
|
||||
# keep it separate until that is not the case.
|
||||
if test "$tsan" = "yes" && test "$sanitizers" = "yes"; then
|
||||
error_exit "TSAN is not supported with other sanitiziers."
|
||||
fi
|
||||
have_tsan=no
|
||||
have_tsan_iface_fiber=no
|
||||
if test "$tsan" = "yes" ; then
|
||||
write_c_skeleton
|
||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then
|
||||
have_tsan=yes
|
||||
fi
|
||||
cat > $TMPC << EOF
|
||||
#include <sanitizer/tsan_interface.h>
|
||||
int main(void) {
|
||||
__tsan_create_fiber(0);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
if compile_prog "$CPU_CFLAGS -Werror -fsanitize=thread" "" ; then
|
||||
have_tsan_iface_fiber=yes
|
||||
fi
|
||||
fi
|
||||
|
||||
##########################################
|
||||
# check for libpmem
|
||||
|
||||
@@ -6378,6 +6407,16 @@ if test "$have_asan" = "yes"; then
|
||||
"Without code annotation, the report may be inferior."
|
||||
fi
|
||||
fi
|
||||
if test "$have_tsan" = "yes" ; then
|
||||
if test "$have_tsan_iface_fiber" = "yes" ; then
|
||||
QEMU_CFLAGS="-fsanitize=thread $QEMU_CFLAGS"
|
||||
QEMU_LDFLAGS="-fsanitize=thread $QEMU_LDFLAGS"
|
||||
else
|
||||
error_exit "Cannot enable TSAN due to missing fiber annotation interface."
|
||||
fi
|
||||
elif test "$tsan" = "yes" ; then
|
||||
error_exit "Cannot enable TSAN due to missing sanitize thread interface."
|
||||
fi
|
||||
if test "$have_ubsan" = "yes"; then
|
||||
QEMU_CFLAGS="-fsanitize=undefined $QEMU_CFLAGS"
|
||||
QEMU_LDFLAGS="-fsanitize=undefined $QEMU_LDFLAGS"
|
||||
@@ -6413,7 +6452,8 @@ if test "$werror" = "yes"; then
|
||||
QEMU_CFLAGS="-Werror $QEMU_CFLAGS"
|
||||
fi
|
||||
|
||||
if test "$solaris" = "no" ; then
|
||||
# Exclude --warn-common with TSan to suppress warnings from the TSan libraries.
|
||||
if test "$solaris" = "no" && test "$tsan" = "no"; then
|
||||
if $ld --version 2>/dev/null | grep "GNU ld" >/dev/null 2>/dev/null ; then
|
||||
QEMU_LDFLAGS="-Wl,--warn-common $QEMU_LDFLAGS"
|
||||
fi
|
||||
@@ -7477,6 +7517,10 @@ if test "$have_asan_iface_fiber" = "yes" ; then
|
||||
echo "CONFIG_ASAN_IFACE_FIBER=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$have_tsan" = "yes" && test "$have_tsan_iface_fiber" = "yes" ; then
|
||||
echo "CONFIG_TSAN=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
if test "$has_environ" = "yes" ; then
|
||||
echo "CONFIG_HAS_ENVIRON=y" >> $config_host_mak
|
||||
fi
|
||||
|
||||
+8
-17
@@ -97,7 +97,7 @@ void cpu_list_remove(CPUState *cpu)
|
||||
}
|
||||
|
||||
struct qemu_work_item {
|
||||
struct qemu_work_item *next;
|
||||
QSIMPLEQ_ENTRY(qemu_work_item) node;
|
||||
run_on_cpu_func func;
|
||||
run_on_cpu_data data;
|
||||
bool free, exclusive, done;
|
||||
@@ -106,13 +106,7 @@ struct qemu_work_item {
|
||||
static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi)
|
||||
{
|
||||
qemu_mutex_lock(&cpu->work_mutex);
|
||||
if (cpu->queued_work_first == NULL) {
|
||||
cpu->queued_work_first = wi;
|
||||
} else {
|
||||
cpu->queued_work_last->next = wi;
|
||||
}
|
||||
cpu->queued_work_last = wi;
|
||||
wi->next = NULL;
|
||||
QSIMPLEQ_INSERT_TAIL(&cpu->work_list, wi, node);
|
||||
wi->done = false;
|
||||
qemu_mutex_unlock(&cpu->work_mutex);
|
||||
|
||||
@@ -306,17 +300,14 @@ void process_queued_cpu_work(CPUState *cpu)
|
||||
{
|
||||
struct qemu_work_item *wi;
|
||||
|
||||
if (cpu->queued_work_first == NULL) {
|
||||
qemu_mutex_lock(&cpu->work_mutex);
|
||||
if (QSIMPLEQ_EMPTY(&cpu->work_list)) {
|
||||
qemu_mutex_unlock(&cpu->work_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_mutex_lock(&cpu->work_mutex);
|
||||
while (cpu->queued_work_first != NULL) {
|
||||
wi = cpu->queued_work_first;
|
||||
cpu->queued_work_first = wi->next;
|
||||
if (!cpu->queued_work_first) {
|
||||
cpu->queued_work_last = NULL;
|
||||
}
|
||||
while (!QSIMPLEQ_EMPTY(&cpu->work_list)) {
|
||||
wi = QSIMPLEQ_FIRST(&cpu->work_list);
|
||||
QSIMPLEQ_REMOVE_HEAD(&cpu->work_list, node);
|
||||
qemu_mutex_unlock(&cpu->work_mutex);
|
||||
if (wi->exclusive) {
|
||||
/* Running work items outside the BQL avoids the following deadlock:
|
||||
|
||||
@@ -97,9 +97,19 @@ bool cpu_is_stopped(CPUState *cpu)
|
||||
return cpu->stopped || !runstate_is_running();
|
||||
}
|
||||
|
||||
static inline bool cpu_work_list_empty(CPUState *cpu)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
qemu_mutex_lock(&cpu->work_mutex);
|
||||
ret = QSIMPLEQ_EMPTY(&cpu->work_list);
|
||||
qemu_mutex_unlock(&cpu->work_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool cpu_thread_is_idle(CPUState *cpu)
|
||||
{
|
||||
if (cpu->stop || cpu->queued_work_first) {
|
||||
if (cpu->stop || !cpu_work_list_empty(cpu)) {
|
||||
return false;
|
||||
}
|
||||
if (cpu_is_stopped(cpu)) {
|
||||
@@ -1518,7 +1528,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
|
||||
cpu = first_cpu;
|
||||
}
|
||||
|
||||
while (cpu && !cpu->queued_work_first && !cpu->exit_request) {
|
||||
while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
|
||||
|
||||
atomic_mb_set(&tcg_current_rr_cpu, cpu);
|
||||
current_cpu = cpu;
|
||||
|
||||
@@ -397,6 +397,113 @@ list is in the ``make docker`` help text. The frequently used ones are:
|
||||
* ``DEBUG=1``: enables debug. See the previous "Debugging a Docker test
|
||||
failure" section.
|
||||
|
||||
Thread Sanitizer
|
||||
================
|
||||
|
||||
Thread Sanitizer (TSan) is a tool which can detect data races. QEMU supports
|
||||
building and testing with this tool.
|
||||
|
||||
For more information on TSan:
|
||||
|
||||
https://github.com/google/sanitizers/wiki/ThreadSanitizerCppManual
|
||||
|
||||
Thread Sanitizer in Docker
|
||||
---------------------------
|
||||
TSan is currently supported in the ubuntu2004 docker.
|
||||
|
||||
The test-tsan test will build using TSan and then run make check.
|
||||
|
||||
.. code::
|
||||
|
||||
make docker-test-tsan@ubuntu2004
|
||||
|
||||
TSan warnings under docker are placed in files located at build/tsan/.
|
||||
|
||||
We recommend using DEBUG=1 to allow launching the test from inside the docker,
|
||||
and to allow review of the warnings generated by TSan.
|
||||
|
||||
Building and Testing with TSan
|
||||
------------------------------
|
||||
|
||||
It is possible to build and test with TSan, with a few additional steps.
|
||||
These steps are normally done automatically in the docker.
|
||||
|
||||
There is a one time patch needed in clang-9 or clang-10 at this time:
|
||||
|
||||
.. code::
|
||||
|
||||
sed -i 's/^const/static const/g' \
|
||||
/usr/lib/llvm-10/lib/clang/10.0.0/include/sanitizer/tsan_interface.h
|
||||
|
||||
To configure the build for TSan:
|
||||
|
||||
.. code::
|
||||
|
||||
../configure --enable-tsan --cc=clang-10 --cxx=clang++-10 \
|
||||
--disable-werror --extra-cflags="-O0"
|
||||
|
||||
The runtime behavior of TSAN is controlled by the TSAN_OPTIONS environment
|
||||
variable.
|
||||
|
||||
More information on the TSAN_OPTIONS can be found here:
|
||||
|
||||
https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags
|
||||
|
||||
For example:
|
||||
|
||||
.. code::
|
||||
|
||||
export TSAN_OPTIONS=suppressions=<path to qemu>/tests/tsan/suppressions.tsan \
|
||||
detect_deadlocks=false history_size=7 exitcode=0 \
|
||||
log_path=<build path>/tsan/tsan_warning
|
||||
|
||||
The above exitcode=0 has TSan continue without error if any warnings are found.
|
||||
This allows for running the test and then checking the warnings afterwards.
|
||||
If you want TSan to stop and exit with error on warnings, use exitcode=66.
|
||||
|
||||
TSan Suppressions
|
||||
-----------------
|
||||
Keep in mind that for any data race warning, although there might be a data race
|
||||
detected by TSan, there might be no actual bug here. TSan provides several
|
||||
different mechanisms for suppressing warnings. In general it is recommended
|
||||
to fix the code if possible to eliminate the data race rather than suppress
|
||||
the warning.
|
||||
|
||||
A few important files for suppressing warnings are:
|
||||
|
||||
tests/tsan/suppressions.tsan - Has TSan warnings we wish to suppress at runtime.
|
||||
The comment on each supression will typically indicate why we are
|
||||
suppressing it. More information on the file format can be found here:
|
||||
|
||||
https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions
|
||||
|
||||
tests/tsan/blacklist.tsan - Has TSan warnings we wish to disable
|
||||
at compile time for test or debug.
|
||||
Add flags to configure to enable:
|
||||
|
||||
"--extra-cflags=-fsanitize-blacklist=<src path>/tests/tsan/blacklist.tsan"
|
||||
|
||||
More information on the file format can be found here under "Blacklist Format":
|
||||
|
||||
https://github.com/google/sanitizers/wiki/ThreadSanitizerFlags
|
||||
|
||||
TSan Annotations
|
||||
----------------
|
||||
include/qemu/tsan.h defines annotations. See this file for more descriptions
|
||||
of the annotations themselves. Annotations can be used to suppress
|
||||
TSan warnings or give TSan more information so that it can detect proper
|
||||
relationships between accesses of data.
|
||||
|
||||
Annotation examples can be found here:
|
||||
|
||||
https://github.com/llvm/llvm-project/tree/master/compiler-rt/test/tsan/
|
||||
|
||||
Good files to start with are: annotate_happens_before.cpp and ignore_race.cpp
|
||||
|
||||
The full set of annotations can be found here:
|
||||
|
||||
https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp
|
||||
|
||||
VM testing
|
||||
==========
|
||||
|
||||
|
||||
+1
-1
Submodule dtc updated: 88f18909db...85e5d83984
@@ -892,6 +892,7 @@ void cpu_exec_unrealizefn(CPUState *cpu)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
|
||||
tlb_destroy(cpu);
|
||||
cpu_list_remove(cpu);
|
||||
|
||||
if (cc->vmsd != NULL) {
|
||||
|
||||
@@ -370,6 +370,7 @@ static void cpu_common_initfn(Object *obj)
|
||||
cpu->nr_threads = 1;
|
||||
|
||||
qemu_mutex_init(&cpu->work_mutex);
|
||||
QSIMPLEQ_INIT(&cpu->work_list);
|
||||
QTAILQ_INIT(&cpu->breakpoints);
|
||||
QTAILQ_INIT(&cpu->watchpoints);
|
||||
|
||||
|
||||
@@ -124,6 +124,11 @@ void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
* @cpu: CPU whose TLB should be initialized
|
||||
*/
|
||||
void tlb_init(CPUState *cpu);
|
||||
/**
|
||||
* tlb_destroy - destroy a CPU's TLB
|
||||
* @cpu: CPU whose TLB should be destroyed
|
||||
*/
|
||||
void tlb_destroy(CPUState *cpu);
|
||||
/**
|
||||
* tlb_flush_page:
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
@@ -284,6 +289,9 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
|
||||
static inline void tlb_init(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
static inline void tlb_destroy(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -331,8 +331,8 @@ struct qemu_work_item;
|
||||
* @opaque: User data.
|
||||
* @mem_io_pc: Host Program Counter at which the memory was accessed.
|
||||
* @kvm_fd: vCPU file descriptor for KVM.
|
||||
* @work_mutex: Lock to prevent multiple access to queued_work_*.
|
||||
* @queued_work_first: First asynchronous work pending.
|
||||
* @work_mutex: Lock to prevent multiple access to @work_list.
|
||||
* @work_list: List of pending asynchronous work.
|
||||
* @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
|
||||
* to @trace_dstate).
|
||||
* @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
|
||||
@@ -376,7 +376,7 @@ struct CPUState {
|
||||
sigjmp_buf jmp_env;
|
||||
|
||||
QemuMutex work_mutex;
|
||||
struct qemu_work_item *queued_work_first, *queued_work_last;
|
||||
QSIMPLEQ_HEAD(, qemu_work_item) work_list;
|
||||
|
||||
CPUAddressSpace *cpu_ases;
|
||||
int num_ases;
|
||||
|
||||
+37
-1
@@ -206,6 +206,10 @@ void qemu_thread_atexit_add(struct Notifier *notifier);
|
||||
*/
|
||||
void qemu_thread_atexit_remove(struct Notifier *notifier);
|
||||
|
||||
#ifdef CONFIG_TSAN
|
||||
#include <sanitizer/tsan_interface.h>
|
||||
#endif
|
||||
|
||||
struct QemuSpin {
|
||||
int value;
|
||||
};
|
||||
@@ -213,20 +217,46 @@ struct QemuSpin {
|
||||
static inline void qemu_spin_init(QemuSpin *spin)
|
||||
{
|
||||
__sync_lock_release(&spin->value);
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_create(spin, __tsan_mutex_not_static);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* const parameter because the only purpose here is the TSAN annotation */
|
||||
static inline void qemu_spin_destroy(const QemuSpin *spin)
|
||||
{
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_destroy((void *)spin, __tsan_mutex_not_static);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void qemu_spin_lock(QemuSpin *spin)
|
||||
{
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_pre_lock(spin, 0);
|
||||
#endif
|
||||
while (unlikely(__sync_lock_test_and_set(&spin->value, true))) {
|
||||
while (atomic_read(&spin->value)) {
|
||||
cpu_relax();
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_post_lock(spin, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool qemu_spin_trylock(QemuSpin *spin)
|
||||
{
|
||||
return __sync_lock_test_and_set(&spin->value, true);
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_pre_lock(spin, __tsan_mutex_try_lock);
|
||||
#endif
|
||||
bool busy = __sync_lock_test_and_set(&spin->value, true);
|
||||
#ifdef CONFIG_TSAN
|
||||
unsigned flags = __tsan_mutex_try_lock;
|
||||
flags |= busy ? __tsan_mutex_try_lock_failed : 0;
|
||||
__tsan_mutex_post_lock(spin, flags, 0);
|
||||
#endif
|
||||
return busy;
|
||||
}
|
||||
|
||||
static inline bool qemu_spin_locked(QemuSpin *spin)
|
||||
@@ -236,7 +266,13 @@ static inline bool qemu_spin_locked(QemuSpin *spin)
|
||||
|
||||
static inline void qemu_spin_unlock(QemuSpin *spin)
|
||||
{
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_pre_unlock(spin, 0);
|
||||
#endif
|
||||
__sync_lock_release(&spin->value);
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_post_unlock(spin, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct QemuLockCnt {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef QEMU_TSAN_H
|
||||
#define QEMU_TSAN_H
|
||||
/*
|
||||
* tsan.h
|
||||
*
|
||||
* This file defines macros used to give ThreadSanitizer
|
||||
* additional information to help suppress warnings.
|
||||
* This is necessary since TSan does not provide a header file
|
||||
* for these annotations. The standard way to include these
|
||||
* is via the below macros.
|
||||
*
|
||||
* Annotation examples can be found here:
|
||||
* https://github.com/llvm/llvm-project/tree/master/compiler-rt/test/tsan
|
||||
* annotate_happens_before.cpp or ignore_race.cpp are good places to start.
|
||||
*
|
||||
* The full set of annotations can be found here in tsan_interface_ann.cpp.
|
||||
* https://github.com/llvm/llvm-project/blob/master/compiler-rt/lib/tsan/rtl/
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_TSAN
|
||||
/*
|
||||
* Informs TSan of a happens before/after relationship.
|
||||
*/
|
||||
#define QEMU_TSAN_ANNOTATE_HAPPENS_BEFORE(addr) \
|
||||
AnnotateHappensBefore(__FILE__, __LINE__, (void *)(addr))
|
||||
#define QEMU_TSAN_ANNOTATE_HAPPENS_AFTER(addr) \
|
||||
AnnotateHappensAfter(__FILE__, __LINE__, (void *)(addr))
|
||||
/*
|
||||
* Gives TSan more information about thread names it can report the
|
||||
* name of the thread in the warning report.
|
||||
*/
|
||||
#define QEMU_TSAN_ANNOTATE_THREAD_NAME(name) \
|
||||
AnnotateThreadName(__FILE__, __LINE__, (void *)(name))
|
||||
/*
|
||||
* Allows defining a region of code on which TSan will not record memory READS.
|
||||
* This has the effect of disabling race detection for this section of code.
|
||||
*/
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_READS_BEGIN() \
|
||||
AnnotateIgnoreReadsBegin(__FILE__, __LINE__)
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_READS_END() \
|
||||
AnnotateIgnoreReadsEnd(__FILE__, __LINE__)
|
||||
/*
|
||||
* Allows defining a region of code on which TSan will not record memory
|
||||
* WRITES. This has the effect of disabling race detection for this
|
||||
* section of code.
|
||||
*/
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN() \
|
||||
AnnotateIgnoreWritesBegin(__FILE__, __LINE__)
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_END() \
|
||||
AnnotateIgnoreWritesEnd(__FILE__, __LINE__)
|
||||
#else
|
||||
#define QEMU_TSAN_ANNOTATE_HAPPENS_BEFORE(addr)
|
||||
#define QEMU_TSAN_ANNOTATE_HAPPENS_AFTER(addr)
|
||||
#define QEMU_TSAN_ANNOTATE_THREAD_NAME(name)
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_READS_BEGIN()
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_READS_END()
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN()
|
||||
#define QEMU_TSAN_ANNOTATE_IGNORE_WRITES_END()
|
||||
#endif
|
||||
|
||||
void AnnotateHappensBefore(const char *f, int l, void *addr);
|
||||
void AnnotateHappensAfter(const char *f, int l, void *addr);
|
||||
void AnnotateThreadName(const char *f, int l, char *name);
|
||||
void AnnotateIgnoreReadsBegin(const char *f, int l);
|
||||
void AnnotateIgnoreReadsEnd(const char *f, int l);
|
||||
void AnnotateIgnoreWritesBegin(const char *f, int l);
|
||||
void AnnotateIgnoreWritesEnd(const char *f, int l);
|
||||
#endif
|
||||
@@ -819,6 +819,7 @@ void tcg_pool_reset(TCGContext *s);
|
||||
TranslationBlock *tcg_tb_alloc(TCGContext *s);
|
||||
|
||||
void tcg_region_init(void);
|
||||
void tb_destroy(TranslationBlock *tb);
|
||||
void tcg_region_reset_all(void);
|
||||
|
||||
size_t tcg_code_size(void);
|
||||
|
||||
@@ -502,6 +502,14 @@ size_t tcg_nb_tbs(void)
|
||||
return nb_tbs;
|
||||
}
|
||||
|
||||
static gboolean tcg_region_tree_traverse(gpointer k, gpointer v, gpointer data)
|
||||
{
|
||||
TranslationBlock *tb = v;
|
||||
|
||||
tb_destroy(tb);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void tcg_region_tree_reset_all(void)
|
||||
{
|
||||
size_t i;
|
||||
@@ -510,6 +518,7 @@ static void tcg_region_tree_reset_all(void)
|
||||
for (i = 0; i < region.n; i++) {
|
||||
struct tcg_region_tree *rt = region_trees + i * tree_size;
|
||||
|
||||
g_tree_foreach(rt->tree, tcg_region_tree_traverse, NULL);
|
||||
/* Increment the refcount first so that destroy acts as a reset */
|
||||
g_tree_ref(rt->tree);
|
||||
g_tree_destroy(rt->tree);
|
||||
|
||||
@@ -55,7 +55,6 @@ SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
|
||||
|
||||
check-unit-y += tests/check-qdict$(EXESUF)
|
||||
check-unit-y += tests/check-block-qdict$(EXESUF)
|
||||
check-unit-$(CONFIG_SOFTMMU) += tests/test-char$(EXESUF)
|
||||
check-unit-y += tests/check-qnum$(EXESUF)
|
||||
check-unit-y += tests/check-qstring$(EXESUF)
|
||||
check-unit-y += tests/check-qlist$(EXESUF)
|
||||
@@ -108,7 +107,6 @@ check-unit-y += tests/test-qht$(EXESUF)
|
||||
check-unit-y += tests/test-qht-par$(EXESUF)
|
||||
check-unit-y += tests/test-bitops$(EXESUF)
|
||||
check-unit-y += tests/test-bitcnt$(EXESUF)
|
||||
check-unit-$(CONFIG_SOFTMMU) += tests/test-qdev-global-props$(EXESUF)
|
||||
check-unit-y += tests/check-qom-interface$(EXESUF)
|
||||
check-unit-y += tests/check-qom-proplist$(EXESUF)
|
||||
check-unit-y += tests/test-qemu-opts$(EXESUF)
|
||||
@@ -123,9 +121,16 @@ check-speed-$(CONFIG_BLOCK) += tests/benchmark-crypto-cipher$(EXESUF)
|
||||
check-unit-$(CONFIG_BLOCK) += tests/test-crypto-secret$(EXESUF)
|
||||
check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlscredsx509$(EXESUF)
|
||||
check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_GNUTLS)) += tests/test-crypto-tlssession$(EXESUF)
|
||||
ifndef CONFIG_TSAN
|
||||
# Some tests: test-char, test-qdev-global-props, and test-qga,
|
||||
# are not runnable under TSan due to a known issue.
|
||||
# https://github.com/google/sanitizers/issues/1116
|
||||
check-unit-$(CONFIG_SOFTMMU) += tests/test-char$(EXESUF)
|
||||
check-unit-$(CONFIG_SOFTMMU) += tests/test-qdev-global-props$(EXESUF)
|
||||
ifneq (,$(findstring qemu-ga,$(TOOLS)))
|
||||
check-unit-$(call land,$(CONFIG_LINUX),$(CONFIG_VIRTIO_SERIAL)) += tests/test-qga$(EXESUF)
|
||||
endif
|
||||
endif
|
||||
check-unit-$(CONFIG_SOFTMMU) += tests/test-timed-average$(EXESUF)
|
||||
check-unit-$(call land,$(CONFIG_SOFTMMU),$(CONFIG_INOTIFY1)) += tests/test-util-filemonitor$(EXESUF)
|
||||
check-unit-$(CONFIG_SOFTMMU) += tests/test-util-sockets$(EXESUF)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM fedora:30
|
||||
FROM fedora:32
|
||||
|
||||
# Please keep this list sorted alphabetically
|
||||
ENV PACKAGES \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user