diff options
author | Ilya Leoshkevich <iii@linux.ibm.com> | 2022-03-14 11:42:32 +0100 |
---|---|---|
committer | Thomas Huth <thuth@redhat.com> | 2022-03-16 08:43:10 +0100 |
commit | c587bddb530c2f48b1a43b6df5028f78c39c81c3 (patch) | |
tree | 8d7fe83342cc396a22283c764ad04364306c6a5b /tests | |
parent | 16ed5f14215b20c8dc49b96e2149032ba3238beb (diff) |
tests/tcg/s390x: Test BRASL and BRCL with large negative offsets
Add a small test in order to prevent regressions.
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Message-Id: <20220314104232.675863-4-iii@linux.ibm.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/tcg/s390x/Makefile.target | 1 | ||||
-rw-r--r-- | tests/tcg/s390x/branch-relative-long.c | 68 |
2 files changed, 69 insertions, 0 deletions
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 7aa502a557..f0d474a245 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -15,6 +15,7 @@ TESTS+=mvc TESTS+=shift TESTS+=trap TESTS+=signals-s390x +TESTS+=branch-relative-long ifneq ($(HAVE_GDB_BIN),) GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py diff --git a/tests/tcg/s390x/branch-relative-long.c b/tests/tcg/s390x/branch-relative-long.c new file mode 100644 index 0000000000..94219afcad --- /dev/null +++ b/tests/tcg/s390x/branch-relative-long.c @@ -0,0 +1,68 @@ +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <sys/mman.h> + +#define DEFINE_ASM(_name, _code) \ + extern const char _name[]; \ + extern const char _name ## _end[]; \ + asm(" .globl " #_name "\n" \ + #_name ":\n" \ + " " _code "\n" \ + " .globl " #_name "_end\n" \ + #_name "_end:\n"); + +DEFINE_ASM(br_r14, "br %r14"); +DEFINE_ASM(brasl_r0, "brasl %r0,.-0x100000000"); +DEFINE_ASM(brcl_0xf, "brcl 0xf,.-0x100000000"); + +struct test { + const char *code; + const char *code_end; +}; + +static const struct test tests[] = { + { + .code = brasl_r0, + .code_end = brasl_r0_end, + }, + { + .code = brcl_0xf, + .code_end = brcl_0xf_end, + }, +}; + +int main(void) +{ + unsigned char *buf; + size_t length = 0; + size_t i; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + size_t test_length = 0x100000000 + (tests[i].code_end - tests[i].code); + + if (test_length > length) { + length = test_length; + } + } + + buf = mmap(NULL, length, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0); + if (buf == MAP_FAILED) { + perror("SKIP: mmap() failed"); + return 0; + } + + memcpy(buf, br_r14, br_r14_end - br_r14); + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + void (*code)(void) = (void *)(buf + 0x100000000); + + memcpy(code, tests[i].code, tests[i].code_end - tests[i].code); + code(); + memset(code, 0, tests[i].code_end - tests[i].code); + } + + munmap(buf, length); + + return 0; +} |