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