aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorIlya Leoshkevich <iii@linux.ibm.com>2023-08-07 13:48:21 +0200
committerThomas Huth <thuth@redhat.com>2023-08-31 19:10:01 +0200
commitc3513ce5c8736807cb4e5ff529eebadf7a82dbde (patch)
treefd2f7bde5805be8a36c5a0b4b7c87998a2139ee1 /tests
parentc7f41e4f53c4763bf1e350723a560dc3bf46e04b (diff)
downloadqemu-c3513ce5c8736807cb4e5ff529eebadf7a82dbde.zip
qemu-c3513ce5c8736807cb4e5ff529eebadf7a82dbde.tar.gz
qemu-c3513ce5c8736807cb4e5ff529eebadf7a82dbde.tar.bz2
tests/tcg/s390x: Test precise self-modifying code handling
Add small softmmu and user tests to prevent regressions. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> Message-Id: <20230807114921.438881-2-iii@linux.ibm.com> Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/tcg/s390x/Makefile.softmmu-target1
-rw-r--r--tests/tcg/s390x/Makefile.target1
-rw-r--r--tests/tcg/s390x/precise-smc-softmmu.S63
-rw-r--r--tests/tcg/s390x/precise-smc-user.c39
4 files changed, 104 insertions, 0 deletions
diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target
index 76345b6..1a1f088 100644
--- a/tests/tcg/s390x/Makefile.softmmu-target
+++ b/tests/tcg/s390x/Makefile.softmmu-target
@@ -25,6 +25,7 @@ ASM_TESTS = \
lpswe-early \
lra \
mc \
+ precise-smc-softmmu \
ssm-early \
stosm-early \
stpq \
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 9c0e70c..c650aef 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -61,6 +61,7 @@ Z13_TESTS+=locfhr
Z13_TESTS+=vcksm
Z13_TESTS+=vstl
Z13_TESTS+=vrep
+Z13_TESTS+=precise-smc-user
$(Z13_TESTS): CFLAGS+=-march=z13 -O2
TESTS+=$(Z13_TESTS)
diff --git a/tests/tcg/s390x/precise-smc-softmmu.S b/tests/tcg/s390x/precise-smc-softmmu.S
new file mode 100644
index 0000000..f7fa57d
--- /dev/null
+++ b/tests/tcg/s390x/precise-smc-softmmu.S
@@ -0,0 +1,63 @@
+/*
+ * Test s390x-softmmu precise self-modifying code handling.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+ .org 0x8e
+program_interruption_code:
+ .org 0x150
+program_old_psw:
+ .org 0x1D0 /* program new PSW */
+ .quad 0x180000000,pgm /* 64-bit mode */
+ .org 0x200 /* lowcore padding */
+ .globl _start
+_start:
+ lctlg %c0,%c0,c0
+ lghi %r0,15
+
+ /* Test 1: replace sgr with agr. */
+ lghi %r1,21
+ vl %v0,patch1
+ jg 1f /* start a new TB */
+0:
+ .org . + 6 /* pad patched code to 16 bytes */
+1:
+ vstl %v0,%r0,0b /* start writing before TB */
+ sgr %r1,%r1 /* this becomes `agr %r1,%r1` */
+ cgijne %r1,42,failure
+
+ /* Test 2: replace agr with division by zero. */
+ vl %v0,patch2
+ jg 1f /* start a new TB */
+0:
+ .org . + 6 /* pad patched code to 16 bytes */
+1:
+ vstl %v0,%r0,0b /* start writing before TB */
+ sgr %r1,%r1 /* this becomes `d %r0,zero` */
+failure:
+ lpswe failure_psw
+
+pgm:
+ chhsi program_interruption_code,0x9 /* divide exception? */
+ jne failure
+ clc program_old_psw(16),expected_old_psw2 /* correct old PSW? */
+ jne failure
+ lpswe success_psw
+
+patch1:
+ .fill 12 /* replaces padding and stpq */
+ agr %r1,%r1 /* replaces sgr */
+patch2:
+ .fill 12 /* replaces padding and stpq */
+ d %r0,zero /* replaces sgr */
+zero:
+ .long 0
+expected_old_psw2:
+ .quad 0x200180000000,failure /* cc is from addition */
+ .align 8
+c0:
+ .quad 0x60000 /* AFP, VX */
+success_psw:
+ .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */
+failure_psw:
+ .quad 0x2000000000000,0 /* disabled wait */
diff --git a/tests/tcg/s390x/precise-smc-user.c b/tests/tcg/s390x/precise-smc-user.c
new file mode 100644
index 0000000..33a5270
--- /dev/null
+++ b/tests/tcg/s390x/precise-smc-user.c
@@ -0,0 +1,39 @@
+/*
+ * Test s390x-linux-user precise self-modifying code handling.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include <assert.h>
+#include <sys/mman.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+extern __uint128_t __attribute__((__aligned__(1))) smc;
+extern __uint128_t __attribute__((__aligned__(1))) patch;
+
+int main(void)
+{
+ char *aligned_smc = (char *)((uintptr_t)&smc & ~0xFFFULL);
+ char *smc_end = (char *)&smc + sizeof(smc);
+ uint64_t value = 21;
+ int err;
+
+ err = mprotect(aligned_smc, smc_end - aligned_smc,
+ PROT_READ | PROT_WRITE | PROT_EXEC);
+ assert(err == 0);
+
+ asm("jg 0f\n" /* start a new TB */
+ "patch: .byte 0,0,0,0,0,0\n" /* replaces padding */
+ ".byte 0,0,0,0,0,0\n" /* replaces vstl */
+ "agr %[value],%[value]\n" /* replaces sgr */
+ "smc: .org . + 6\n" /* pad patched code to 16 bytes */
+ "0: vstl %[patch],%[idx],%[smc]\n" /* start writing before TB */
+ "sgr %[value],%[value]" /* this becomes `agr %r0,%r0` */
+ : [smc] "=R" (smc)
+ , [value] "+r" (value)
+ : [patch] "v" (patch)
+ , [idx] "r" (sizeof(patch) - 1)
+ : "cc");
+
+ return value == 42 ? EXIT_SUCCESS : EXIT_FAILURE;
+}