0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "emulate_step_test: " fmt
0009
0010 #include <linux/ptrace.h>
0011 #include <asm/cpu_has_feature.h>
0012 #include <asm/sstep.h>
0013 #include <asm/ppc-opcode.h>
0014 #include <asm/code-patching.h>
0015 #include <asm/inst.h>
0016
0017 #define MAX_SUBTESTS 16
0018
0019 #define IGNORE_GPR(n) (0x1UL << (n))
0020 #define IGNORE_XER (0x1UL << 32)
0021 #define IGNORE_CCR (0x1UL << 33)
0022 #define NEGATIVE_TEST (0x1UL << 63)
0023
0024 #define TEST_PLD(r, base, i, pr) \
0025 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
0026 PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
0027
0028 #define TEST_PLWZ(r, base, i, pr) \
0029 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
0030 PPC_RAW_LWZ(r, base, i))
0031
0032 #define TEST_PSTD(r, base, i, pr) \
0033 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \
0034 PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
0035
0036 #define TEST_PLFS(r, base, i, pr) \
0037 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
0038 PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
0039
0040 #define TEST_PSTFS(r, base, i, pr) \
0041 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
0042 PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
0043
0044 #define TEST_PLFD(r, base, i, pr) \
0045 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
0046 PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
0047
0048 #define TEST_PSTFD(r, base, i, pr) \
0049 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
0050 PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i))
0051
0052 #define TEST_PADDI(t, a, i, pr) \
0053 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \
0054 PPC_RAW_ADDI(t, a, i))
0055
0056 static void __init init_pt_regs(struct pt_regs *regs)
0057 {
0058 static unsigned long msr;
0059 static bool msr_cached;
0060
0061 memset(regs, 0, sizeof(struct pt_regs));
0062
0063 if (likely(msr_cached)) {
0064 regs->msr = msr;
0065 return;
0066 }
0067
0068 asm volatile("mfmsr %0" : "=r"(regs->msr));
0069
0070 regs->msr |= MSR_FP;
0071 regs->msr |= MSR_VEC;
0072 regs->msr |= MSR_VSX;
0073
0074 msr = regs->msr;
0075 msr_cached = true;
0076 }
0077
0078 static void __init show_result(char *mnemonic, char *result)
0079 {
0080 pr_info("%-14s : %s\n", mnemonic, result);
0081 }
0082
0083 static void __init show_result_with_descr(char *mnemonic, char *descr,
0084 char *result)
0085 {
0086 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result);
0087 }
0088
0089 static void __init test_ld(void)
0090 {
0091 struct pt_regs regs;
0092 unsigned long a = 0x23;
0093 int stepped = -1;
0094
0095 init_pt_regs(®s);
0096 regs.gpr[3] = (unsigned long) &a;
0097
0098
0099 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LD(5, 3, 0)));
0100
0101 if (stepped == 1 && regs.gpr[5] == a)
0102 show_result("ld", "PASS");
0103 else
0104 show_result("ld", "FAIL");
0105 }
0106
0107 static void __init test_pld(void)
0108 {
0109 struct pt_regs regs;
0110 unsigned long a = 0x23;
0111 int stepped = -1;
0112
0113 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0114 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
0115 return;
0116 }
0117
0118 init_pt_regs(®s);
0119 regs.gpr[3] = (unsigned long)&a;
0120
0121
0122 stepped = emulate_step(®s, TEST_PLD(5, 3, 0, 0));
0123
0124 if (stepped == 1 && regs.gpr[5] == a)
0125 show_result("pld", "PASS");
0126 else
0127 show_result("pld", "FAIL");
0128 }
0129
0130 static void __init test_lwz(void)
0131 {
0132 struct pt_regs regs;
0133 unsigned int a = 0x4545;
0134 int stepped = -1;
0135
0136 init_pt_regs(®s);
0137 regs.gpr[3] = (unsigned long) &a;
0138
0139
0140 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZ(5, 3, 0)));
0141
0142 if (stepped == 1 && regs.gpr[5] == a)
0143 show_result("lwz", "PASS");
0144 else
0145 show_result("lwz", "FAIL");
0146 }
0147
0148 static void __init test_plwz(void)
0149 {
0150 struct pt_regs regs;
0151 unsigned int a = 0x4545;
0152 int stepped = -1;
0153
0154 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0155 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)");
0156 return;
0157 }
0158
0159 init_pt_regs(®s);
0160 regs.gpr[3] = (unsigned long)&a;
0161
0162
0163
0164 stepped = emulate_step(®s, TEST_PLWZ(5, 3, 0, 0));
0165
0166 if (stepped == 1 && regs.gpr[5] == a)
0167 show_result("plwz", "PASS");
0168 else
0169 show_result("plwz", "FAIL");
0170 }
0171
0172 static void __init test_lwzx(void)
0173 {
0174 struct pt_regs regs;
0175 unsigned int a[3] = {0x0, 0x0, 0x1234};
0176 int stepped = -1;
0177
0178 init_pt_regs(®s);
0179 regs.gpr[3] = (unsigned long) a;
0180 regs.gpr[4] = 8;
0181 regs.gpr[5] = 0x8765;
0182
0183
0184 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZX(5, 3, 4)));
0185 if (stepped == 1 && regs.gpr[5] == a[2])
0186 show_result("lwzx", "PASS");
0187 else
0188 show_result("lwzx", "FAIL");
0189 }
0190
0191 static void __init test_std(void)
0192 {
0193 struct pt_regs regs;
0194 unsigned long a = 0x1234;
0195 int stepped = -1;
0196
0197 init_pt_regs(®s);
0198 regs.gpr[3] = (unsigned long) &a;
0199 regs.gpr[5] = 0x5678;
0200
0201
0202 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STD(5, 3, 0)));
0203 if (stepped == 1 && regs.gpr[5] == a)
0204 show_result("std", "PASS");
0205 else
0206 show_result("std", "FAIL");
0207 }
0208
0209 static void __init test_pstd(void)
0210 {
0211 struct pt_regs regs;
0212 unsigned long a = 0x1234;
0213 int stepped = -1;
0214
0215 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0216 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)");
0217 return;
0218 }
0219
0220 init_pt_regs(®s);
0221 regs.gpr[3] = (unsigned long)&a;
0222 regs.gpr[5] = 0x5678;
0223
0224
0225 stepped = emulate_step(®s, TEST_PSTD(5, 3, 0, 0));
0226 if (stepped == 1 || regs.gpr[5] == a)
0227 show_result("pstd", "PASS");
0228 else
0229 show_result("pstd", "FAIL");
0230 }
0231
0232 static void __init test_ldarx_stdcx(void)
0233 {
0234 struct pt_regs regs;
0235 unsigned long a = 0x1234;
0236 int stepped = -1;
0237 unsigned long cr0_eq = 0x1 << 29;
0238
0239 init_pt_regs(®s);
0240 asm volatile("mfcr %0" : "=r"(regs.ccr));
0241
0242
0243
0244
0245 regs.gpr[3] = (unsigned long) &a;
0246 regs.gpr[4] = 0;
0247 regs.gpr[5] = 0x5678;
0248
0249
0250 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0)));
0251
0252
0253
0254
0255
0256
0257 if (stepped <= 0 || regs.gpr[5] != 0x1234) {
0258 show_result("ldarx / stdcx.", "FAIL (ldarx)");
0259 return;
0260 }
0261
0262
0263
0264
0265 regs.gpr[5] = 0x9ABC;
0266
0267
0268 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STDCX(5, 3, 4)));
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq))
0279 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq))))
0280 show_result("ldarx / stdcx.", "PASS");
0281 else
0282 show_result("ldarx / stdcx.", "FAIL (stdcx.)");
0283 }
0284
0285 #ifdef CONFIG_PPC_FPU
0286 static void __init test_lfsx_stfsx(void)
0287 {
0288 struct pt_regs regs;
0289 union {
0290 float a;
0291 int b;
0292 } c;
0293 int cached_b;
0294 int stepped = -1;
0295
0296 init_pt_regs(®s);
0297
0298
0299
0300
0301 c.a = 123.45;
0302 cached_b = c.b;
0303
0304 regs.gpr[3] = (unsigned long) &c.a;
0305 regs.gpr[4] = 0;
0306
0307
0308 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFSX(10, 3, 4)));
0309
0310 if (stepped == 1)
0311 show_result("lfsx", "PASS");
0312 else
0313 show_result("lfsx", "FAIL");
0314
0315
0316
0317
0318 c.a = 678.91;
0319
0320
0321 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFSX(10, 3, 4)));
0322
0323 if (stepped == 1 && c.b == cached_b)
0324 show_result("stfsx", "PASS");
0325 else
0326 show_result("stfsx", "FAIL");
0327 }
0328
0329 static void __init test_plfs_pstfs(void)
0330 {
0331 struct pt_regs regs;
0332 union {
0333 float a;
0334 int b;
0335 } c;
0336 int cached_b;
0337 int stepped = -1;
0338
0339 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0340 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
0341 return;
0342 }
0343
0344 init_pt_regs(®s);
0345
0346
0347
0348
0349 c.a = 123.45;
0350 cached_b = c.b;
0351
0352 regs.gpr[3] = (unsigned long)&c.a;
0353
0354
0355 stepped = emulate_step(®s, TEST_PLFS(10, 3, 0, 0));
0356
0357 if (stepped == 1)
0358 show_result("plfs", "PASS");
0359 else
0360 show_result("plfs", "FAIL");
0361
0362
0363
0364
0365 c.a = 678.91;
0366
0367
0368 stepped = emulate_step(®s, TEST_PSTFS(10, 3, 0, 0));
0369
0370 if (stepped == 1 && c.b == cached_b)
0371 show_result("pstfs", "PASS");
0372 else
0373 show_result("pstfs", "FAIL");
0374 }
0375
0376 static void __init test_lfdx_stfdx(void)
0377 {
0378 struct pt_regs regs;
0379 union {
0380 double a;
0381 long b;
0382 } c;
0383 long cached_b;
0384 int stepped = -1;
0385
0386 init_pt_regs(®s);
0387
0388
0389
0390
0391 c.a = 123456.78;
0392 cached_b = c.b;
0393
0394 regs.gpr[3] = (unsigned long) &c.a;
0395 regs.gpr[4] = 0;
0396
0397
0398 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFDX(10, 3, 4)));
0399
0400 if (stepped == 1)
0401 show_result("lfdx", "PASS");
0402 else
0403 show_result("lfdx", "FAIL");
0404
0405
0406
0407
0408 c.a = 987654.32;
0409
0410
0411 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFDX(10, 3, 4)));
0412
0413 if (stepped == 1 && c.b == cached_b)
0414 show_result("stfdx", "PASS");
0415 else
0416 show_result("stfdx", "FAIL");
0417 }
0418
0419 static void __init test_plfd_pstfd(void)
0420 {
0421 struct pt_regs regs;
0422 union {
0423 double a;
0424 long b;
0425 } c;
0426 long cached_b;
0427 int stepped = -1;
0428
0429 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0430 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)");
0431 return;
0432 }
0433
0434 init_pt_regs(®s);
0435
0436
0437
0438
0439 c.a = 123456.78;
0440 cached_b = c.b;
0441
0442 regs.gpr[3] = (unsigned long)&c.a;
0443
0444
0445 stepped = emulate_step(®s, TEST_PLFD(10, 3, 0, 0));
0446
0447 if (stepped == 1)
0448 show_result("plfd", "PASS");
0449 else
0450 show_result("plfd", "FAIL");
0451
0452
0453
0454
0455 c.a = 987654.32;
0456
0457
0458 stepped = emulate_step(®s, TEST_PSTFD(10, 3, 0, 0));
0459
0460 if (stepped == 1 && c.b == cached_b)
0461 show_result("pstfd", "PASS");
0462 else
0463 show_result("pstfd", "FAIL");
0464 }
0465 #else
0466 static void __init test_lfsx_stfsx(void)
0467 {
0468 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)");
0469 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)");
0470 }
0471
0472 static void __init test_plfs_pstfs(void)
0473 {
0474 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)");
0475 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)");
0476 }
0477
0478 static void __init test_lfdx_stfdx(void)
0479 {
0480 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)");
0481 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)");
0482 }
0483
0484 static void __init test_plfd_pstfd(void)
0485 {
0486 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)");
0487 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)");
0488 }
0489 #endif
0490
0491 #ifdef CONFIG_ALTIVEC
0492 static void __init test_lvx_stvx(void)
0493 {
0494 struct pt_regs regs;
0495 union {
0496 vector128 a;
0497 u32 b[4];
0498 } c;
0499 u32 cached_b[4];
0500 int stepped = -1;
0501
0502 init_pt_regs(®s);
0503
0504
0505
0506
0507 cached_b[0] = c.b[0] = 923745;
0508 cached_b[1] = c.b[1] = 2139478;
0509 cached_b[2] = c.b[2] = 9012;
0510 cached_b[3] = c.b[3] = 982134;
0511
0512 regs.gpr[3] = (unsigned long) &c.a;
0513 regs.gpr[4] = 0;
0514
0515
0516 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LVX(10, 3, 4)));
0517
0518 if (stepped == 1)
0519 show_result("lvx", "PASS");
0520 else
0521 show_result("lvx", "FAIL");
0522
0523
0524
0525
0526 c.b[0] = 4987513;
0527 c.b[1] = 84313948;
0528 c.b[2] = 71;
0529 c.b[3] = 498532;
0530
0531
0532 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STVX(10, 3, 4)));
0533
0534 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
0535 cached_b[2] == c.b[2] && cached_b[3] == c.b[3])
0536 show_result("stvx", "PASS");
0537 else
0538 show_result("stvx", "FAIL");
0539 }
0540 #else
0541 static void __init test_lvx_stvx(void)
0542 {
0543 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)");
0544 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)");
0545 }
0546 #endif
0547
0548 #ifdef CONFIG_VSX
0549 static void __init test_lxvd2x_stxvd2x(void)
0550 {
0551 struct pt_regs regs;
0552 union {
0553 vector128 a;
0554 u32 b[4];
0555 } c;
0556 u32 cached_b[4];
0557 int stepped = -1;
0558
0559 init_pt_regs(®s);
0560
0561
0562
0563
0564 cached_b[0] = c.b[0] = 18233;
0565 cached_b[1] = c.b[1] = 34863571;
0566 cached_b[2] = c.b[2] = 834;
0567 cached_b[3] = c.b[3] = 6138911;
0568
0569 regs.gpr[3] = (unsigned long) &c.a;
0570 regs.gpr[4] = 0;
0571
0572
0573 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4)));
0574
0575 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
0576 show_result("lxvd2x", "PASS");
0577 } else {
0578 if (!cpu_has_feature(CPU_FTR_VSX))
0579 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)");
0580 else
0581 show_result("lxvd2x", "FAIL");
0582 }
0583
0584
0585
0586
0587 c.b[0] = 21379463;
0588 c.b[1] = 87;
0589 c.b[2] = 374234;
0590 c.b[3] = 4;
0591
0592
0593 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4)));
0594
0595 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] &&
0596 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] &&
0597 cpu_has_feature(CPU_FTR_VSX)) {
0598 show_result("stxvd2x", "PASS");
0599 } else {
0600 if (!cpu_has_feature(CPU_FTR_VSX))
0601 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)");
0602 else
0603 show_result("stxvd2x", "FAIL");
0604 }
0605 }
0606 #else
0607 static void __init test_lxvd2x_stxvd2x(void)
0608 {
0609 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)");
0610 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)");
0611 }
0612 #endif
0613
0614 #ifdef CONFIG_VSX
0615 static void __init test_lxvp_stxvp(void)
0616 {
0617 struct pt_regs regs;
0618 union {
0619 vector128 a;
0620 u32 b[4];
0621 } c[2];
0622 u32 cached_b[8];
0623 int stepped = -1;
0624
0625 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0626 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)");
0627 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)");
0628 return;
0629 }
0630
0631 init_pt_regs(®s);
0632
0633
0634
0635 cached_b[0] = c[0].b[0] = 18233;
0636 cached_b[1] = c[0].b[1] = 34863571;
0637 cached_b[2] = c[0].b[2] = 834;
0638 cached_b[3] = c[0].b[3] = 6138911;
0639 cached_b[4] = c[1].b[0] = 1234;
0640 cached_b[5] = c[1].b[1] = 5678;
0641 cached_b[6] = c[1].b[2] = 91011;
0642 cached_b[7] = c[1].b[3] = 121314;
0643
0644 regs.gpr[4] = (unsigned long)&c[0].a;
0645
0646
0647
0648
0649
0650
0651 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVP(34, 4, 0)));
0652
0653 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
0654 show_result("lxvp", "PASS");
0655 } else {
0656 if (!cpu_has_feature(CPU_FTR_VSX))
0657 show_result("lxvp", "PASS (!CPU_FTR_VSX)");
0658 else
0659 show_result("lxvp", "FAIL");
0660 }
0661
0662
0663
0664 c[0].b[0] = 21379463;
0665 c[0].b[1] = 87;
0666 c[0].b[2] = 374234;
0667 c[0].b[3] = 4;
0668 c[1].b[0] = 90;
0669 c[1].b[1] = 122;
0670 c[1].b[2] = 555;
0671 c[1].b[3] = 32144;
0672
0673
0674
0675
0676
0677
0678 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVP(34, 4, 0)));
0679
0680 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
0681 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
0682 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
0683 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
0684 cpu_has_feature(CPU_FTR_VSX)) {
0685 show_result("stxvp", "PASS");
0686 } else {
0687 if (!cpu_has_feature(CPU_FTR_VSX))
0688 show_result("stxvp", "PASS (!CPU_FTR_VSX)");
0689 else
0690 show_result("stxvp", "FAIL");
0691 }
0692 }
0693 #else
0694 static void __init test_lxvp_stxvp(void)
0695 {
0696 show_result("lxvp", "SKIP (CONFIG_VSX is not set)");
0697 show_result("stxvp", "SKIP (CONFIG_VSX is not set)");
0698 }
0699 #endif
0700
0701 #ifdef CONFIG_VSX
0702 static void __init test_lxvpx_stxvpx(void)
0703 {
0704 struct pt_regs regs;
0705 union {
0706 vector128 a;
0707 u32 b[4];
0708 } c[2];
0709 u32 cached_b[8];
0710 int stepped = -1;
0711
0712 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0713 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)");
0714 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)");
0715 return;
0716 }
0717
0718 init_pt_regs(®s);
0719
0720
0721
0722 cached_b[0] = c[0].b[0] = 18233;
0723 cached_b[1] = c[0].b[1] = 34863571;
0724 cached_b[2] = c[0].b[2] = 834;
0725 cached_b[3] = c[0].b[3] = 6138911;
0726 cached_b[4] = c[1].b[0] = 1234;
0727 cached_b[5] = c[1].b[1] = 5678;
0728 cached_b[6] = c[1].b[2] = 91011;
0729 cached_b[7] = c[1].b[3] = 121314;
0730
0731 regs.gpr[3] = (unsigned long)&c[0].a;
0732 regs.gpr[4] = 0;
0733
0734
0735
0736
0737
0738
0739 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVPX(34, 3, 4)));
0740
0741 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
0742 show_result("lxvpx", "PASS");
0743 } else {
0744 if (!cpu_has_feature(CPU_FTR_VSX))
0745 show_result("lxvpx", "PASS (!CPU_FTR_VSX)");
0746 else
0747 show_result("lxvpx", "FAIL");
0748 }
0749
0750
0751
0752 c[0].b[0] = 21379463;
0753 c[0].b[1] = 87;
0754 c[0].b[2] = 374234;
0755 c[0].b[3] = 4;
0756 c[1].b[0] = 90;
0757 c[1].b[1] = 122;
0758 c[1].b[2] = 555;
0759 c[1].b[3] = 32144;
0760
0761
0762
0763
0764
0765
0766 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVPX(34, 3, 4)));
0767
0768 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
0769 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
0770 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
0771 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
0772 cpu_has_feature(CPU_FTR_VSX)) {
0773 show_result("stxvpx", "PASS");
0774 } else {
0775 if (!cpu_has_feature(CPU_FTR_VSX))
0776 show_result("stxvpx", "PASS (!CPU_FTR_VSX)");
0777 else
0778 show_result("stxvpx", "FAIL");
0779 }
0780 }
0781 #else
0782 static void __init test_lxvpx_stxvpx(void)
0783 {
0784 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)");
0785 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)");
0786 }
0787 #endif
0788
0789 #ifdef CONFIG_VSX
0790 static void __init test_plxvp_pstxvp(void)
0791 {
0792 ppc_inst_t instr;
0793 struct pt_regs regs;
0794 union {
0795 vector128 a;
0796 u32 b[4];
0797 } c[2];
0798 u32 cached_b[8];
0799 int stepped = -1;
0800
0801 if (!cpu_has_feature(CPU_FTR_ARCH_31)) {
0802 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)");
0803 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)");
0804 return;
0805 }
0806
0807
0808
0809 cached_b[0] = c[0].b[0] = 18233;
0810 cached_b[1] = c[0].b[1] = 34863571;
0811 cached_b[2] = c[0].b[2] = 834;
0812 cached_b[3] = c[0].b[3] = 6138911;
0813 cached_b[4] = c[1].b[0] = 1234;
0814 cached_b[5] = c[1].b[1] = 5678;
0815 cached_b[6] = c[1].b[2] = 91011;
0816 cached_b[7] = c[1].b[3] = 121314;
0817
0818 init_pt_regs(®s);
0819 regs.gpr[3] = (unsigned long)&c[0].a;
0820
0821
0822
0823
0824
0825
0826 instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0));
0827
0828 stepped = emulate_step(®s, instr);
0829 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) {
0830 show_result("plxvp", "PASS");
0831 } else {
0832 if (!cpu_has_feature(CPU_FTR_VSX))
0833 show_result("plxvp", "PASS (!CPU_FTR_VSX)");
0834 else
0835 show_result("plxvp", "FAIL");
0836 }
0837
0838
0839
0840 c[0].b[0] = 21379463;
0841 c[0].b[1] = 87;
0842 c[0].b[2] = 374234;
0843 c[0].b[3] = 4;
0844 c[1].b[0] = 90;
0845 c[1].b[1] = 122;
0846 c[1].b[2] = 555;
0847 c[1].b[3] = 32144;
0848
0849
0850
0851
0852
0853
0854 instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0));
0855
0856 stepped = emulate_step(®s, instr);
0857
0858 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] &&
0859 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] &&
0860 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] &&
0861 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] &&
0862 cpu_has_feature(CPU_FTR_VSX)) {
0863 show_result("pstxvp", "PASS");
0864 } else {
0865 if (!cpu_has_feature(CPU_FTR_VSX))
0866 show_result("pstxvp", "PASS (!CPU_FTR_VSX)");
0867 else
0868 show_result("pstxvp", "FAIL");
0869 }
0870 }
0871 #else
0872 static void __init test_plxvp_pstxvp(void)
0873 {
0874 show_result("plxvp", "SKIP (CONFIG_VSX is not set)");
0875 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)");
0876 }
0877 #endif
0878
0879 static void __init run_tests_load_store(void)
0880 {
0881 test_ld();
0882 test_pld();
0883 test_lwz();
0884 test_plwz();
0885 test_lwzx();
0886 test_std();
0887 test_pstd();
0888 test_ldarx_stdcx();
0889 test_lfsx_stfsx();
0890 test_plfs_pstfs();
0891 test_lfdx_stfdx();
0892 test_plfd_pstfd();
0893 test_lvx_stvx();
0894 test_lxvd2x_stxvd2x();
0895 test_lxvp_stxvp();
0896 test_lxvpx_stxvpx();
0897 test_plxvp_pstxvp();
0898 }
0899
0900 struct compute_test {
0901 char *mnemonic;
0902 unsigned long cpu_feature;
0903 struct {
0904 char *descr;
0905 unsigned long flags;
0906 ppc_inst_t instr;
0907 struct pt_regs regs;
0908 } subtests[MAX_SUBTESTS + 1];
0909 };
0910
0911
0912 #define SI_MIN BIT(33)
0913 #define SI_MAX (BIT(33) - 1)
0914 #define SI_UMAX (BIT(34) - 1)
0915
0916 static struct compute_test compute_tests[] = {
0917 {
0918 .mnemonic = "nop",
0919 .subtests = {
0920 {
0921 .descr = "R0 = LONG_MAX",
0922 .instr = ppc_inst(PPC_RAW_NOP()),
0923 .regs = {
0924 .gpr[0] = LONG_MAX,
0925 }
0926 }
0927 }
0928 },
0929 {
0930 .mnemonic = "setb",
0931 .cpu_feature = CPU_FTR_ARCH_300,
0932 .subtests = {
0933 {
0934 .descr = "BFA = 1, CR = GT",
0935 .instr = ppc_inst(PPC_RAW_SETB(20, 1)),
0936 .regs = {
0937 .ccr = 0x4000000,
0938 }
0939 },
0940 {
0941 .descr = "BFA = 4, CR = LT",
0942 .instr = ppc_inst(PPC_RAW_SETB(20, 4)),
0943 .regs = {
0944 .ccr = 0x8000,
0945 }
0946 },
0947 {
0948 .descr = "BFA = 5, CR = EQ",
0949 .instr = ppc_inst(PPC_RAW_SETB(20, 5)),
0950 .regs = {
0951 .ccr = 0x200,
0952 }
0953 }
0954 }
0955 },
0956 {
0957 .mnemonic = "add",
0958 .subtests = {
0959 {
0960 .descr = "RA = LONG_MIN, RB = LONG_MIN",
0961 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
0962 .regs = {
0963 .gpr[21] = LONG_MIN,
0964 .gpr[22] = LONG_MIN,
0965 }
0966 },
0967 {
0968 .descr = "RA = LONG_MIN, RB = LONG_MAX",
0969 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
0970 .regs = {
0971 .gpr[21] = LONG_MIN,
0972 .gpr[22] = LONG_MAX,
0973 }
0974 },
0975 {
0976 .descr = "RA = LONG_MAX, RB = LONG_MAX",
0977 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
0978 .regs = {
0979 .gpr[21] = LONG_MAX,
0980 .gpr[22] = LONG_MAX,
0981 }
0982 },
0983 {
0984 .descr = "RA = ULONG_MAX, RB = ULONG_MAX",
0985 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
0986 .regs = {
0987 .gpr[21] = ULONG_MAX,
0988 .gpr[22] = ULONG_MAX,
0989 }
0990 },
0991 {
0992 .descr = "RA = ULONG_MAX, RB = 0x1",
0993 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)),
0994 .regs = {
0995 .gpr[21] = ULONG_MAX,
0996 .gpr[22] = 0x1,
0997 }
0998 },
0999 {
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
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
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
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
1683
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
1691 passed = rc;
1692 goto print;
1693 } else if (rc || execute_compute_instr(&exp, instr)) {
1694 passed = false;
1695 goto print;
1696 }
1697
1698
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
1708 if (exp.link != got.link) {
1709 passed = false;
1710 reg_mismatch("LR", exp.link, got.link);
1711 }
1712
1713
1714 if (!ignore_xer && exp.xer != got.xer) {
1715 passed = false;
1716 reg_mismatch("XER", exp.xer, got.xer);
1717 }
1718
1719
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);