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
emit_function(unsigned char * p,int n)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
memcpy_mvc(void * dest,void * src,unsigned long n)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
main(void)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