xref: /qemu/tests/tcg/s390x/precise-smc-user.c (revision 5e6f3db2)
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 
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