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