1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Simple sanity tests for instruction emulation infrastructure.
4 *
5 * Copyright IBM Corp. 2016
6 */
7
8 #define pr_fmt(fmt) "emulate_step_test: " fmt
9
10 #include <linux/ptrace.h>
11 #include <asm/cpu_has_feature.h>
12 #include <asm/sstep.h>
13 #include <asm/ppc-opcode.h>
14 #include <asm/code-patching.h>
15 #include <asm/inst.h>
16
17 #define MAX_SUBTESTS 16
18
19 #define IGNORE_GPR(n) (0x1UL << (n))
20 #define IGNORE_XER (0x1UL << 32)
21 #define IGNORE_CCR (0x1UL << 33)
22 #define NEGATIVE_TEST (0x1UL << 63)
23
24 #define TEST_PLD(r, base, i, pr) \
25 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
26 PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
27
28 #define TEST_PLWZ(r, base, i, pr) \
29 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
30 PPC_RAW_LWZ(r, base, i))
31
32 #define TEST_PSTD(r, base, i, pr) \
33 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
34 PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
35
36 #define TEST_PLFS(r, base, i, pr) \
37 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
38 PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
39
40 #define TEST_PSTFS(r, base, i, pr) \
41 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
42 PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
43
44 #define TEST_PLFD(r, base, i, pr) \
45 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
46 PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
47
48 #define TEST_PSTFD(r, base, i, pr) \
49 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
50 PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
51
52 #define TEST_PADDI(t, a, i, pr) \
53 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
54 PPC_RAW_ADDI(t, a, i))
55
init_pt_regs(struct pt_regs * regs)56 static void __init init_pt_regs(struct pt_regs *regs)
57 {
58 static unsigned long msr;
59 static bool msr_cached;
60
61 memset(regs, 0, sizeof(struct pt_regs));
62
63 if (likely(msr_cached)) {
64 regs->msr = msr;
65 return;
66 }
67
68 asm volatile("mfmsr %0" : "=r"(regs->msr));
69
70 regs->msr |= MSR_FP;
71 regs->msr |= MSR_VEC;
72 regs->msr |= MSR_VSX;
73
74 msr = regs->msr;
75 msr_cached = true;
76 }
77
show_result(char * mnemonic,char * result)78 static void __init show_result(char *mnemonic, char *result)
79 {
80 pr_info("%-14s : %s\n", mnemonic, result);
81 }
82
show_result_with_descr(char * mnemonic,char * descr,char * result)83 static void __init show_result_with_descr(char *mnemonic, char *descr,
84 char *result)
85 {
86 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
87 }
88
test_ld(void)89 static void __init test_ld(void)
90 {
91 struct pt_regs regs;
92 unsigned long a = 0x23;
93 int stepped = -1;
94
95 init_pt_regs(®s);
96 regs.gpr[3] = (unsigned long) &a;
97
98 /* ld r5, 0(r3) */
99 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LD(5, 3, 0)));
100
101 if (stepped == 1 && regs.gpr[5] == a)
102 show_result("ld", "PASS");
103 else
104 show_result("ld", "FAIL");
105 }
106
test_pld(void)107 static void __init test_pld(void)
108 {
109 struct pt_regs regs;
110 unsigned long a = 0x23;
111 int stepped = -1;
112
113 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
114 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
115 return;
116 }
117
118 init_pt_regs(®s);
119 regs.gpr[3] = (unsigned long)&a;
120
121 /* pld r5, 0(r3), 0 */
122 stepped = emulate_step(®s, TEST_PLD(5, 3, 0, 0));
123
124 if (stepped == 1 && regs.gpr[5] == a)
125 show_result("pld", "PASS");
126 else
127 show_result("pld", "FAIL");
128 }
129
test_lwz(void)130 static void __init test_lwz(void)
131 {
132 struct pt_regs regs;
133 unsigned int a = 0x4545;
134 int stepped = -1;
135
136 init_pt_regs(®s);
137 regs.gpr[3] = (unsigned long) &a;
138
139 /* lwz r5, 0(r3) */
140 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
141
142 if (stepped == 1 && regs.gpr[5] == a)
143 show_result("lwz", "PASS");
144 else
145 show_result("lwz", "FAIL");
146 }
147
test_plwz(void)148 static void __init test_plwz(void)
149 {
150 struct pt_regs regs;
151 unsigned int a = 0x4545;
152 int stepped = -1;
153
154 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
155 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
156 return;
157 }
158
159 init_pt_regs(®s);
160 regs.gpr[3] = (unsigned long)&a;
161
162 /* plwz r5, 0(r3), 0 */
163
164 stepped = emulate_step(®s, TEST_PLWZ(5, 3, 0, 0));
165
166 if (stepped == 1 && regs.gpr[5] == a)
167 show_result("plwz", "PASS");
168 else
169 show_result("plwz", "FAIL");
170 }
171
test_lwzx(void)172 static void __init test_lwzx(void)
173 {
174 struct pt_regs regs;
175 unsigned int a[3] = {0x0, 0x0, 0x1234};
176 int stepped = -1;
177
178 init_pt_regs(®s);
179 regs.gpr[3] = (unsigned long) a;
180 regs.gpr[4] = 8;
181 regs.gpr[5] = 0x8765;
182
183 /* lwzx r5, r3, r4 */
184 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
185 if (stepped == 1 && regs.gpr[5] == a[2])
186 show_result("lwzx", "PASS");
187 else
188 show_result("lwzx", "FAIL");
189 }
190
test_std(void)191 static void __init test_std(void)
192 {
193 struct pt_regs regs;
194 unsigned long a = 0x1234;
195 int stepped = -1;
196
197 init_pt_regs(®s);
198 regs.gpr[3] = (unsigned long) &a;
199 regs.gpr[5] = 0x5678;
200
201 /* std r5, 0(r3) */
202 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STD(5, 3, 0)));
203 if (stepped == 1 && regs.gpr[5] == a)
204 show_result("std", "PASS");
205 else
206 show_result("std", "FAIL");
207 }
208
test_pstd(void)209 static void __init test_pstd(void)
210 {
211 struct pt_regs regs;
212 unsigned long a = 0x1234;
213 int stepped = -1;
214
215 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
216 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
217 return;
218 }
219
220 init_pt_regs(®s);
221 regs.gpr[3] = (unsigned long)&a;
222 regs.gpr[5] = 0x5678;
223
224 /* pstd r5, 0(r3), 0 */
225 stepped = emulate_step(®s, TEST_PSTD(5, 3, 0, 0));
226 if (stepped == 1 || regs.gpr[5] == a)
227 show_result("pstd", "PASS");
228 else
229 show_result("pstd", "FAIL");
230 }
231
test_ldarx_stdcx(void)232 static void __init test_ldarx_stdcx(void)
233 {
234 struct pt_regs regs;
235 unsigned long a = 0x1234;
236 int stepped = -1;
237 unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */
238
239 init_pt_regs(®s);
240 asm volatile("mfcr %0" : "=r"(regs.ccr));
241
242
243 /*** ldarx ***/
244
245 regs.gpr[3] = (unsigned long) &a;
246 regs.gpr[4] = 0;
247 regs.gpr[5] = 0x5678;
248
249 /* ldarx r5, r3, r4, 0 */
250 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
251
252 /*
253 * Don't touch 'a' here. Touching 'a' can do Load/store
254 * of 'a' which result in failure of subsequent stdcx.
255 * Instead, use hardcoded value for comparison.
256 */
257 if (stepped <= 0 || regs.gpr[5] != 0x1234) {
258 show_result("ldarx / stdcx.", "FAIL (ldarx)");
259 return;
260 }
261
262
263 /*** stdcx. ***/
264
265 regs.gpr[5] = 0x9ABC;
266
267 /* stdcx. r5, r3, r4 */
268 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
269
270 /*
271 * Two possible scenarios that indicates successful emulation
272 * of stdcx. :
273 * 1. Reservation is active and store is performed. In this
274 * case cr0.eq bit will be set to 1.
275 * 2. Reservation is not active and store is not performed.
276 * In this case cr0.eq bit will be set to 0.
277 */
278 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
279 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
280 show_result("ldarx / stdcx.", "PASS");
281 else
282 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
283 }
284
285 #ifdef CONFIG_PPC_FPU
test_lfsx_stfsx(void)286 static void __init test_lfsx_stfsx(void)
287 {
288 struct pt_regs regs;
289 union {
290 float a;
291 int b;
292 } c;
293 int cached_b;
294 int stepped = -1;
295
296 init_pt_regs(®s);
297
298
299 /*** lfsx ***/
300
301 c.a = 123.45;
302 cached_b = c.b;
303
304 regs.gpr[3] = (unsigned long) &c.a;
305 regs.gpr[4] = 0;
306
307 /* lfsx frt10, r3, r4 */
308 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
309
310 if (stepped == 1)
311 show_result("lfsx", "PASS");
312 else
313 show_result("lfsx", "FAIL");
314
315
316 /*** stfsx ***/
317
318 c.a = 678.91;
319
320 /* stfsx frs10, r3, r4 */
321 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
322
323 if (stepped == 1 && c.b == cached_b)
324 show_result("stfsx", "PASS");
325 else
326 show_result("stfsx", "FAIL");
327 }
328
test_plfs_pstfs(void)329 static void __init test_plfs_pstfs(void)
330 {
331 struct pt_regs regs;
332 union {
333 float a;
334 int b;
335 } c;
336 int cached_b;
337 int stepped = -1;
338
339 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
340 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
341 return;
342 }
343
344 init_pt_regs(®s);
345
346
347 /*** plfs ***/
348
349 c.a = 123.45;
350 cached_b = c.b;
351
352 regs.gpr[3] = (unsigned long)&c.a;
353
354 /* plfs frt10, 0(r3), 0 */
355 stepped = emulate_step(®s, TEST_PLFS(10, 3, 0, 0));
356
357 if (stepped == 1)
358 show_result("plfs", "PASS");
359 else
360 show_result("plfs", "FAIL");
361
362
363 /*** pstfs ***/
364
365 c.a = 678.91;
366
367 /* pstfs frs10, 0(r3), 0 */
368 stepped = emulate_step(®s, TEST_PSTFS(10, 3, 0, 0));
369
370 if (stepped == 1 && c.b == cached_b)
371 show_result("pstfs", "PASS");
372 else
373 show_result("pstfs", "FAIL");
374 }
375
test_lfdx_stfdx(void)376 static void __init test_lfdx_stfdx(void)
377 {
378 struct pt_regs regs;
379 union {
380 double a;
381 long b;
382 } c;
383 long cached_b;
384 int stepped = -1;
385
386 init_pt_regs(®s);
387
388
389 /*** lfdx ***/
390
391 c.a = 123456.78;
392 cached_b = c.b;
393
394 regs.gpr[3] = (unsigned long) &c.a;
395 regs.gpr[4] = 0;
396
397 /* lfdx frt10, r3, r4 */
398 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
399
400 if (stepped == 1)
401 show_result("lfdx", "PASS");
402 else
403 show_result("lfdx", "FAIL");
404
405
406 /*** stfdx ***/
407
408 c.a = 987654.32;
409
410 /* stfdx frs10, r3, r4 */
411 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
412
413 if (stepped == 1 && c.b == cached_b)
414 show_result("stfdx", "PASS");
415 else
416 show_result("stfdx", "FAIL");
417 }
418
test_plfd_pstfd(void)419 static void __init test_plfd_pstfd(void)
420 {
421 struct pt_regs regs;
422 union {
423 double a;
424 long b;
425 } c;
426 long cached_b;
427 int stepped = -1;
428
429 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
430 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
431 return;
432 }
433
434 init_pt_regs(®s);
435
436
437 /*** plfd ***/
438
439 c.a = 123456.78;
440 cached_b = c.b;
441
442 regs.gpr[3] = (unsigned long)&c.a;
443
444 /* plfd frt10, 0(r3), 0 */
445 stepped = emulate_step(®s, TEST_PLFD(10, 3, 0, 0));
446
447 if (stepped == 1)
448 show_result("plfd", "PASS");
449 else
450 show_result("plfd", "FAIL");
451
452
453 /*** pstfd ***/
454
455 c.a = 987654.32;
456
457 /* pstfd frs10, 0(r3), 0 */
458 stepped = emulate_step(®s, TEST_PSTFD(10, 3, 0, 0));
459
460 if (stepped == 1 && c.b == cached_b)
461 show_result("pstfd", "PASS");
462 else
463 show_result("pstfd", "FAIL");
464 }
465 #else
test_lfsx_stfsx(void)466 static void __init test_lfsx_stfsx(void)
467 {
468 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
469 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
470 }
471
test_plfs_pstfs(void)472 static void __init test_plfs_pstfs(void)
473 {
474 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
475 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
476 }
477
test_lfdx_stfdx(void)478 static void __init test_lfdx_stfdx(void)
479 {
480 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
481 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
482 }
483
test_plfd_pstfd(void)484 static void __init test_plfd_pstfd(void)
485 {
486 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
487 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
488 }
489 #endif /* CONFIG_PPC_FPU */
490
491 #ifdef CONFIG_ALTIVEC
test_lvx_stvx(void)492 static void __init test_lvx_stvx(void)
493 {
494 struct pt_regs regs;
495 union {
496 vector128 a;
497 u32 b[4];
498 } c;
499 u32 cached_b[4];
500 int stepped = -1;
501
502 init_pt_regs(®s);
503
504
505 /*** lvx ***/
506
507 cached_b[0] = c.b[0] = 923745;
508 cached_b[1] = c.b[1] = 2139478;
509 cached_b[2] = c.b[2] = 9012;
510 cached_b[3] = c.b[3] = 982134;
511
512 regs.gpr[3] = (unsigned long) &c.a;
513 regs.gpr[4] = 0;
514
515 /* lvx vrt10, r3, r4 */
516 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
517
518 if (stepped == 1)
519 show_result("lvx", "PASS");
520 else
521 show_result("lvx", "FAIL");
522
523
524 /*** stvx ***/
525
526 c.b[0] = 4987513;
527 c.b[1] = 84313948;
528 c.b[2] = 71;
529 c.b[3] = 498532;
530
531 /* stvx vrs10, r3, r4 */
532 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
533
534 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
535 cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
536 show_result("stvx", "PASS");
537 else
538 show_result("stvx", "FAIL");
539 }
540 #else
test_lvx_stvx(void)541 static void __init test_lvx_stvx(void)
542 {
543 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
544 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
545 }
546 #endif /* CONFIG_ALTIVEC */
547
548 #ifdef CONFIG_VSX
test_lxvd2x_stxvd2x(void)549 static void __init test_lxvd2x_stxvd2x(void)
550 {
551 struct pt_regs regs;
552 union {
553 vector128 a;
554 u32 b[4];
555 } c;
556 u32 cached_b[4];
557 int stepped = -1;
558
559 init_pt_regs(®s);
560
561
562 /*** lxvd2x ***/
563
564 cached_b[0] = c.b[0] = 18233;
565 cached_b[1] = c.b[1] = 34863571;
566 cached_b[2] = c.b[2] = 834;
567 cached_b[3] = c.b[3] = 6138911;
568
569 regs.gpr[3] = (unsigned long) &c.a;
570 regs.gpr[4] = 0;
571
572 /* lxvd2x vsr39, r3, r4 */
573 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
574
575 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
576 show_result("lxvd2x", "PASS");
577 } else {
578 if (!cpu_has_feature(CPU_FTR_VSX))
579 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
580 else
581 show_result("lxvd2x", "FAIL");
582 }
583
584
585 /*** stxvd2x ***/
586
587 c.b[0] = 21379463;
588 c.b[1] = 87;
589 c.b[2] = 374234;
590 c.b[3] = 4;
591
592 /* stxvd2x vsr39, r3, r4 */
593 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
594
595 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
596 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
597 cpu_has_feature(CPU_FTR_VSX)) {
598 show_result("stxvd2x", "PASS");
599 } else {
600 if (!cpu_has_feature(CPU_FTR_VSX))
601 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
602 else
603 show_result("stxvd2x", "FAIL");
604 }
605 }
606 #else
test_lxvd2x_stxvd2x(void)607 static void __init test_lxvd2x_stxvd2x(void)
608 {
609 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
610 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
611 }
612 #endif /* CONFIG_VSX */
613
614 #ifdef CONFIG_VSX
test_lxvp_stxvp(void)615 static void __init test_lxvp_stxvp(void)
616 {
617 struct pt_regs regs;
618 union {
619 vector128 a;
620 u32 b[4];
621 } c[2];
622 u32 cached_b[8];
623 int stepped = -1;
624
625 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
626 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)");
627 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)");
628 return;
629 }
630
631 init_pt_regs(®s);
632
633 /*** lxvp ***/
634
635 cached_b[0] = c[0].b[0] = 18233;
636 cached_b[1] = c[0].b[1] = 34863571;
637 cached_b[2] = c[0].b[2] = 834;
638 cached_b[3] = c[0].b[3] = 6138911;
639 cached_b[4] = c[1].b[0] = 1234;
640 cached_b[5] = c[1].b[1] = 5678;
641 cached_b[6] = c[1].b[2] = 91011;
642 cached_b[7] = c[1].b[3] = 121314;
643
644 regs.gpr[4] = (unsigned long)&c[0].a;
645
646 /*
647 * lxvp XTp,DQ(RA)
648 * XTp = 32xTX + 2xTp
649 * let TX=1 Tp=1 RA=4 DQ=0
650 */
651 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
652
653 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
654 show_result("lxvp", "PASS");
655 } else {
656 if (!cpu_has_feature(CPU_FTR_VSX))
657 show_result("lxvp", "PASS (!CPU_FTR_VSX)");
658 else
659 show_result("lxvp", "FAIL");
660 }
661
662 /*** stxvp ***/
663
664 c[0].b[0] = 21379463;
665 c[0].b[1] = 87;
666 c[0].b[2] = 374234;
667 c[0].b[3] = 4;
668 c[1].b[0] = 90;
669 c[1].b[1] = 122;
670 c[1].b[2] = 555;
671 c[1].b[3] = 32144;
672
673 /*
674 * stxvp XSp,DQ(RA)
675 * XSp = 32xSX + 2xSp
676 * let SX=1 Sp=1 RA=4 DQ=0
677 */
678 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
679
680 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
681 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
682 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
683 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
684 cpu_has_feature(CPU_FTR_VSX)) {
685 show_result("stxvp", "PASS");
686 } else {
687 if (!cpu_has_feature(CPU_FTR_VSX))
688 show_result("stxvp", "PASS (!CPU_FTR_VSX)");
689 else
690 show_result("stxvp", "FAIL");
691 }
692 }
693 #else
test_lxvp_stxvp(void)694 static void __init test_lxvp_stxvp(void)
695 {
696 show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
697 show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
698 }
699 #endif /* CONFIG_VSX */
700
701 #ifdef CONFIG_VSX
test_lxvpx_stxvpx(void)702 static void __init test_lxvpx_stxvpx(void)
703 {
704 struct pt_regs regs;
705 union {
706 vector128 a;
707 u32 b[4];
708 } c[2];
709 u32 cached_b[8];
710 int stepped = -1;
711
712 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
713 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)");
714 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)");
715 return;
716 }
717
718 init_pt_regs(®s);
719
720 /*** lxvpx ***/
721
722 cached_b[0] = c[0].b[0] = 18233;
723 cached_b[1] = c[0].b[1] = 34863571;
724 cached_b[2] = c[0].b[2] = 834;
725 cached_b[3] = c[0].b[3] = 6138911;
726 cached_b[4] = c[1].b[0] = 1234;
727 cached_b[5] = c[1].b[1] = 5678;
728 cached_b[6] = c[1].b[2] = 91011;
729 cached_b[7] = c[1].b[3] = 121314;
730
731 regs.gpr[3] = (unsigned long)&c[0].a;
732 regs.gpr[4] = 0;
733
734 /*
735 * lxvpx XTp,RA,RB
736 * XTp = 32xTX + 2xTp
737 * let TX=1 Tp=1 RA=3 RB=4
738 */
739 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
740
741 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
742 show_result("lxvpx", "PASS");
743 } else {
744 if (!cpu_has_feature(CPU_FTR_VSX))
745 show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
746 else
747 show_result("lxvpx", "FAIL");
748 }
749
750 /*** stxvpx ***/
751
752 c[0].b[0] = 21379463;
753 c[0].b[1] = 87;
754 c[0].b[2] = 374234;
755 c[0].b[3] = 4;
756 c[1].b[0] = 90;
757 c[1].b[1] = 122;
758 c[1].b[2] = 555;
759 c[1].b[3] = 32144;
760
761 /*
762 * stxvpx XSp,RA,RB
763 * XSp = 32xSX + 2xSp
764 * let SX=1 Sp=1 RA=3 RB=4
765 */
766 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
767
768 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
769 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
770 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
771 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
772 cpu_has_feature(CPU_FTR_VSX)) {
773 show_result("stxvpx", "PASS");
774 } else {
775 if (!cpu_has_feature(CPU_FTR_VSX))
776 show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
777 else
778 show_result("stxvpx", "FAIL");
779 }
780 }
781 #else
test_lxvpx_stxvpx(void)782 static void __init test_lxvpx_stxvpx(void)
783 {
784 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
785 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
786 }
787 #endif /* CONFIG_VSX */
788
789 #ifdef CONFIG_VSX
test_plxvp_pstxvp(void)790 static void __init test_plxvp_pstxvp(void)
791 {
792 ppc_inst_t instr;
793 struct pt_regs regs;
794 union {
795 vector128 a;
796 u32 b[4];
797 } c[2];
798 u32 cached_b[8];
799 int stepped = -1;
800
801 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
802 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)");
803 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)");
804 return;
805 }
806
807 /*** plxvp ***/
808
809 cached_b[0] = c[0].b[0] = 18233;
810 cached_b[1] = c[0].b[1] = 34863571;
811 cached_b[2] = c[0].b[2] = 834;
812 cached_b[3] = c[0].b[3] = 6138911;
813 cached_b[4] = c[1].b[0] = 1234;
814 cached_b[5] = c[1].b[1] = 5678;
815 cached_b[6] = c[1].b[2] = 91011;
816 cached_b[7] = c[1].b[3] = 121314;
817
818 init_pt_regs(®s);
819 regs.gpr[3] = (unsigned long)&c[0].a;
820
821 /*
822 * plxvp XTp,D(RA),R
823 * XTp = 32xTX + 2xTp
824 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1
825 */
826 instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0));
827
828 stepped = emulate_step(®s, instr);
829 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
830 show_result("plxvp", "PASS");
831 } else {
832 if (!cpu_has_feature(CPU_FTR_VSX))
833 show_result("plxvp", "PASS (!CPU_FTR_VSX)");
834 else
835 show_result("plxvp", "FAIL");
836 }
837
838 /*** pstxvp ***/
839
840 c[0].b[0] = 21379463;
841 c[0].b[1] = 87;
842 c[0].b[2] = 374234;
843 c[0].b[3] = 4;
844 c[1].b[0] = 90;
845 c[1].b[1] = 122;
846 c[1].b[2] = 555;
847 c[1].b[3] = 32144;
848
849 /*
850 * pstxvp XSp,D(RA),R
851 * XSp = 32xSX + 2xSp
852 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1
853 */
854 instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0));
855
856 stepped = emulate_step(®s, instr);
857
858 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
859 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
860 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
861 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
862 cpu_has_feature(CPU_FTR_VSX)) {
863 show_result("pstxvp", "PASS");
864 } else {
865 if (!cpu_has_feature(CPU_FTR_VSX))
866 show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
867 else
868 show_result("pstxvp", "FAIL");
869 }
870 }
871 #else
test_plxvp_pstxvp(void)872 static void __init test_plxvp_pstxvp(void)
873 {
874 show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
875 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
876 }
877 #endif /* CONFIG_VSX */
878
run_tests_load_store(void)879 static void __init run_tests_load_store(void)
880 {
881 test_ld();
882 test_pld();
883 test_lwz();
884 test_plwz();
885 test_lwzx();
886 test_std();
887 test_pstd();
888 test_ldarx_stdcx();
889 test_lfsx_stfsx();
890 test_plfs_pstfs();
891 test_lfdx_stfdx();
892 test_plfd_pstfd();
893 test_lvx_stvx();
894 test_lxvd2x_stxvd2x();
895 test_lxvp_stxvp();
896 test_lxvpx_stxvpx();
897 test_plxvp_pstxvp();
898 }
899
900 struct compute_test {
901 char *mnemonic;
902 unsigned long cpu_feature;
903 struct {
904 char *descr;
905 unsigned long flags;
906 ppc_inst_t instr;
907 struct pt_regs regs;
908 } subtests[MAX_SUBTESTS + 1];
909 };
910
911 /* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */
912 #define SI_MIN BIT(33)
913 #define SI_MAX (BIT(33) - 1)
914 #define SI_UMAX (BIT(34) - 1)
915
916 static struct compute_test compute_tests[] = {
917 {
918 .mnemonic = "nop",
919 .subtests = {
920 {
921 .descr = "R0 = LONG_MAX",
922 .instr = ppc_inst(PPC_RAW_NOP()),
923 .regs = {
924 .gpr[0] = LONG_MAX,
925 }
926 }
927 }
928 },
929 {
930 .mnemonic = "setb",
931 .cpu_feature = CPU_FTR_ARCH_300,
932 .subtests = {
933 {
934 .descr = "BFA = 1, CR = GT",
935 .instr = ppc_inst(PPC_RAW_SETB(20, 1)),
936 .regs = {
937 .ccr = 0x4000000,
938 }
939 },
940 {
941 .descr = "BFA = 4, CR = LT",
942 .instr = ppc_inst(PPC_RAW_SETB(20, 4)),
943 .regs = {
944 .ccr = 0x8000,
945 }
946 },
947 {
948 .descr = "BFA = 5, CR = EQ",
949 .instr = ppc_inst(PPC_RAW_SETB(20, 5)),
950 .regs = {
951 .ccr = 0x200,
952 }
953 }
954 }
955 },
956 {
957 .mnemonic = "add",
958 .subtests = {
959 {
960 .descr = "RA = LONG_MIN, RB = LONG_MIN",
961 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
962 .regs = {
963 .gpr[21] = LONG_MIN,
964 .gpr[22] = LONG_MIN,
965 }
966 },
967 {
968 .descr = "RA = LONG_MIN, RB = LONG_MAX",
969 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
970 .regs = {
971 .gpr[21] = LONG_MIN,
972 .gpr[22] = LONG_MAX,
973 }
974 },
975 {
976 .descr = "RA = LONG_MAX, RB = LONG_MAX",
977 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
978 .regs = {
979 .gpr[21] = LONG_MAX,
980 .gpr[22] = LONG_MAX,
981 }
982 },
983 {
984 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
985 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
986 .regs = {
987 .gpr[21] = ULONG_MAX,
988 .gpr[22] = ULONG_MAX,
989 }
990 },
991 {
992 .descr = "RA = ULONG_MAX, RB = 0x1",
993 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
994 .regs = {
995 .gpr[21] = ULONG_MAX,
996 .gpr[22] = 0x1,
997 }
998 },
999 {
1000 .descr = "RA = INT_MIN, RB = INT_MIN",
1001 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1002 .regs = {
1003 .gpr[21] = INT_MIN,
1004 .gpr[22] = INT_MIN,
1005 }
1006 },
1007 {
1008 .descr = "RA = INT_MIN, RB = INT_MAX",
1009 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1010 .regs = {
1011 .gpr[21] = INT_MIN,
1012 .gpr[22] = INT_MAX,
1013 }
1014 },
1015 {
1016 .descr = "RA = INT_MAX, RB = INT_MAX",
1017 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1018 .regs = {
1019 .gpr[21] = INT_MAX,
1020 .gpr[22] = INT_MAX,
1021 }
1022 },
1023 {
1024 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1025 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1026 .regs = {
1027 .gpr[21] = UINT_MAX,
1028 .gpr[22] = UINT_MAX,
1029 }
1030 },
1031 {
1032 .descr = "RA = UINT_MAX, RB = 0x1",
1033 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
1034 .regs = {
1035 .gpr[21] = UINT_MAX,
1036 .gpr[22] = 0x1,
1037 }
1038 }
1039 }
1040 },
1041 {
1042 .mnemonic = "add.",
1043 .subtests = {
1044 {
1045 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1046 .flags = IGNORE_CCR,
1047 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1048 .regs = {
1049 .gpr[21] = LONG_MIN,
1050 .gpr[22] = LONG_MIN,
1051 }
1052 },
1053 {
1054 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1055 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1056 .regs = {
1057 .gpr[21] = LONG_MIN,
1058 .gpr[22] = LONG_MAX,
1059 }
1060 },
1061 {
1062 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1063 .flags = IGNORE_CCR,
1064 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1065 .regs = {
1066 .gpr[21] = LONG_MAX,
1067 .gpr[22] = LONG_MAX,
1068 }
1069 },
1070 {
1071 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1072 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1073 .regs = {
1074 .gpr[21] = ULONG_MAX,
1075 .gpr[22] = ULONG_MAX,
1076 }
1077 },
1078 {
1079 .descr = "RA = ULONG_MAX, RB = 0x1",
1080 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1081 .regs = {
1082 .gpr[21] = ULONG_MAX,
1083 .gpr[22] = 0x1,
1084 }
1085 },
1086 {
1087 .descr = "RA = INT_MIN, RB = INT_MIN",
1088 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1089 .regs = {
1090 .gpr[21] = INT_MIN,
1091 .gpr[22] = INT_MIN,
1092 }
1093 },
1094 {
1095 .descr = "RA = INT_MIN, RB = INT_MAX",
1096 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1097 .regs = {
1098 .gpr[21] = INT_MIN,
1099 .gpr[22] = INT_MAX,
1100 }
1101 },
1102 {
1103 .descr = "RA = INT_MAX, RB = INT_MAX",
1104 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1105 .regs = {
1106 .gpr[21] = INT_MAX,
1107 .gpr[22] = INT_MAX,
1108 }
1109 },
1110 {
1111 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1112 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1113 .regs = {
1114 .gpr[21] = UINT_MAX,
1115 .gpr[22] = UINT_MAX,
1116 }
1117 },
1118 {
1119 .descr = "RA = UINT_MAX, RB = 0x1",
1120 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)),
1121 .regs = {
1122 .gpr[21] = UINT_MAX,
1123 .gpr[22] = 0x1,
1124 }
1125 }
1126 }
1127 },
1128 {
1129 .mnemonic = "addc",
1130 .subtests = {
1131 {
1132 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1133 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1134 .regs = {
1135 .gpr[21] = LONG_MIN,
1136 .gpr[22] = LONG_MIN,
1137 }
1138 },
1139 {
1140 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1141 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1142 .regs = {
1143 .gpr[21] = LONG_MIN,
1144 .gpr[22] = LONG_MAX,
1145 }
1146 },
1147 {
1148 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1149 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1150 .regs = {
1151 .gpr[21] = LONG_MAX,
1152 .gpr[22] = LONG_MAX,
1153 }
1154 },
1155 {
1156 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1157 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1158 .regs = {
1159 .gpr[21] = ULONG_MAX,
1160 .gpr[22] = ULONG_MAX,
1161 }
1162 },
1163 {
1164 .descr = "RA = ULONG_MAX, RB = 0x1",
1165 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1166 .regs = {
1167 .gpr[21] = ULONG_MAX,
1168 .gpr[22] = 0x1,
1169 }
1170 },
1171 {
1172 .descr = "RA = INT_MIN, RB = INT_MIN",
1173 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1174 .regs = {
1175 .gpr[21] = INT_MIN,
1176 .gpr[22] = INT_MIN,
1177 }
1178 },
1179 {
1180 .descr = "RA = INT_MIN, RB = INT_MAX",
1181 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1182 .regs = {
1183 .gpr[21] = INT_MIN,
1184 .gpr[22] = INT_MAX,
1185 }
1186 },
1187 {
1188 .descr = "RA = INT_MAX, RB = INT_MAX",
1189 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1190 .regs = {
1191 .gpr[21] = INT_MAX,
1192 .gpr[22] = INT_MAX,
1193 }
1194 },
1195 {
1196 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1197 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1198 .regs = {
1199 .gpr[21] = UINT_MAX,
1200 .gpr[22] = UINT_MAX,
1201 }
1202 },
1203 {
1204 .descr = "RA = UINT_MAX, RB = 0x1",
1205 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1206 .regs = {
1207 .gpr[21] = UINT_MAX,
1208 .gpr[22] = 0x1,
1209 }
1210 },
1211 {
1212 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1213 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)),
1214 .regs = {
1215 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1216 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1217 }
1218 }
1219 }
1220 },
1221 {
1222 .mnemonic = "addc.",
1223 .subtests = {
1224 {
1225 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1226 .flags = IGNORE_CCR,
1227 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1228 .regs = {
1229 .gpr[21] = LONG_MIN,
1230 .gpr[22] = LONG_MIN,
1231 }
1232 },
1233 {
1234 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1235 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1236 .regs = {
1237 .gpr[21] = LONG_MIN,
1238 .gpr[22] = LONG_MAX,
1239 }
1240 },
1241 {
1242 .descr = "RA = LONG_MAX, RB = LONG_MAX",
1243 .flags = IGNORE_CCR,
1244 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1245 .regs = {
1246 .gpr[21] = LONG_MAX,
1247 .gpr[22] = LONG_MAX,
1248 }
1249 },
1250 {
1251 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
1252 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1253 .regs = {
1254 .gpr[21] = ULONG_MAX,
1255 .gpr[22] = ULONG_MAX,
1256 }
1257 },
1258 {
1259 .descr = "RA = ULONG_MAX, RB = 0x1",
1260 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1261 .regs = {
1262 .gpr[21] = ULONG_MAX,
1263 .gpr[22] = 0x1,
1264 }
1265 },
1266 {
1267 .descr = "RA = INT_MIN, RB = INT_MIN",
1268 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1269 .regs = {
1270 .gpr[21] = INT_MIN,
1271 .gpr[22] = INT_MIN,
1272 }
1273 },
1274 {
1275 .descr = "RA = INT_MIN, RB = INT_MAX",
1276 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1277 .regs = {
1278 .gpr[21] = INT_MIN,
1279 .gpr[22] = INT_MAX,
1280 }
1281 },
1282 {
1283 .descr = "RA = INT_MAX, RB = INT_MAX",
1284 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1285 .regs = {
1286 .gpr[21] = INT_MAX,
1287 .gpr[22] = INT_MAX,
1288 }
1289 },
1290 {
1291 .descr = "RA = UINT_MAX, RB = UINT_MAX",
1292 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1293 .regs = {
1294 .gpr[21] = UINT_MAX,
1295 .gpr[22] = UINT_MAX,
1296 }
1297 },
1298 {
1299 .descr = "RA = UINT_MAX, RB = 0x1",
1300 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1301 .regs = {
1302 .gpr[21] = UINT_MAX,
1303 .gpr[22] = 0x1,
1304 }
1305 },
1306 {
1307 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN",
1308 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)),
1309 .regs = {
1310 .gpr[21] = LONG_MIN | (uint)INT_MIN,
1311 .gpr[22] = LONG_MIN | (uint)INT_MIN,
1312 }
1313 }
1314 }
1315 },
1316 {
1317 .mnemonic = "divde",
1318 .subtests = {
1319 {
1320 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1321 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1322 .regs = {
1323 .gpr[21] = LONG_MIN,
1324 .gpr[22] = LONG_MIN,
1325 }
1326 },
1327 {
1328 .descr = "RA = 1L, RB = 0",
1329 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1330 .flags = IGNORE_GPR(20),
1331 .regs = {
1332 .gpr[21] = 1L,
1333 .gpr[22] = 0,
1334 }
1335 },
1336 {
1337 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1338 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)),
1339 .regs = {
1340 .gpr[21] = LONG_MIN,
1341 .gpr[22] = LONG_MAX,
1342 }
1343 }
1344 }
1345 },
1346 {
1347 .mnemonic = "divde.",
1348 .subtests = {
1349 {
1350 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1351 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1352 .regs = {
1353 .gpr[21] = LONG_MIN,
1354 .gpr[22] = LONG_MIN,
1355 }
1356 },
1357 {
1358 .descr = "RA = 1L, RB = 0",
1359 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1360 .flags = IGNORE_GPR(20),
1361 .regs = {
1362 .gpr[21] = 1L,
1363 .gpr[22] = 0,
1364 }
1365 },
1366 {
1367 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1368 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)),
1369 .regs = {
1370 .gpr[21] = LONG_MIN,
1371 .gpr[22] = LONG_MAX,
1372 }
1373 }
1374 }
1375 },
1376 {
1377 .mnemonic = "divdeu",
1378 .subtests = {
1379 {
1380 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1381 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1382 .flags = IGNORE_GPR(20),
1383 .regs = {
1384 .gpr[21] = LONG_MIN,
1385 .gpr[22] = LONG_MIN,
1386 }
1387 },
1388 {
1389 .descr = "RA = 1L, RB = 0",
1390 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1391 .flags = IGNORE_GPR(20),
1392 .regs = {
1393 .gpr[21] = 1L,
1394 .gpr[22] = 0,
1395 }
1396 },
1397 {
1398 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1399 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1400 .regs = {
1401 .gpr[21] = LONG_MIN,
1402 .gpr[22] = LONG_MAX,
1403 }
1404 },
1405 {
1406 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1407 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1408 .regs = {
1409 .gpr[21] = LONG_MAX - 1,
1410 .gpr[22] = LONG_MAX,
1411 }
1412 },
1413 {
1414 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1415 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)),
1416 .flags = IGNORE_GPR(20),
1417 .regs = {
1418 .gpr[21] = LONG_MIN + 1,
1419 .gpr[22] = LONG_MIN,
1420 }
1421 }
1422 }
1423 },
1424 {
1425 .mnemonic = "divdeu.",
1426 .subtests = {
1427 {
1428 .descr = "RA = LONG_MIN, RB = LONG_MIN",
1429 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1430 .flags = IGNORE_GPR(20),
1431 .regs = {
1432 .gpr[21] = LONG_MIN,
1433 .gpr[22] = LONG_MIN,
1434 }
1435 },
1436 {
1437 .descr = "RA = 1L, RB = 0",
1438 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1439 .flags = IGNORE_GPR(20),
1440 .regs = {
1441 .gpr[21] = 1L,
1442 .gpr[22] = 0,
1443 }
1444 },
1445 {
1446 .descr = "RA = LONG_MIN, RB = LONG_MAX",
1447 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1448 .regs = {
1449 .gpr[21] = LONG_MIN,
1450 .gpr[22] = LONG_MAX,
1451 }
1452 },
1453 {
1454 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX",
1455 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1456 .regs = {
1457 .gpr[21] = LONG_MAX - 1,
1458 .gpr[22] = LONG_MAX,
1459 }
1460 },
1461 {
1462 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN",
1463 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)),
1464 .flags = IGNORE_GPR(20),
1465 .regs = {
1466 .gpr[21] = LONG_MIN + 1,
1467 .gpr[22] = LONG_MIN,
1468 }
1469 }
1470 }
1471 },
1472 {
1473 .mnemonic = "paddi",
1474 .cpu_feature = CPU_FTR_ARCH_31,
1475 .subtests = {
1476 {
1477 .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0",
1478 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1479 .regs = {
1480 .gpr[21] = 0,
1481 .gpr[22] = LONG_MIN,
1482 }
1483 },
1484 {
1485 .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0",
1486 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1487 .regs = {
1488 .gpr[21] = 0,
1489 .gpr[22] = LONG_MIN,
1490 }
1491 },
1492 {
1493 .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0",
1494 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1495 .regs = {
1496 .gpr[21] = 0,
1497 .gpr[22] = LONG_MAX,
1498 }
1499 },
1500 {
1501 .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0",
1502 .instr = TEST_PADDI(21, 22, SI_UMAX, 0),
1503 .regs = {
1504 .gpr[21] = 0,
1505 .gpr[22] = ULONG_MAX,
1506 }
1507 },
1508 {
1509 .descr = "RA = ULONG_MAX, SI = 0x1, R = 0",
1510 .instr = TEST_PADDI(21, 22, 0x1, 0),
1511 .regs = {
1512 .gpr[21] = 0,
1513 .gpr[22] = ULONG_MAX,
1514 }
1515 },
1516 {
1517 .descr = "RA = INT_MIN, SI = SI_MIN, R = 0",
1518 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1519 .regs = {
1520 .gpr[21] = 0,
1521 .gpr[22] = INT_MIN,
1522 }
1523 },
1524 {
1525 .descr = "RA = INT_MIN, SI = SI_MAX, R = 0",
1526 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1527 .regs = {
1528 .gpr[21] = 0,
1529 .gpr[22] = INT_MIN,
1530 }
1531 },
1532 {
1533 .descr = "RA = INT_MAX, SI = SI_MAX, R = 0",
1534 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1535 .regs = {
1536 .gpr[21] = 0,
1537 .gpr[22] = INT_MAX,
1538 }
1539 },
1540 {
1541 .descr = "RA = UINT_MAX, SI = 0x1, R = 0",
1542 .instr = TEST_PADDI(21, 22, 0x1, 0),
1543 .regs = {
1544 .gpr[21] = 0,
1545 .gpr[22] = UINT_MAX,
1546 }
1547 },
1548 {
1549 .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0",
1550 .instr = TEST_PADDI(21, 22, SI_MAX, 0),
1551 .regs = {
1552 .gpr[21] = 0,
1553 .gpr[22] = UINT_MAX,
1554 }
1555 },
1556 {
1557 .descr = "RA is r0, SI = SI_MIN, R = 0",
1558 .instr = TEST_PADDI(21, 0, SI_MIN, 0),
1559 .regs = {
1560 .gpr[21] = 0x0,
1561 }
1562 },
1563 {
1564 .descr = "RA = 0, SI = SI_MIN, R = 0",
1565 .instr = TEST_PADDI(21, 22, SI_MIN, 0),
1566 .regs = {
1567 .gpr[21] = 0x0,
1568 .gpr[22] = 0x0,
1569 }
1570 },
1571 {
1572 .descr = "RA is r0, SI = 0, R = 1",
1573 .instr = TEST_PADDI(21, 0, 0, 1),
1574 .regs = {
1575 .gpr[21] = 0,
1576 }
1577 },
1578 {
1579 .descr = "RA is r0, SI = SI_MIN, R = 1",
1580 .instr = TEST_PADDI(21, 0, SI_MIN, 1),
1581 .regs = {
1582 .gpr[21] = 0,
1583 }
1584 },
1585 /* Invalid instruction form with R = 1 and RA != 0 */
1586 {
1587 .descr = "RA = R22(0), SI = 0, R = 1",
1588 .instr = TEST_PADDI(21, 22, 0, 1),
1589 .flags = NEGATIVE_TEST,
1590 .regs = {
1591 .gpr[21] = 0,
1592 .gpr[22] = 0,
1593 }
1594 }
1595 }
1596 }
1597 };
1598
emulate_compute_instr(struct pt_regs * regs,ppc_inst_t instr,bool negative)1599 static int __init emulate_compute_instr(struct pt_regs *regs,
1600 ppc_inst_t instr,
1601 bool negative)
1602 {
1603 int analysed;
1604 struct instruction_op op;
1605
1606 if (!regs || !ppc_inst_val(instr))
1607 return -EINVAL;
1608
1609 /* This is not a return frame regs */
1610 regs->nip = patch_site_addr(&patch__exec_instr);
1611
1612 analysed = analyse_instr(&op, regs, instr);
1613 if (analysed != 1 || GETTYPE(op.type) != COMPUTE) {
1614 if (negative)
1615 return -EFAULT;
1616 pr_info("emulation failed, instruction = %08lx\n", ppc_inst_as_ulong(instr));
1617 return -EFAULT;
1618 }
1619 if (analysed == 1 && negative)
1620 pr_info("negative test failed, instruction = %08lx\n", ppc_inst_as_ulong(instr));
1621 if (!negative)
1622 emulate_update_regs(regs, &op);
1623 return 0;
1624 }
1625
execute_compute_instr(struct pt_regs * regs,ppc_inst_t instr)1626 static int __init execute_compute_instr(struct pt_regs *regs,
1627 ppc_inst_t instr)
1628 {
1629 extern int exec_instr(struct pt_regs *regs);
1630
1631 if (!regs || !ppc_inst_val(instr))
1632 return -EINVAL;
1633
1634 /* Patch the NOP with the actual instruction */
1635 patch_instruction_site(&patch__exec_instr, instr);
1636 if (exec_instr(regs)) {
1637 pr_info("execution failed, instruction = %08lx\n", ppc_inst_as_ulong(instr));
1638 return -EFAULT;
1639 }
1640
1641 return 0;
1642 }
1643
1644 #define gpr_mismatch(gprn, exp, got) \
1645 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1646 gprn, exp, got)
1647
1648 #define reg_mismatch(name, exp, got) \
1649 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \
1650 name, exp, got)
1651
run_tests_compute(void)1652 static void __init run_tests_compute(void)
1653 {
1654 unsigned long flags;
1655 struct compute_test *test;
1656 struct pt_regs *regs, exp, got;
1657 unsigned int i, j, k;
1658 ppc_inst_t instr;
1659 bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative;
1660
1661 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) {
1662 test = &compute_tests[i];
1663
1664 if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) {
1665 show_result(test->mnemonic, "SKIP (!CPU_FTR)");
1666 continue;
1667 }
1668
1669 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) {
1670 instr = test->subtests[j].instr;
1671 flags = test->subtests[j].flags;
1672 regs = &test->subtests[j].regs;
1673 negative = flags & NEGATIVE_TEST;
1674 ignore_xer = flags & IGNORE_XER;
1675 ignore_ccr = flags & IGNORE_CCR;
1676 passed = true;
1677
1678 memcpy(&exp, regs, sizeof(struct pt_regs));
1679 memcpy(&got, regs, sizeof(struct pt_regs));
1680
1681 /*
1682 * Set a compatible MSR value explicitly to ensure
1683 * that XER and CR bits are updated appropriately
1684 */
1685 exp.msr = MSR_KERNEL;
1686 got.msr = MSR_KERNEL;
1687
1688 rc = emulate_compute_instr(&got, instr, negative) != 0;
1689 if (negative) {
1690 /* skip executing instruction */
1691 passed = rc;
1692 goto print;
1693 } else if (rc || execute_compute_instr(&exp, instr)) {
1694 passed = false;
1695 goto print;
1696 }
1697
1698 /* Verify GPR values */
1699 for (k = 0; k < 32; k++) {
1700 ignore_gpr = flags & IGNORE_GPR(k);
1701 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) {
1702 passed = false;
1703 gpr_mismatch(k, exp.gpr[k], got.gpr[k]);
1704 }
1705 }
1706
1707 /* Verify LR value */
1708 if (exp.link != got.link) {
1709 passed = false;
1710 reg_mismatch("LR", exp.link, got.link);
1711 }
1712
1713 /* Verify XER value */
1714 if (!ignore_xer && exp.xer != got.xer) {
1715 passed = false;
1716 reg_mismatch("XER", exp.xer, got.xer);
1717 }
1718
1719 /* Verify CR value */
1720 if (!ignore_ccr && exp.ccr != got.ccr) {
1721 passed = false;
1722 reg_mismatch("CR", exp.ccr, got.ccr);
1723 }
1724
1725 print:
1726 show_result_with_descr(test->mnemonic,
1727 test->subtests[j].descr,
1728 passed ? "PASS" : "FAIL");
1729 }
1730 }
1731 }
1732
test_emulate_step(void)1733 static int __init test_emulate_step(void)
1734 {
1735 printk(KERN_INFO "Running instruction emulation self-tests ...\n");
1736 run_tests_load_store();
1737 run_tests_compute();
1738
1739 return 0;
1740 }
1741 late_initcall(test_emulate_step);
1742