testing, gdbstub and plugin updates
- update MAINTAINERS with pointers to foo/next - add NOFETCH to help test custom docker builds - update microblaze toolchain with atomic fixes - update tsan build and documentation - don't restrict build-environment by arch unless needed - add cross-modifying code test - add tracepoints for cpu_step_atomic fallbacks - fix defaults for loongarch cross build - make check-[dco|patch] a little more verbose - fix gdbstub bug preventing aarch64_be-linux-user starting - add basic test for aarch64_be - clean up some gdbstub test scripts - fix qemu_plugin_reset -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmcaDeQACgkQ+9DbCVqe KkRTlQgAlFaP1Nxa8y6pRZSL0WY9J3Znf5e2GDnVN3nJbfx1wZg7oZ4/dWieDF/Y /9jLfMi8nDJ51tzH24PSASbHQ1xnblhuUfhRMwqAFhSwsZUb0VzdeGdq+FIyXQ5w Cy2Ubz7g81qP/x9JRCCUGFfXaM1LSizsY1lNioRsDd533WJLkvxWucmpSN3XhxHJ rEa3xI/qAcUah4G3yww47L+DmlKnJQcsihShRBC6Am2tWqxbz+1kBUaVfaVVo1if IPN+bBk4eI1EHdRRyWJSsq3nELzqW4FJ3+9V0ifsOFW2KGsnkhbl0qUxqDmW5aBb P9flEdpTfSiCbqp+IKG9vxJKuf/BGw== =5Wui -----END PGP SIGNATURE----- Merge tag 'pull-maintainer-oct-misc-241024-1' of https://gitlab.com/stsquad/qemu into staging testing, gdbstub and plugin updates - update MAINTAINERS with pointers to foo/next - add NOFETCH to help test custom docker builds - update microblaze toolchain with atomic fixes - update tsan build and documentation - don't restrict build-environment by arch unless needed - add cross-modifying code test - add tracepoints for cpu_step_atomic fallbacks - fix defaults for loongarch cross build - make check-[dco|patch] a little more verbose - fix gdbstub bug preventing aarch64_be-linux-user starting - add basic test for aarch64_be - clean up some gdbstub test scripts - fix qemu_plugin_reset # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmcaDeQACgkQ+9DbCVqe # KkRTlQgAlFaP1Nxa8y6pRZSL0WY9J3Znf5e2GDnVN3nJbfx1wZg7oZ4/dWieDF/Y # /9jLfMi8nDJ51tzH24PSASbHQ1xnblhuUfhRMwqAFhSwsZUb0VzdeGdq+FIyXQ5w # Cy2Ubz7g81qP/x9JRCCUGFfXaM1LSizsY1lNioRsDd533WJLkvxWucmpSN3XhxHJ # rEa3xI/qAcUah4G3yww47L+DmlKnJQcsihShRBC6Am2tWqxbz+1kBUaVfaVVo1if # IPN+bBk4eI1EHdRRyWJSsq3nELzqW4FJ3+9V0ifsOFW2KGsnkhbl0qUxqDmW5aBb # P9flEdpTfSiCbqp+IKG9vxJKuf/BGw== # =5Wui # -----END PGP SIGNATURE----- # gpg: Signature made Thu 24 Oct 2024 10:05:40 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 * tag 'pull-maintainer-oct-misc-241024-1' of https://gitlab.com/stsquad/qemu: plugins: fix qemu_plugin_reset MAINTAINERS: mention my plugins/next tree testing: Enhance gdb probe script tests/tcg/aarch64: Use raw strings for regexes in test-mte.py tests/tcg: enable basic testing for aarch64_be-linux-user config/targets: update aarch64_be-linux-user gdb XML list MAINTAINERS: mention my gdbstub/next tree gitlab: make check-[dco|patch] a little more verbose dockerfiles: fix default targets for debian-loongarch-cross accel/tcg: add tracepoints for cpu_loop_exit_atomic tests/tcg/x86_64: Add cross-modifying code test scripts/ci: remove architecture checks for build-environment updates docs/devel: update tsan build documentation meson: hide tsan related warnings MAINTAINERS: mention my testing/next tree tests/docker: add NOFETCH env variable for testing tests/docker: Fix microblaze atomics Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
fdf250e5a3
@ -19,10 +19,9 @@ cwd = os.getcwd()
|
|||||||
reponame = os.path.basename(cwd)
|
reponame = os.path.basename(cwd)
|
||||||
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
||||||
|
|
||||||
|
print(f"adding upstream git repo @ {repourl}")
|
||||||
subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
|
subprocess.check_call(["git", "remote", "add", "check-dco", repourl])
|
||||||
subprocess.check_call(["git", "fetch", "check-dco", "master"],
|
subprocess.check_call(["git", "fetch", "check-dco", "master"])
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL)
|
|
||||||
|
|
||||||
ancestor = subprocess.check_output(["git", "merge-base",
|
ancestor = subprocess.check_output(["git", "merge-base",
|
||||||
"check-dco/master", "HEAD"],
|
"check-dco/master", "HEAD"],
|
||||||
|
@ -19,13 +19,12 @@ cwd = os.getcwd()
|
|||||||
reponame = os.path.basename(cwd)
|
reponame = os.path.basename(cwd)
|
||||||
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
repourl = "https://gitlab.com/%s/%s.git" % (namespace, reponame)
|
||||||
|
|
||||||
|
print(f"adding upstream git repo @ {repourl}")
|
||||||
# GitLab CI environment does not give us any direct info about the
|
# GitLab CI environment does not give us any direct info about the
|
||||||
# base for the user's branch. We thus need to figure out a common
|
# base for the user's branch. We thus need to figure out a common
|
||||||
# ancestor between the user's branch and current git master.
|
# ancestor between the user's branch and current git master.
|
||||||
subprocess.check_call(["git", "remote", "add", "check-patch", repourl])
|
subprocess.check_call(["git", "remote", "add", "check-patch", repourl])
|
||||||
subprocess.check_call(["git", "fetch", "check-patch", "master"],
|
subprocess.check_call(["git", "fetch", "check-patch", "master"])
|
||||||
stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.DEVNULL)
|
|
||||||
|
|
||||||
ancestor = subprocess.check_output(["git", "merge-base",
|
ancestor = subprocess.check_output(["git", "merge-base",
|
||||||
"check-patch/master", "HEAD"],
|
"check-patch/master", "HEAD"],
|
||||||
|
@ -2985,6 +2985,7 @@ F: gdb-xml/
|
|||||||
F: tests/tcg/multiarch/gdbstub/*
|
F: tests/tcg/multiarch/gdbstub/*
|
||||||
F: scripts/feature_to_c.py
|
F: scripts/feature_to_c.py
|
||||||
F: scripts/probe-gdb-support.py
|
F: scripts/probe-gdb-support.py
|
||||||
|
T: git https://gitlab.com/stsquad/qemu gdbstub/next
|
||||||
|
|
||||||
Memory API
|
Memory API
|
||||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
@ -3708,6 +3709,7 @@ F: include/tcg/
|
|||||||
|
|
||||||
TCG Plugins
|
TCG Plugins
|
||||||
M: Alex Bennée <alex.bennee@linaro.org>
|
M: Alex Bennée <alex.bennee@linaro.org>
|
||||||
|
T: git https://gitlab.com/stsquad/qemu plugins/next
|
||||||
R: Alexandre Iooss <erdnaxe@crans.org>
|
R: Alexandre Iooss <erdnaxe@crans.org>
|
||||||
R: Mahmoud Mandour <ma.mandourr@gmail.com>
|
R: Mahmoud Mandour <ma.mandourr@gmail.com>
|
||||||
R: Pierrick Bouvier <pierrick.bouvier@linaro.org>
|
R: Pierrick Bouvier <pierrick.bouvier@linaro.org>
|
||||||
@ -4081,6 +4083,7 @@ Build and test automation
|
|||||||
-------------------------
|
-------------------------
|
||||||
Build and test automation, general continuous integration
|
Build and test automation, general continuous integration
|
||||||
M: Alex Bennée <alex.bennee@linaro.org>
|
M: Alex Bennée <alex.bennee@linaro.org>
|
||||||
|
T: git https://gitlab.com/stsquad/qemu testing/next
|
||||||
M: Philippe Mathieu-Daudé <philmd@linaro.org>
|
M: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||||
M: Thomas Huth <thuth@redhat.com>
|
M: Thomas Huth <thuth@redhat.com>
|
||||||
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
||||||
|
@ -168,6 +168,7 @@ static uint64_t load_atomic8_or_exit(CPUState *cpu, uintptr_t ra, void *pv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Ultimate fallback: re-execute in serial context. */
|
/* Ultimate fallback: re-execute in serial context. */
|
||||||
|
trace_load_atom8_or_exit_fallback(ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,6 +213,7 @@ static Int128 load_atomic16_or_exit(CPUState *cpu, uintptr_t ra, void *pv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Ultimate fallback: re-execute in serial context. */
|
/* Ultimate fallback: re-execute in serial context. */
|
||||||
|
trace_load_atom16_or_exit_fallback(ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,6 +521,7 @@ static uint64_t load_atom_8(CPUState *cpu, uintptr_t ra,
|
|||||||
if (HAVE_al8) {
|
if (HAVE_al8) {
|
||||||
return load_atom_extract_al8x2(pv);
|
return load_atom_extract_al8x2(pv);
|
||||||
}
|
}
|
||||||
|
trace_load_atom8_fallback(memop, ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
@ -563,6 +566,7 @@ static Int128 load_atom_16(CPUState *cpu, uintptr_t ra,
|
|||||||
break;
|
break;
|
||||||
case MO_64:
|
case MO_64:
|
||||||
if (!HAVE_al8) {
|
if (!HAVE_al8) {
|
||||||
|
trace_load_atom16_fallback(memop, ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
}
|
}
|
||||||
a = load_atomic8(pv);
|
a = load_atomic8(pv);
|
||||||
@ -570,6 +574,7 @@ static Int128 load_atom_16(CPUState *cpu, uintptr_t ra,
|
|||||||
break;
|
break;
|
||||||
case -MO_64:
|
case -MO_64:
|
||||||
if (!HAVE_al8) {
|
if (!HAVE_al8) {
|
||||||
|
trace_load_atom16_fallback(memop, ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
}
|
}
|
||||||
a = load_atom_extract_al8x2(pv);
|
a = load_atom_extract_al8x2(pv);
|
||||||
@ -897,6 +902,7 @@ static void store_atom_2(CPUState *cpu, uintptr_t ra,
|
|||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace_store_atom2_fallback(memop, ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,6 +967,7 @@ static void store_atom_4(CPUState *cpu, uintptr_t ra,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
trace_store_atom4_fallback(memop, ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
@ -1029,6 +1036,7 @@ static void store_atom_8(CPUState *cpu, uintptr_t ra,
|
|||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
trace_store_atom8_fallback(memop, ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,5 +1115,6 @@ static void store_atom_16(CPUState *cpu, uintptr_t ra,
|
|||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
|
trace_store_atom16_fallback(memop, ra);
|
||||||
cpu_loop_exit_atomic(cpu, ra);
|
cpu_loop_exit_atomic(cpu, ra);
|
||||||
}
|
}
|
||||||
|
@ -467,4 +467,8 @@ void plugin_gen_tb_end(CPUState *cpu, size_t num_insns)
|
|||||||
|
|
||||||
/* inject the instrumentation at the appropriate places */
|
/* inject the instrumentation at the appropriate places */
|
||||||
plugin_gen_inject(ptb);
|
plugin_gen_inject(ptb);
|
||||||
|
|
||||||
|
/* reset plugin translation state (plugin_tb is reused between blocks) */
|
||||||
|
tcg_ctx->plugin_db = NULL;
|
||||||
|
tcg_ctx->plugin_insn = NULL;
|
||||||
}
|
}
|
||||||
|
@ -12,3 +12,15 @@ memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64
|
|||||||
|
|
||||||
# translate-all.c
|
# translate-all.c
|
||||||
translate_block(void *tb, uintptr_t pc, const void *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p"
|
translate_block(void *tb, uintptr_t pc, const void *tb_code) "tb:%p, pc:0x%"PRIxPTR", tb_code:%p"
|
||||||
|
|
||||||
|
# ldst_atomicity
|
||||||
|
load_atom2_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
load_atom4_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
load_atom8_or_exit_fallback(uintptr_t ra) "ra:0x%"PRIxPTR""
|
||||||
|
load_atom8_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
load_atom16_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
load_atom16_or_exit_fallback(uintptr_t ra) "ra:0x%"PRIxPTR""
|
||||||
|
store_atom2_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
store_atom4_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
store_atom8_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
store_atom16_fallback(uint32_t memop, uintptr_t ra) "mop:0x%"PRIx32", ra:0x%"PRIxPTR""
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
#include "exec/page-protection.h"
|
#include "exec/page-protection.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "qemu/atomic128.h"
|
#include "qemu/atomic128.h"
|
||||||
#include "trace/trace-root.h"
|
#include "trace.h"
|
||||||
#include "tcg/tcg-ldst.h"
|
#include "tcg/tcg-ldst.h"
|
||||||
#include "internal-common.h"
|
#include "internal-common.h"
|
||||||
#include "internal-target.h"
|
#include "internal-target.h"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
TARGET_ARCH=aarch64
|
TARGET_ARCH=aarch64
|
||||||
TARGET_BASE_ARCH=arm
|
TARGET_BASE_ARCH=arm
|
||||||
TARGET_BIG_ENDIAN=y
|
TARGET_BIG_ENDIAN=y
|
||||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/aarch64-pauth.xml
|
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/aarch64-pauth.xml gdb-xml/aarch64-mte.xml
|
||||||
TARGET_HAS_BFLT=y
|
TARGET_HAS_BFLT=y
|
||||||
CONFIG_SEMIHOSTING=y
|
CONFIG_SEMIHOSTING=y
|
||||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||||
|
5
configure
vendored
5
configure
vendored
@ -1418,6 +1418,7 @@ probe_target_compiler() {
|
|||||||
target_arch=${1%%-*}
|
target_arch=${1%%-*}
|
||||||
case $target_arch in
|
case $target_arch in
|
||||||
aarch64) container_hosts="x86_64 aarch64" ;;
|
aarch64) container_hosts="x86_64 aarch64" ;;
|
||||||
|
aarch64_be) container_hosts="x86_64 aarch64" ;;
|
||||||
alpha) container_hosts=x86_64 ;;
|
alpha) container_hosts=x86_64 ;;
|
||||||
arm) container_hosts="x86_64 aarch64" ;;
|
arm) container_hosts="x86_64 aarch64" ;;
|
||||||
hexagon) container_hosts=x86_64 ;;
|
hexagon) container_hosts=x86_64 ;;
|
||||||
@ -1447,6 +1448,10 @@ probe_target_compiler() {
|
|||||||
case $target_arch in
|
case $target_arch in
|
||||||
# debian-all-test-cross architectures
|
# debian-all-test-cross architectures
|
||||||
|
|
||||||
|
aarch64_be)
|
||||||
|
container_image=debian-all-test-cross
|
||||||
|
container_cross_prefix=aarch64-linux-gnu-
|
||||||
|
;;
|
||||||
hppa|m68k|mips|riscv64|sparc64)
|
hppa|m68k|mips|riscv64|sparc64)
|
||||||
container_image=debian-all-test-cross
|
container_image=debian-all-test-cross
|
||||||
;;
|
;;
|
||||||
|
@ -628,20 +628,38 @@ Building and Testing with TSan
|
|||||||
It is possible to build and test with TSan, with a few additional steps.
|
It is possible to build and test with TSan, with a few additional steps.
|
||||||
These steps are normally done automatically in the docker.
|
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:
|
TSan is supported for clang and gcc.
|
||||||
|
One particularity of sanitizers is that all the code, including shared objects
|
||||||
|
dependencies, should be built with it.
|
||||||
|
In the case of TSan, any synchronization primitive from glib (GMutex for
|
||||||
|
instance) will not be recognized, and will lead to false positives.
|
||||||
|
|
||||||
|
To build a tsan version of glib:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
sed -i 's/^const/static const/g' \
|
$ git clone --depth=1 --branch=2.81.0 https://github.com/GNOME/glib.git
|
||||||
/usr/lib/llvm-10/lib/clang/10.0.0/include/sanitizer/tsan_interface.h
|
$ cd glib
|
||||||
|
$ CFLAGS="-O2 -g -fsanitize=thread" meson build
|
||||||
|
$ ninja -C build
|
||||||
|
|
||||||
To configure the build for TSan:
|
To configure the build for TSan:
|
||||||
|
|
||||||
.. code::
|
.. code::
|
||||||
|
|
||||||
../configure --enable-tsan --cc=clang-10 --cxx=clang++-10 \
|
../configure --enable-tsan \
|
||||||
--disable-werror --extra-cflags="-O0"
|
--disable-werror --extra-cflags="-O0"
|
||||||
|
|
||||||
|
When executing qemu, don't forget to point to tsan glib:
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
$ glib_dir=/path/to/glib
|
||||||
|
$ export LD_LIBRARY_PATH=$glib_dir/build/gio:$glib_dir/build/glib:$glib_dir/build/gmodule:$glib_dir/build/gobject:$glib_dir/build/gthread
|
||||||
|
# check correct version is used
|
||||||
|
$ ldd build/qemu-x86_64 | grep glib
|
||||||
|
$ qemu-system-x86_64 ...
|
||||||
|
|
||||||
The runtime behavior of TSAN is controlled by the TSAN_OPTIONS environment
|
The runtime behavior of TSAN is controlled by the TSAN_OPTIONS environment
|
||||||
variable.
|
variable.
|
||||||
|
|
||||||
|
10
meson.build
10
meson.build
@ -538,7 +538,15 @@ if get_option('tsan')
|
|||||||
prefix: '#include <sanitizer/tsan_interface.h>')
|
prefix: '#include <sanitizer/tsan_interface.h>')
|
||||||
error('Cannot enable TSAN due to missing fiber annotation interface')
|
error('Cannot enable TSAN due to missing fiber annotation interface')
|
||||||
endif
|
endif
|
||||||
qemu_cflags = ['-fsanitize=thread'] + qemu_cflags
|
tsan_warn_suppress = []
|
||||||
|
# gcc (>=11) will report constructions not supported by tsan:
|
||||||
|
# "error: ‘atomic_thread_fence’ is not supported with ‘-fsanitize=thread’"
|
||||||
|
# https://gcc.gnu.org/gcc-11/changes.html
|
||||||
|
# However, clang does not support this warning and this triggers an error.
|
||||||
|
if cc.has_argument('-Wno-tsan')
|
||||||
|
tsan_warn_suppress = ['-Wno-tsan']
|
||||||
|
endif
|
||||||
|
qemu_cflags = ['-fsanitize=thread'] + tsan_warn_suppress + qemu_cflags
|
||||||
qemu_ldflags = ['-fsanitize=thread'] + qemu_ldflags
|
qemu_ldflags = ['-fsanitize=thread'] + qemu_ldflags
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
when:
|
when:
|
||||||
- ansible_facts['distribution'] == 'Ubuntu'
|
- ansible_facts['distribution'] == 'Ubuntu'
|
||||||
- ansible_facts['distribution_version'] == '22.04'
|
- ansible_facts['distribution_version'] == '22.04'
|
||||||
- ansible_facts['architecture'] == 'aarch64' or ansible_facts['architecture'] == 'x86_64'
|
|
||||||
|
|
||||||
- name: Install packages for QEMU on Ubuntu 22.04
|
- name: Install packages for QEMU on Ubuntu 22.04
|
||||||
package:
|
package:
|
||||||
@ -47,7 +46,6 @@
|
|||||||
when:
|
when:
|
||||||
- ansible_facts['distribution'] == 'Ubuntu'
|
- ansible_facts['distribution'] == 'Ubuntu'
|
||||||
- ansible_facts['distribution_version'] == '22.04'
|
- ansible_facts['distribution_version'] == '22.04'
|
||||||
- ansible_facts['architecture'] == 'aarch64' or ansible_facts['architecture'] == 'x86_64'
|
|
||||||
|
|
||||||
- name: Install armhf cross-compile packages to build QEMU on AArch64 Ubuntu 22.04
|
- name: Install armhf cross-compile packages to build QEMU on AArch64 Ubuntu 22.04
|
||||||
package:
|
package:
|
||||||
|
@ -19,58 +19,61 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import re
|
import re
|
||||||
from subprocess import check_output, STDOUT
|
from subprocess import check_output, STDOUT, CalledProcessError
|
||||||
|
import sys
|
||||||
|
|
||||||
# mappings from gdb arch to QEMU target
|
# Mappings from gdb arch to QEMU target
|
||||||
mappings = {
|
MAP = {
|
||||||
"alpha" : "alpha",
|
"alpha" : ["alpha"],
|
||||||
"aarch64" : ["aarch64", "aarch64_be"],
|
"aarch64" : ["aarch64", "aarch64_be"],
|
||||||
"armv7": "arm",
|
"armv7": ["arm"],
|
||||||
"armv8-a" : ["aarch64", "aarch64_be"],
|
"armv8-a" : ["aarch64", "aarch64_be"],
|
||||||
"avr" : "avr",
|
"avr" : ["avr"],
|
||||||
# no hexagon in upstream gdb
|
# no hexagon in upstream gdb
|
||||||
"hppa1.0" : "hppa",
|
"hppa1.0" : ["hppa"],
|
||||||
"i386" : "i386",
|
"i386" : ["i386"],
|
||||||
"i386:x86-64" : "x86_64",
|
"i386:x86-64" : ["x86_64"],
|
||||||
"Loongarch64" : "loongarch64",
|
"Loongarch64" : ["loongarch64"],
|
||||||
"m68k" : "m68k",
|
"m68k" : ["m68k"],
|
||||||
"MicroBlaze" : "microblaze",
|
"MicroBlaze" : ["microblaze"],
|
||||||
"mips:isa64" : ["mips64", "mips64el"],
|
"mips:isa64" : ["mips64", "mips64el"],
|
||||||
"or1k" : "or1k",
|
"or1k" : ["or1k"],
|
||||||
"powerpc:common" : "ppc",
|
"powerpc:common" : ["ppc"],
|
||||||
"powerpc:common64" : ["ppc64", "ppc64le"],
|
"powerpc:common64" : ["ppc64", "ppc64le"],
|
||||||
"riscv:rv32" : "riscv32",
|
"riscv:rv32" : ["riscv32"],
|
||||||
"riscv:rv64" : "riscv64",
|
"riscv:rv64" : ["riscv64"],
|
||||||
"s390:64-bit" : "s390x",
|
"s390:64-bit" : ["s390x"],
|
||||||
"sh4" : ["sh4", "sh4eb"],
|
"sh4" : ["sh4", "sh4eb"],
|
||||||
"sparc": "sparc",
|
"sparc": ["sparc"],
|
||||||
"sparc:v8plus": "sparc32plus",
|
"sparc:v8plus": ["sparc32plus"],
|
||||||
"sparc:v9a" : "sparc64",
|
"sparc:v9a" : ["sparc64"],
|
||||||
# no tricore in upstream gdb
|
# no tricore in upstream gdb
|
||||||
"xtensa" : ["xtensa", "xtensaeb"]
|
"xtensa" : ["xtensa", "xtensaeb"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def do_probe(gdb):
|
def do_probe(gdb):
|
||||||
gdb_out = check_output([gdb,
|
try:
|
||||||
"-ex", "set architecture",
|
gdb_out = check_output([gdb,
|
||||||
"-ex", "quit"], stderr=STDOUT)
|
"-ex", "set architecture",
|
||||||
|
"-ex", "quit"], stderr=STDOUT, encoding="utf-8")
|
||||||
|
except (OSError) as e:
|
||||||
|
sys.exit(e)
|
||||||
|
except CalledProcessError as e:
|
||||||
|
sys.exit(f'{e}. Output:\n\n{e.output}')
|
||||||
|
|
||||||
m = re.search(r"Valid arguments are (.*)",
|
found_gdb_archs = re.search(r'Valid arguments are (.*)', gdb_out)
|
||||||
gdb_out.decode("utf-8"))
|
|
||||||
|
|
||||||
valid_arches = set()
|
targets = set()
|
||||||
|
if found_gdb_archs:
|
||||||
|
gdb_archs = found_gdb_archs.group(1).split(", ")
|
||||||
|
mapped_gdb_archs = [arch for arch in gdb_archs if arch in MAP]
|
||||||
|
|
||||||
if m.group(1):
|
targets = {target for arch in mapped_gdb_archs for target in MAP[arch]}
|
||||||
for arch in m.group(1).split(", "):
|
|
||||||
if arch in mappings:
|
# QEMU targets
|
||||||
mapping = mappings[arch]
|
return targets
|
||||||
if isinstance(mapping, str):
|
|
||||||
valid_arches.add(mapping)
|
|
||||||
else:
|
|
||||||
for entry in mapping:
|
|
||||||
valid_arches.add(entry)
|
|
||||||
|
|
||||||
return valid_arches
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
parser = argparse.ArgumentParser(description='Probe GDB Architectures')
|
parser = argparse.ArgumentParser(description='Probe GDB Architectures')
|
||||||
|
@ -92,10 +92,10 @@ endif
|
|||||||
docker-image-alpine: NOUSER=1
|
docker-image-alpine: NOUSER=1
|
||||||
|
|
||||||
debian-toolchain-run = \
|
debian-toolchain-run = \
|
||||||
$(if $(NOCACHE), \
|
$(if $(NOCACHE)$(NOFETCH), \
|
||||||
$(call quiet-command, \
|
$(call quiet-command, \
|
||||||
$(DOCKER_SCRIPT) build -t qemu/$1 -f $< \
|
$(DOCKER_SCRIPT) build -t qemu/$1 -f $< \
|
||||||
$(if $V,,--quiet) --no-cache \
|
$(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \
|
||||||
--registry $(DOCKER_REGISTRY) --extra-files \
|
--registry $(DOCKER_REGISTRY) --extra-files \
|
||||||
$(DOCKER_FILES_DIR)/$1.d/build-toolchain.sh, \
|
$(DOCKER_FILES_DIR)/$1.d/build-toolchain.sh, \
|
||||||
"BUILD", $1), \
|
"BUILD", $1), \
|
||||||
@ -177,6 +177,7 @@ docker:
|
|||||||
@echo ' NETWORK=$$BACKEND Enable virtual network interface with $$BACKEND.'
|
@echo ' NETWORK=$$BACKEND Enable virtual network interface with $$BACKEND.'
|
||||||
@echo ' NOUSER=1 Define to disable adding current user to containers passwd.'
|
@echo ' NOUSER=1 Define to disable adding current user to containers passwd.'
|
||||||
@echo ' NOCACHE=1 Ignore cache when build images.'
|
@echo ' NOCACHE=1 Ignore cache when build images.'
|
||||||
|
@echo ' NOFETCH=1 Do not fetch from the registry.'
|
||||||
@echo ' EXECUTABLE=<path> Include executable in image.'
|
@echo ' EXECUTABLE=<path> Include executable in image.'
|
||||||
@echo ' EXTRA_FILES="<path> [... <path>]"'
|
@echo ' EXTRA_FILES="<path> [... <path>]"'
|
||||||
@echo ' Include extra files in image.'
|
@echo ' Include extra files in image.'
|
||||||
|
@ -43,8 +43,8 @@ RUN curl -#SL https://github.com/loongson/build-tools/releases/download/2023.08.
|
|||||||
ENV PATH $PATH:/opt/cross-tools/bin
|
ENV PATH $PATH:/opt/cross-tools/bin
|
||||||
ENV LD_LIBRARY_PATH /opt/cross-tools/lib:/opt/cross-tools/loongarch64-unknown-linux-gnu/lib:$LD_LIBRARY_PATH
|
ENV LD_LIBRARY_PATH /opt/cross-tools/lib:/opt/cross-tools/loongarch64-unknown-linux-gnu/lib:$LD_LIBRARY_PATH
|
||||||
|
|
||||||
ENV QEMU_CONFIGURE_OPTS --disable-system --disable-docs --disable-tools
|
ENV QEMU_CONFIGURE_OPTS --disable-docs --disable-tools
|
||||||
ENV DEF_TARGET_LIST loongarch64-linux-user,loongarch-softmmu
|
ENV DEF_TARGET_LIST loongarch64-linux-user,loongarch64-softmmu
|
||||||
ENV MAKE /usr/bin/make
|
ENV MAKE /usr/bin/make
|
||||||
|
|
||||||
# As a final step configure the user (if env is defined)
|
# As a final step configure the user (if env is defined)
|
||||||
|
@ -10,6 +10,8 @@ TOOLCHAIN_INSTALL=/usr/local
|
|||||||
TOOLCHAIN_BIN=${TOOLCHAIN_INSTALL}/bin
|
TOOLCHAIN_BIN=${TOOLCHAIN_INSTALL}/bin
|
||||||
CROSS_SYSROOT=${TOOLCHAIN_INSTALL}/$TARGET/sys-root
|
CROSS_SYSROOT=${TOOLCHAIN_INSTALL}/$TARGET/sys-root
|
||||||
|
|
||||||
|
GCC_PATCH0_URL=https://raw.githubusercontent.com/Xilinx/meta-xilinx/refs/tags/xlnx-rel-v2024.1/meta-microblaze/recipes-devtools/gcc/gcc-12/0009-Patch-microblaze-Fix-atomic-boolean-return-value.patch
|
||||||
|
|
||||||
export PATH=${TOOLCHAIN_BIN}:$PATH
|
export PATH=${TOOLCHAIN_BIN}:$PATH
|
||||||
|
|
||||||
#
|
#
|
||||||
@ -31,6 +33,12 @@ mv gcc-11.2.0 src-gcc
|
|||||||
mv musl-1.2.2 src-musl
|
mv musl-1.2.2 src-musl
|
||||||
mv linux-5.10.70 src-linux
|
mv linux-5.10.70 src-linux
|
||||||
|
|
||||||
|
#
|
||||||
|
# Patch gcc
|
||||||
|
#
|
||||||
|
|
||||||
|
wget -O - ${GCC_PATCH0_URL} | patch -d src-gcc -p1
|
||||||
|
|
||||||
mkdir -p bld-hdr bld-binu bld-gcc bld-musl
|
mkdir -p bld-hdr bld-binu bld-gcc bld-musl
|
||||||
mkdir -p ${CROSS_SYSROOT}/usr/include
|
mkdir -p ${CROSS_SYSROOT}/usr/include
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ FROM docker.io/library/debian:11-slim
|
|||||||
# ??? The build-dep isn't working, missing a number of
|
# ??? The build-dep isn't working, missing a number of
|
||||||
# minimal build dependiencies, e.g. libmpc.
|
# minimal build dependiencies, e.g. libmpc.
|
||||||
|
|
||||||
|
RUN sed 's/^deb /deb-src /' </etc/apt/sources.list >/etc/apt/sources.list.d/deb-src.list
|
||||||
|
|
||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
|
DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
|
||||||
DEBIAN_FRONTEND=noninteractive eatmydata \
|
DEBIAN_FRONTEND=noninteractive eatmydata \
|
||||||
@ -33,6 +35,11 @@ RUN cd /root && ./build-toolchain.sh
|
|||||||
# and the build trees by restoring the original image,
|
# and the build trees by restoring the original image,
|
||||||
# then copying the built toolchain from stage 0.
|
# then copying the built toolchain from stage 0.
|
||||||
FROM docker.io/library/debian:11-slim
|
FROM docker.io/library/debian:11-slim
|
||||||
|
RUN apt update && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
|
||||||
|
DEBIAN_FRONTEND=noninteractive eatmydata \
|
||||||
|
apt install -y --no-install-recommends \
|
||||||
|
libmpc3
|
||||||
COPY --from=0 /usr/local /usr/local
|
COPY --from=0 /usr/local /usr/local
|
||||||
# As a final step configure the user (if env is defined)
|
# As a final step configure the user (if env is defined)
|
||||||
ARG USER
|
ARG USER
|
||||||
|
@ -103,9 +103,14 @@ ifeq ($(filter %-softmmu, $(TARGET)),)
|
|||||||
# then the target. If there are common tests shared between
|
# then the target. If there are common tests shared between
|
||||||
# sub-targets (e.g. ARM & AArch64) then it is up to
|
# sub-targets (e.g. ARM & AArch64) then it is up to
|
||||||
# $(TARGET_NAME)/Makefile.target to include the common parent
|
# $(TARGET_NAME)/Makefile.target to include the common parent
|
||||||
# architecture in its VPATH.
|
# architecture in its VPATH. However some targets are so minimal we
|
||||||
|
# can't even build the multiarch tests.
|
||||||
|
ifneq ($(filter $(TARGET_NAME),aarch64_be),)
|
||||||
|
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.target
|
||||||
|
else
|
||||||
-include $(SRC_PATH)/tests/tcg/multiarch/Makefile.target
|
-include $(SRC_PATH)/tests/tcg/multiarch/Makefile.target
|
||||||
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.target
|
-include $(SRC_PATH)/tests/tcg/$(TARGET_NAME)/Makefile.target
|
||||||
|
endif
|
||||||
|
|
||||||
# Add the common build options
|
# Add the common build options
|
||||||
CFLAGS+=-Wall -Werror -O0 -g -fno-strict-aliasing
|
CFLAGS+=-Wall -Werror -O0 -g -fno-strict-aliasing
|
||||||
|
@ -23,8 +23,8 @@ from sys import argv
|
|||||||
from test_gdbstub import arg_parser, main, report
|
from test_gdbstub import arg_parser, main, report
|
||||||
|
|
||||||
|
|
||||||
PATTERN_0 = "Memory tags for address 0x[0-9a-f]+ match \\(0x[0-9a-f]+\\)."
|
PATTERN_0 = r"Memory tags for address 0x[0-9a-f]+ match \(0x[0-9a-f]+\)."
|
||||||
PATTERN_1 = ".*(0x[0-9a-f]+)"
|
PATTERN_1 = r".*(0x[0-9a-f]+)"
|
||||||
|
|
||||||
|
|
||||||
def run_test():
|
def run_test():
|
||||||
|
17
tests/tcg/aarch64_be/Makefile.target
Normal file
17
tests/tcg/aarch64_be/Makefile.target
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# -*- Mode: makefile -*-
|
||||||
|
#
|
||||||
|
# A super basic AArch64 BE makefile. As we don't have any big-endian
|
||||||
|
# libc available the best we can do is a basic Hello World.
|
||||||
|
|
||||||
|
AARCH64BE_SRC=$(SRC_PATH)/tests/tcg/aarch64_be
|
||||||
|
VPATH += $(AARCH64BE_SRC)
|
||||||
|
|
||||||
|
AARCH64BE_TEST_SRCS=$(notdir $(wildcard $(AARCH64BE_SRC)/*.c))
|
||||||
|
AARCH64BE_TESTS=$(AARCH64BE_TEST_SRCS:.c=)
|
||||||
|
#MULTIARCH_TESTS = $(MULTIARCH_SRCS:.c=)
|
||||||
|
|
||||||
|
# We need to specify big-endian cflags
|
||||||
|
CFLAGS +=-mbig-endian -ffreestanding
|
||||||
|
LDFLAGS +=-nostdlib
|
||||||
|
|
||||||
|
TESTS += $(AARCH64BE_TESTS)
|
35
tests/tcg/aarch64_be/hello.c
Normal file
35
tests/tcg/aarch64_be/hello.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Non-libc syscall hello world for Aarch64 BE
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define __NR_write 64
|
||||||
|
#define __NR_exit 93
|
||||||
|
|
||||||
|
int write(int fd, char *buf, int len)
|
||||||
|
{
|
||||||
|
register int x0 __asm__("x0") = fd;
|
||||||
|
register char *x1 __asm__("x1") = buf;
|
||||||
|
register int x2 __asm__("x2") = len;
|
||||||
|
register int x8 __asm__("x8") = __NR_write;
|
||||||
|
|
||||||
|
asm volatile("svc #0" : : "r"(x0), "r"(x1), "r"(x2), "r"(x8));
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exit(int ret)
|
||||||
|
{
|
||||||
|
register int x0 __asm__("x0") = ret;
|
||||||
|
register int x8 __asm__("x8") = __NR_exit;
|
||||||
|
|
||||||
|
asm volatile("svc #0" : : "r"(x0), "r"(x8));
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _start(void)
|
||||||
|
{
|
||||||
|
write(1, "Hello World\n", 12);
|
||||||
|
exit(0);
|
||||||
|
}
|
@ -17,6 +17,7 @@ X86_64_TESTS += cmpxchg
|
|||||||
X86_64_TESTS += adox
|
X86_64_TESTS += adox
|
||||||
X86_64_TESTS += test-1648
|
X86_64_TESTS += test-1648
|
||||||
X86_64_TESTS += test-2175
|
X86_64_TESTS += test-2175
|
||||||
|
X86_64_TESTS += cross-modifying-code
|
||||||
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
|
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
|
||||||
else
|
else
|
||||||
TESTS=$(MULTIARCH_TESTS)
|
TESTS=$(MULTIARCH_TESTS)
|
||||||
@ -27,6 +28,9 @@ adox: CFLAGS=-O2
|
|||||||
run-test-i386-ssse3: QEMU_OPTS += -cpu max
|
run-test-i386-ssse3: QEMU_OPTS += -cpu max
|
||||||
run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max
|
run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max
|
||||||
|
|
||||||
|
cross-modifying-code: CFLAGS+=-pthread
|
||||||
|
cross-modifying-code: LDFLAGS+=-pthread
|
||||||
|
|
||||||
test-x86_64: LDFLAGS+=-lm -lc
|
test-x86_64: LDFLAGS+=-lm -lc
|
||||||
test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
|
test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
|
||||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||||
|
80
tests/tcg/x86_64/cross-modifying-code.c
Normal file
80
tests/tcg/x86_64/cross-modifying-code.c
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Test patching code, running in one thread, from another thread.
|
||||||
|
*
|
||||||
|
* Intel SDM calls this "cross-modifying code" and recommends a special
|
||||||
|
* sequence, which requires both threads to cooperate.
|
||||||
|
*
|
||||||
|
* Linux kernel uses a different sequence that does not require cooperation and
|
||||||
|
* involves patching the first byte with int3.
|
||||||
|
*
|
||||||
|
* Finally, there is user-mode software out there that simply uses atomics, and
|
||||||
|
* that seems to be good enough in practice. Test that QEMU has no problems
|
||||||
|
* with this as well.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void add1_or_nop(long *x);
|
||||||
|
asm(".pushsection .rwx,\"awx\",@progbits\n"
|
||||||
|
".globl add1_or_nop\n"
|
||||||
|
/* addq $0x1,(%rdi) */
|
||||||
|
"add1_or_nop: .byte 0x48, 0x83, 0x07, 0x01\n"
|
||||||
|
"ret\n"
|
||||||
|
".popsection\n");
|
||||||
|
|
||||||
|
#define THREAD_WAIT 0
|
||||||
|
#define THREAD_PATCH 1
|
||||||
|
#define THREAD_STOP 2
|
||||||
|
|
||||||
|
static void *thread_func(void *arg)
|
||||||
|
{
|
||||||
|
int val = 0x0026748d; /* nop */
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
switch (__atomic_load_n((int *)arg, __ATOMIC_SEQ_CST)) {
|
||||||
|
case THREAD_WAIT:
|
||||||
|
break;
|
||||||
|
case THREAD_PATCH:
|
||||||
|
val = __atomic_exchange_n((int *)&add1_or_nop, val,
|
||||||
|
__ATOMIC_SEQ_CST);
|
||||||
|
break;
|
||||||
|
case THREAD_STOP:
|
||||||
|
return NULL;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INITIAL 42
|
||||||
|
#define COUNT 1000000
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int command = THREAD_WAIT;
|
||||||
|
pthread_t thread;
|
||||||
|
long x = 0;
|
||||||
|
int err;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
err = pthread_create(&thread, NULL, &thread_func, &command);
|
||||||
|
assert(err == 0);
|
||||||
|
|
||||||
|
__atomic_store_n(&command, THREAD_PATCH, __ATOMIC_SEQ_CST);
|
||||||
|
for (i = 0; i < COUNT; i++) {
|
||||||
|
add1_or_nop(&x);
|
||||||
|
}
|
||||||
|
__atomic_store_n(&command, THREAD_STOP, __ATOMIC_SEQ_CST);
|
||||||
|
|
||||||
|
err = pthread_join(thread, NULL);
|
||||||
|
assert(err == 0);
|
||||||
|
|
||||||
|
assert(x >= INITIAL);
|
||||||
|
assert(x <= INITIAL + COUNT);
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user