1 /* 2 * Test modifying code using the MVC instruction. 3 * 4 * SPDX-License-Identifier: GPL-2.0-or-later 5 */ 6 7 #include <minilib.h> 8 9 #define PAGE_SIZE 4096 10 #define BR_14_SIZE 2 11 #define RWX_OFFSET 2 12 13 static unsigned char rw[PAGE_SIZE + BR_14_SIZE]; 14 static unsigned char rwx[RWX_OFFSET + sizeof(rw)] 15 __attribute__((aligned(PAGE_SIZE))); 16 17 typedef unsigned long (*function_t)(unsigned long); 18 19 static int emit_function(unsigned char *p, int n) 20 { 21 int i = 0, val = 0; 22 23 while (i < n - 2) { 24 /* aghi %r2,1 */ 25 p[i++] = 0xa7; 26 p[i++] = 0x2b; 27 p[i++] = 0x00; 28 p[i++] = 0x01; 29 val++; 30 } 31 32 /* br %r14 */ 33 p[i++] = 0x07; 34 p[i++] = 0xfe; 35 36 return val; 37 } 38 39 static void memcpy_mvc(void *dest, void *src, unsigned long n) 40 { 41 while (n >= 256) { 42 asm("mvc 0(256,%[dest]),0(%[src])" 43 : 44 : [dest] "a" (dest) 45 , [src] "a" (src) 46 : "memory"); 47 dest += 256; 48 src += 256; 49 n -= 256; 50 } 51 asm("exrl %[n],0f\n" 52 "j 1f\n" 53 "0: mvc 0(1,%[dest]),0(%[src])\n" 54 "1:" 55 : 56 : [dest] "a" (dest) 57 , [src] "a" (src) 58 , [n] "a" (n) 59 : "memory"); 60 } 61 62 int main(void) 63 { 64 int expected, size; 65 66 /* Create a TB. */ 67 size = sizeof(rwx) - RWX_OFFSET - 4; 68 expected = emit_function(rwx + RWX_OFFSET, size); 69 if (((function_t)(rwx + RWX_OFFSET))(0) != expected) { 70 return 1; 71 } 72 73 /* Overwrite the TB. */ 74 size += 4; 75 expected = emit_function(rw, size); 76 memcpy_mvc(rwx + RWX_OFFSET, rw, size); 77 if (((function_t)(rwx + RWX_OFFSET))(0) != expected) { 78 return 2; 79 } 80 81 return 0; 82 } 83