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