xref: /qemu/tests/tcg/s390x/mvc-smc.c (revision e60938852ff051ab0afeb178af01bba0d63b3bbc)
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