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