Skip to content

Commit

Permalink
tests/tcg/s390x: Test precise self-modifying code handling
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
iii-i authored and huth committed Aug 31, 2023
1 parent c7f41e4 commit c3513ce
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 0 deletions.
1 change: 1 addition & 0 deletions tests/tcg/s390x/Makefile.softmmu-target
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ ASM_TESTS = \
lpswe-early \
lra \
mc \
precise-smc-softmmu \
ssm-early \
stosm-early \
stpq \
Expand Down
1 change: 1 addition & 0 deletions tests/tcg/s390x/Makefile.target
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
63 changes: 63 additions & 0 deletions tests/tcg/s390x/precise-smc-softmmu.S
Original file line number Diff line number Diff line change
@@ -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 */
39 changes: 39 additions & 0 deletions tests/tcg/s390x/precise-smc-user.c
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit c3513ce

Please sign in to comment.