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