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 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