Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/powerpc/lib/test_emulate_step.c
26424 views
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/text-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
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
78
static void __init show_result(char *mnemonic, char *result)
79
{
80
pr_info("%-14s : %s\n", mnemonic, result);
81
}
82
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
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(&regs);
96
regs.gpr[3] = (unsigned long) &a;
97
98
/* ld r5, 0(r3) */
99
stepped = emulate_step(&regs, 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
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(&regs);
119
regs.gpr[3] = (unsigned long)&a;
120
121
/* pld r5, 0(r3), 0 */
122
stepped = emulate_step(&regs, 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
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(&regs);
137
regs.gpr[3] = (unsigned long) &a;
138
139
/* lwz r5, 0(r3) */
140
stepped = emulate_step(&regs, 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
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(&regs);
160
regs.gpr[3] = (unsigned long)&a;
161
162
/* plwz r5, 0(r3), 0 */
163
164
stepped = emulate_step(&regs, 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
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(&regs);
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(&regs, 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
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(&regs);
198
regs.gpr[3] = (unsigned long) &a;
199
regs.gpr[5] = 0x5678;
200
201
/* std r5, 0(r3) */
202
stepped = emulate_step(&regs, 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
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(&regs);
221
regs.gpr[3] = (unsigned long)&a;
222
regs.gpr[5] = 0x5678;
223
224
/* pstd r5, 0(r3), 0 */
225
stepped = emulate_step(&regs, 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
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(&regs);
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(&regs, 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(&regs, 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
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(&regs);
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(&regs, 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(&regs, 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
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(&regs);
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(&regs, 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(&regs, 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
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(&regs);
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(&regs, 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(&regs, 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
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(&regs);
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(&regs, 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(&regs, 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
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
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
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
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
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(&regs);
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(&regs, 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(&regs, 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
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
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(&regs);
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(&regs, 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(&regs, 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
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
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(&regs);
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(&regs, 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(&regs, 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
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
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(&regs);
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(&regs, 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(&regs, 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
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
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(&regs);
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(&regs, 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(&regs, 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
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
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
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
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
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
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
1743