From: Richard Henderson <richard.hender...@linaro.org> Requires gcc 10 for -mbranch-protection=standard.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> Message-Id: <20200520023139.9812-3-richard.hender...@linaro.org> [AJB: add CROSS_CC_HAS_ARMV8_BTI check] Signed-off-by: Alex Bennée <alex.ben...@linaro.org> --- tests/tcg/aarch64/bti-1.c | 62 +++++++++++++++++++++++++++++++ tests/tcg/aarch64/bti-crt.inc.c | 51 +++++++++++++++++++++++++ tests/tcg/aarch64/Makefile.target | 9 +++++ tests/tcg/configure.sh | 4 ++ 4 files changed, 126 insertions(+) create mode 100644 tests/tcg/aarch64/bti-1.c create mode 100644 tests/tcg/aarch64/bti-crt.inc.c diff --git a/tests/tcg/aarch64/bti-1.c b/tests/tcg/aarch64/bti-1.c new file mode 100644 index 00000000000..61924f0d7a4 --- /dev/null +++ b/tests/tcg/aarch64/bti-1.c @@ -0,0 +1,62 @@ +/* + * Branch target identification, basic notskip cases. + */ + +#include "bti-crt.inc.c" + +static void skip2_sigill(int sig, siginfo_t *info, ucontext_t *uc) +{ + uc->uc_mcontext.pc += 8; + uc->uc_mcontext.pstate = 1; +} + +#define NOP "nop" +#define BTI_N "hint #32" +#define BTI_C "hint #34" +#define BTI_J "hint #36" +#define BTI_JC "hint #38" + +#define BTYPE_1(DEST) \ + asm("mov %0,#1; adr x16, 1f; br x16; 1: " DEST "; mov %0,#0" \ + : "=r"(skipped) : : "x16") + +#define BTYPE_2(DEST) \ + asm("mov %0,#1; adr x16, 1f; blr x16; 1: " DEST "; mov %0,#0" \ + : "=r"(skipped) : : "x16", "x30") + +#define BTYPE_3(DEST) \ + asm("mov %0,#1; adr x15, 1f; br x15; 1: " DEST "; mov %0,#0" \ + : "=r"(skipped) : : "x15") + +#define TEST(WHICH, DEST, EXPECT) \ + do { WHICH(DEST); fail += skipped ^ EXPECT; } while (0) + + +int main() +{ + int fail = 0; + int skipped; + + /* Signal-like with SA_SIGINFO. */ + signal_info(SIGILL, skip2_sigill); + + TEST(BTYPE_1, NOP, 1); + TEST(BTYPE_1, BTI_N, 1); + TEST(BTYPE_1, BTI_C, 0); + TEST(BTYPE_1, BTI_J, 0); + TEST(BTYPE_1, BTI_JC, 0); + + TEST(BTYPE_2, NOP, 1); + TEST(BTYPE_2, BTI_N, 1); + TEST(BTYPE_2, BTI_C, 0); + TEST(BTYPE_2, BTI_J, 1); + TEST(BTYPE_2, BTI_JC, 0); + + TEST(BTYPE_3, NOP, 1); + TEST(BTYPE_3, BTI_N, 1); + TEST(BTYPE_3, BTI_C, 1); + TEST(BTYPE_3, BTI_J, 0); + TEST(BTYPE_3, BTI_JC, 0); + + return fail; +} diff --git a/tests/tcg/aarch64/bti-crt.inc.c b/tests/tcg/aarch64/bti-crt.inc.c new file mode 100644 index 00000000000..ef7831ad76a --- /dev/null +++ b/tests/tcg/aarch64/bti-crt.inc.c @@ -0,0 +1,51 @@ +/* + * Minimal user-environment for testing BTI. + * + * Normal libc is not built with BTI support enabled, and so could + * generate a BTI TRAP before ever reaching main. + */ + +#include <stdlib.h> +#include <signal.h> +#include <ucontext.h> +#include <asm/unistd.h> + +int main(void); + +void _start(void) +{ + exit(main()); +} + +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(); +} + +/* + * Irritatingly, the user API struct sigaction does not match the + * kernel API struct sigaction. So for simplicity, isolate the + * kernel ABI here, and make this act like signal. + */ +void signal_info(int sig, void (*fn)(int, siginfo_t *, ucontext_t *)) +{ + struct kernel_sigaction { + void (*handler)(int, siginfo_t *, ucontext_t *); + unsigned long flags; + unsigned long restorer; + unsigned long mask; + } sa = { fn, SA_SIGINFO, 0, 0 }; + + register int x0 __asm__("x0") = sig; + register void *x1 __asm__("x1") = &sa; + register void *x2 __asm__("x2") = 0; + register int x3 __asm__("x3") = sizeof(unsigned long); + register int x8 __asm__("x8") = __NR_rt_sigaction; + + asm volatile("svc #0" + : : "r"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x8) : "memory"); +} diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target index 312f36cde5f..8d39f4b2f45 100644 --- a/tests/tcg/aarch64/Makefile.target +++ b/tests/tcg/aarch64/Makefile.target @@ -24,6 +24,15 @@ run-pauth-%: QEMU_OPTS += -cpu max pauth-%: CFLAGS += -march=armv8.3-a endif +# We need binutils-2.32 to link this test case without warnings. +# And if we know that we have 2.32, we also don't need the linker script. +# In the meantime, disable the test by default. +ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_ARMV8_BTI),) +AARCH64_TESTS += bti-1 +bti-%: CFLAGS += -mbranch-protection=standard +bti-1: LDFLAGS += -nostdlib +endif + # Semihosting smoke test for linux-user AARCH64_TESTS += semihosting run-semihosting: semihosting diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index 2326f978562..ebfe3e2ce5a 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -231,6 +231,10 @@ for target in $target_list; do -march=armv8.3-a -o $TMPE $TMPC; then echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak fi + if do_compiler "$target_compiler" $target_compiler_cflags \ + -mbranch-protection=standard -o $TMPE $TMPC; then + echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak + fi ;; esac -- 2.20.1