1*c3513ce5SIlya Leoshkevich /*
2*c3513ce5SIlya Leoshkevich * Test s390x-linux-user precise self-modifying code handling.
3*c3513ce5SIlya Leoshkevich *
4*c3513ce5SIlya Leoshkevich * SPDX-License-Identifier: GPL-2.0-or-later
5*c3513ce5SIlya Leoshkevich */
6*c3513ce5SIlya Leoshkevich #include <assert.h>
7*c3513ce5SIlya Leoshkevich #include <sys/mman.h>
8*c3513ce5SIlya Leoshkevich #include <stdint.h>
9*c3513ce5SIlya Leoshkevich #include <stdlib.h>
10*c3513ce5SIlya Leoshkevich
11*c3513ce5SIlya Leoshkevich extern __uint128_t __attribute__((__aligned__(1))) smc;
12*c3513ce5SIlya Leoshkevich extern __uint128_t __attribute__((__aligned__(1))) patch;
13*c3513ce5SIlya Leoshkevich
main(void)14*c3513ce5SIlya Leoshkevich int main(void)
15*c3513ce5SIlya Leoshkevich {
16*c3513ce5SIlya Leoshkevich char *aligned_smc = (char *)((uintptr_t)&smc & ~0xFFFULL);
17*c3513ce5SIlya Leoshkevich char *smc_end = (char *)&smc + sizeof(smc);
18*c3513ce5SIlya Leoshkevich uint64_t value = 21;
19*c3513ce5SIlya Leoshkevich int err;
20*c3513ce5SIlya Leoshkevich
21*c3513ce5SIlya Leoshkevich err = mprotect(aligned_smc, smc_end - aligned_smc,
22*c3513ce5SIlya Leoshkevich PROT_READ | PROT_WRITE | PROT_EXEC);
23*c3513ce5SIlya Leoshkevich assert(err == 0);
24*c3513ce5SIlya Leoshkevich
25*c3513ce5SIlya Leoshkevich asm("jg 0f\n" /* start a new TB */
26*c3513ce5SIlya Leoshkevich "patch: .byte 0,0,0,0,0,0\n" /* replaces padding */
27*c3513ce5SIlya Leoshkevich ".byte 0,0,0,0,0,0\n" /* replaces vstl */
28*c3513ce5SIlya Leoshkevich "agr %[value],%[value]\n" /* replaces sgr */
29*c3513ce5SIlya Leoshkevich "smc: .org . + 6\n" /* pad patched code to 16 bytes */
30*c3513ce5SIlya Leoshkevich "0: vstl %[patch],%[idx],%[smc]\n" /* start writing before TB */
31*c3513ce5SIlya Leoshkevich "sgr %[value],%[value]" /* this becomes `agr %r0,%r0` */
32*c3513ce5SIlya Leoshkevich : [smc] "=R" (smc)
33*c3513ce5SIlya Leoshkevich , [value] "+r" (value)
34*c3513ce5SIlya Leoshkevich : [patch] "v" (patch)
35*c3513ce5SIlya Leoshkevich , [idx] "r" (sizeof(patch) - 1)
36*c3513ce5SIlya Leoshkevich : "cc");
37*c3513ce5SIlya Leoshkevich
38*c3513ce5SIlya Leoshkevich return value == 42 ? EXIT_SUCCESS : EXIT_FAILURE;
39*c3513ce5SIlya Leoshkevich }
40