qemu-system-aarch64 asserts trying to execute STXP on hosts without HAVE_CMPXCHG128
If the host system doesn't HAVE_CMPXCHG128, the code in target/arm/translate-a64.c in gen_store_exclusive() that handles STXP generates bad code that ends up causing QEMU to assert. In particular, this happens with the xlnx-versal-virt 'make check-acceptance' test if you are building using clang with the sanitizer enabled. My configure arguments are:
'../../configure' '--cc=clang' '--cxx=clang++' '--with-pkgversion=pm215' '--extra-cflags=-fsanitize=undefined -fno-sanitize=shift-base' '--enable-debug' '--target-list=aarch64-softmmu'
with clang 10.0.0-4ubuntu1 (the Ubuntu 20.04 focal one).
The cut-down version of the acceptance test's command line is:
./build/clang-assert/qemu-system-aarch64 -display none -machine xlnx-versal-virt -serial stdio -kernel /home/petmay01/avocado/data/cache/by_location/a7a30e5f9475bb545b4b0f00b9b3b04589cb299b/linux -initrd /home/petmay01/avocado/data/cache/by_location/a7a30e5f9475bb545b4b0f00b9b3b04589cb299b/initrd.gz
qemu-system-aarch64: ../../accel/tcg/cpu-exec.c:867: void cpu_loop_exec_tb(CPUState *, TranslationBlock *, TranslationBlock **, int *): Assertion `icount_enabled()' failed.
Aborted (core dumped)
(obviously you'll need to look in the check-acceptance log to find the paths to the kernel and initrd on your system.)
The reason for the assertion is that for the "two 64-bit values" case of gen_store_exclusive(), if !HAVE_CMPXCHG128 we call gen_helper_exit_atomic() and set is_jmp to DISAS_NORETURN. However, this has forgotten that we already emitted a brcond to jump over this if we failed to get the exclusive. The upshot is that because of DISAS_NORETURN we don't generate code for "exit TB for end of instruction" and instead execution falls through into the TB_EXIT_REQUESTED exit generated by gen_tb_end(). The assert then happens because we leave the TB with TB_EXIT_REQUESTED but not because of either an interrupt or because we're using icount.
Haven't thought about the fix yet but it might be as simple as not setting is_jmp...