Merge remote-tracking branches 'spi/topic/atmel', 'spi/topic/bcm63xx', 'spi/topic...
[sfrench/cifs-2.6.git] / arch / powerpc / lib / test_emulate_step.c
1 /*
2  * Simple sanity test for emulate_step load/store instructions.
3  *
4  * Copyright IBM Corp. 2016
5  *
6  * This program is free software;  you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  */
11
12 #define pr_fmt(fmt) "emulate_step_test: " fmt
13
14 #include <linux/ptrace.h>
15 #include <asm/sstep.h>
16 #include <asm/ppc-opcode.h>
17
18 #define IMM_L(i)                ((uintptr_t)(i) & 0xffff)
19
20 /*
21  * Defined with TEST_ prefix so it does not conflict with other
22  * definitions.
23  */
24 #define TEST_LD(r, base, i)     (PPC_INST_LD | ___PPC_RT(r) |           \
25                                         ___PPC_RA(base) | IMM_L(i))
26 #define TEST_LWZ(r, base, i)    (PPC_INST_LWZ | ___PPC_RT(r) |          \
27                                         ___PPC_RA(base) | IMM_L(i))
28 #define TEST_LWZX(t, a, b)      (PPC_INST_LWZX | ___PPC_RT(t) |         \
29                                         ___PPC_RA(a) | ___PPC_RB(b))
30 #define TEST_STD(r, base, i)    (PPC_INST_STD | ___PPC_RS(r) |          \
31                                         ___PPC_RA(base) | ((i) & 0xfffc))
32 #define TEST_LDARX(t, a, b, eh) (PPC_INST_LDARX | ___PPC_RT(t) |        \
33                                         ___PPC_RA(a) | ___PPC_RB(b) |   \
34                                         __PPC_EH(eh))
35 #define TEST_STDCX(s, a, b)     (PPC_INST_STDCX | ___PPC_RS(s) |        \
36                                         ___PPC_RA(a) | ___PPC_RB(b))
37 #define TEST_LFSX(t, a, b)      (PPC_INST_LFSX | ___PPC_RT(t) |         \
38                                         ___PPC_RA(a) | ___PPC_RB(b))
39 #define TEST_STFSX(s, a, b)     (PPC_INST_STFSX | ___PPC_RS(s) |        \
40                                         ___PPC_RA(a) | ___PPC_RB(b))
41 #define TEST_LFDX(t, a, b)      (PPC_INST_LFDX | ___PPC_RT(t) |         \
42                                         ___PPC_RA(a) | ___PPC_RB(b))
43 #define TEST_STFDX(s, a, b)     (PPC_INST_STFDX | ___PPC_RS(s) |        \
44                                         ___PPC_RA(a) | ___PPC_RB(b))
45 #define TEST_LVX(t, a, b)       (PPC_INST_LVX | ___PPC_RT(t) |          \
46                                         ___PPC_RA(a) | ___PPC_RB(b))
47 #define TEST_STVX(s, a, b)      (PPC_INST_STVX | ___PPC_RS(s) |         \
48                                         ___PPC_RA(a) | ___PPC_RB(b))
49 #define TEST_LXVD2X(s, a, b)    (PPC_INST_LXVD2X | VSX_XX1((s), R##a, R##b))
50 #define TEST_STXVD2X(s, a, b)   (PPC_INST_STXVD2X | VSX_XX1((s), R##a, R##b))
51
52
53 static void __init init_pt_regs(struct pt_regs *regs)
54 {
55         static unsigned long msr;
56         static bool msr_cached;
57
58         memset(regs, 0, sizeof(struct pt_regs));
59
60         if (likely(msr_cached)) {
61                 regs->msr = msr;
62                 return;
63         }
64
65         asm volatile("mfmsr %0" : "=r"(regs->msr));
66
67         regs->msr |= MSR_FP;
68         regs->msr |= MSR_VEC;
69         regs->msr |= MSR_VSX;
70
71         msr = regs->msr;
72         msr_cached = true;
73 }
74
75 static void __init show_result(char *ins, char *result)
76 {
77         pr_info("%-14s : %s\n", ins, result);
78 }
79
80 static void __init test_ld(void)
81 {
82         struct pt_regs regs;
83         unsigned long a = 0x23;
84         int stepped = -1;
85
86         init_pt_regs(&regs);
87         regs.gpr[3] = (unsigned long) &a;
88
89         /* ld r5, 0(r3) */
90         stepped = emulate_step(&regs, TEST_LD(5, 3, 0));
91
92         if (stepped == 1 && regs.gpr[5] == a)
93                 show_result("ld", "PASS");
94         else
95                 show_result("ld", "FAIL");
96 }
97
98 static void __init test_lwz(void)
99 {
100         struct pt_regs regs;
101         unsigned int a = 0x4545;
102         int stepped = -1;
103
104         init_pt_regs(&regs);
105         regs.gpr[3] = (unsigned long) &a;
106
107         /* lwz r5, 0(r3) */
108         stepped = emulate_step(&regs, TEST_LWZ(5, 3, 0));
109
110         if (stepped == 1 && regs.gpr[5] == a)
111                 show_result("lwz", "PASS");
112         else
113                 show_result("lwz", "FAIL");
114 }
115
116 static void __init test_lwzx(void)
117 {
118         struct pt_regs regs;
119         unsigned int a[3] = {0x0, 0x0, 0x1234};
120         int stepped = -1;
121
122         init_pt_regs(&regs);
123         regs.gpr[3] = (unsigned long) a;
124         regs.gpr[4] = 8;
125         regs.gpr[5] = 0x8765;
126
127         /* lwzx r5, r3, r4 */
128         stepped = emulate_step(&regs, TEST_LWZX(5, 3, 4));
129         if (stepped == 1 && regs.gpr[5] == a[2])
130                 show_result("lwzx", "PASS");
131         else
132                 show_result("lwzx", "FAIL");
133 }
134
135 static void __init test_std(void)
136 {
137         struct pt_regs regs;
138         unsigned long a = 0x1234;
139         int stepped = -1;
140
141         init_pt_regs(&regs);
142         regs.gpr[3] = (unsigned long) &a;
143         regs.gpr[5] = 0x5678;
144
145         /* std r5, 0(r3) */
146         stepped = emulate_step(&regs, TEST_STD(5, 3, 0));
147         if (stepped == 1 || regs.gpr[5] == a)
148                 show_result("std", "PASS");
149         else
150                 show_result("std", "FAIL");
151 }
152
153 static void __init test_ldarx_stdcx(void)
154 {
155         struct pt_regs regs;
156         unsigned long a = 0x1234;
157         int stepped = -1;
158         unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
159
160         init_pt_regs(&regs);
161         asm volatile("mfcr %0" : "=r"(regs.ccr));
162
163
164         /*** ldarx ***/
165
166         regs.gpr[3] = (unsigned long) &a;
167         regs.gpr[4] = 0;
168         regs.gpr[5] = 0x5678;
169
170         /* ldarx r5, r3, r4, 0 */
171         stepped = emulate_step(&regs, TEST_LDARX(5, 3, 4, 0));
172
173         /*
174          * Don't touch 'a' here. Touching 'a' can do Load/store
175          * of 'a' which result in failure of subsequent stdcx.
176          * Instead, use hardcoded value for comparison.
177          */
178         if (stepped <= 0 || regs.gpr[5] != 0x1234) {
179                 show_result("ldarx / stdcx.", "FAIL (ldarx)");
180                 return;
181         }
182
183
184         /*** stdcx. ***/
185
186         regs.gpr[5] = 0x9ABC;
187
188         /* stdcx. r5, r3, r4 */
189         stepped = emulate_step(&regs, TEST_STDCX(5, 3, 4));
190
191         /*
192          * Two possible scenarios that indicates successful emulation
193          * of stdcx. :
194          *  1. Reservation is active and store is performed. In this
195          *     case cr0.eq bit will be set to 1.
196          *  2. Reservation is not active and store is not performed.
197          *     In this case cr0.eq bit will be set to 0.
198          */
199         if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
200                         || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
201                 show_result("ldarx / stdcx.", "PASS");
202         else
203                 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
204 }
205
206 #ifdef CONFIG_PPC_FPU
207 static void __init test_lfsx_stfsx(void)
208 {
209         struct pt_regs regs;
210         union {
211                 float a;
212                 int b;
213         } c;
214         int cached_b;
215         int stepped = -1;
216
217         init_pt_regs(&regs);
218
219
220         /*** lfsx ***/
221
222         c.a = 123.45;
223         cached_b = c.b;
224
225         regs.gpr[3] = (unsigned long) &c.a;
226         regs.gpr[4] = 0;
227
228         /* lfsx frt10, r3, r4 */
229         stepped = emulate_step(&regs, TEST_LFSX(10, 3, 4));
230
231         if (stepped == 1)
232                 show_result("lfsx", "PASS");
233         else
234                 show_result("lfsx", "FAIL");
235
236
237         /*** stfsx ***/
238
239         c.a = 678.91;
240
241         /* stfsx frs10, r3, r4 */
242         stepped = emulate_step(&regs, TEST_STFSX(10, 3, 4));
243
244         if (stepped == 1 && c.b == cached_b)
245                 show_result("stfsx", "PASS");
246         else
247                 show_result("stfsx", "FAIL");
248 }
249
250 static void __init test_lfdx_stfdx(void)
251 {
252         struct pt_regs regs;
253         union {
254                 double a;
255                 long b;
256         } c;
257         long cached_b;
258         int stepped = -1;
259
260         init_pt_regs(&regs);
261
262
263         /*** lfdx ***/
264
265         c.a = 123456.78;
266         cached_b = c.b;
267
268         regs.gpr[3] = (unsigned long) &c.a;
269         regs.gpr[4] = 0;
270
271         /* lfdx frt10, r3, r4 */
272         stepped = emulate_step(&regs, TEST_LFDX(10, 3, 4));
273
274         if (stepped == 1)
275                 show_result("lfdx", "PASS");
276         else
277                 show_result("lfdx", "FAIL");
278
279
280         /*** stfdx ***/
281
282         c.a = 987654.32;
283
284         /* stfdx frs10, r3, r4 */
285         stepped = emulate_step(&regs, TEST_STFDX(10, 3, 4));
286
287         if (stepped == 1 && c.b == cached_b)
288                 show_result("stfdx", "PASS");
289         else
290                 show_result("stfdx", "FAIL");
291 }
292 #else
293 static void __init test_lfsx_stfsx(void)
294 {
295         show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
296         show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
297 }
298
299 static void __init test_lfdx_stfdx(void)
300 {
301         show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
302         show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
303 }
304 #endif /* CONFIG_PPC_FPU */
305
306 #ifdef CONFIG_ALTIVEC
307 static void __init test_lvx_stvx(void)
308 {
309         struct pt_regs regs;
310         union {
311                 vector128 a;
312                 u32 b[4];
313         } c;
314         u32 cached_b[4];
315         int stepped = -1;
316
317         init_pt_regs(&regs);
318
319
320         /*** lvx ***/
321
322         cached_b[0] = c.b[0] = 923745;
323         cached_b[1] = c.b[1] = 2139478;
324         cached_b[2] = c.b[2] = 9012;
325         cached_b[3] = c.b[3] = 982134;
326
327         regs.gpr[3] = (unsigned long) &c.a;
328         regs.gpr[4] = 0;
329
330         /* lvx vrt10, r3, r4 */
331         stepped = emulate_step(&regs, TEST_LVX(10, 3, 4));
332
333         if (stepped == 1)
334                 show_result("lvx", "PASS");
335         else
336                 show_result("lvx", "FAIL");
337
338
339         /*** stvx ***/
340
341         c.b[0] = 4987513;
342         c.b[1] = 84313948;
343         c.b[2] = 71;
344         c.b[3] = 498532;
345
346         /* stvx vrs10, r3, r4 */
347         stepped = emulate_step(&regs, TEST_STVX(10, 3, 4));
348
349         if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
350             cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
351                 show_result("stvx", "PASS");
352         else
353                 show_result("stvx", "FAIL");
354 }
355 #else
356 static void __init test_lvx_stvx(void)
357 {
358         show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
359         show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
360 }
361 #endif /* CONFIG_ALTIVEC */
362
363 #ifdef CONFIG_VSX
364 static void __init test_lxvd2x_stxvd2x(void)
365 {
366         struct pt_regs regs;
367         union {
368                 vector128 a;
369                 u32 b[4];
370         } c;
371         u32 cached_b[4];
372         int stepped = -1;
373
374         init_pt_regs(&regs);
375
376
377         /*** lxvd2x ***/
378
379         cached_b[0] = c.b[0] = 18233;
380         cached_b[1] = c.b[1] = 34863571;
381         cached_b[2] = c.b[2] = 834;
382         cached_b[3] = c.b[3] = 6138911;
383
384         regs.gpr[3] = (unsigned long) &c.a;
385         regs.gpr[4] = 0;
386
387         /* lxvd2x vsr39, r3, r4 */
388         stepped = emulate_step(&regs, TEST_LXVD2X(39, 3, 4));
389
390         if (stepped == 1)
391                 show_result("lxvd2x", "PASS");
392         else
393                 show_result("lxvd2x", "FAIL");
394
395
396         /*** stxvd2x ***/
397
398         c.b[0] = 21379463;
399         c.b[1] = 87;
400         c.b[2] = 374234;
401         c.b[3] = 4;
402
403         /* stxvd2x vsr39, r3, r4 */
404         stepped = emulate_step(&regs, TEST_STXVD2X(39, 3, 4));
405
406         if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
407             cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
408                 show_result("stxvd2x", "PASS");
409         else
410                 show_result("stxvd2x", "FAIL");
411 }
412 #else
413 static void __init test_lxvd2x_stxvd2x(void)
414 {
415         show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
416         show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
417 }
418 #endif /* CONFIG_VSX */
419
420 static int __init test_emulate_step(void)
421 {
422         test_ld();
423         test_lwz();
424         test_lwzx();
425         test_std();
426         test_ldarx_stdcx();
427         test_lfsx_stfsx();
428         test_lfdx_stfdx();
429         test_lvx_stvx();
430         test_lxvd2x_stxvd2x();
431
432         return 0;
433 }
434 late_initcall(test_emulate_step);