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/sstep.h> 12 #include <asm/ppc-opcode.h> 13 #include <asm/code-patching.h> 14 #include <asm/inst.h> 15 16 #define MAX_SUBTESTS 16 17 18 #define IGNORE_GPR(n) (0x1UL << (n)) 19 #define IGNORE_XER (0x1UL << 32) 20 #define IGNORE_CCR (0x1UL << 33) 21 22 #define TEST_PLD(r, base, i, pr) \ 23 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \ 24 PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 25 26 #define TEST_PLWZ(r, base, i, pr) \ 27 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 28 PPC_RAW_LWZ(r, base, i)) 29 30 #define TEST_PSTD(r, base, i, pr) \ 31 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \ 32 PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 33 34 #define TEST_PLFS(r, base, i, pr) \ 35 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 36 PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 37 38 #define TEST_PSTFS(r, base, i, pr) \ 39 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 40 PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 41 42 #define TEST_PLFD(r, base, i, pr) \ 43 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 44 PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 45 46 #define TEST_PSTFD(r, base, i, pr) \ 47 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 48 PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 49 50 static void __init init_pt_regs(struct pt_regs *regs) 51 { 52 static unsigned long msr; 53 static bool msr_cached; 54 55 memset(regs, 0, sizeof(struct pt_regs)); 56 57 if (likely(msr_cached)) { 58 regs->msr = msr; 59 return; 60 } 61 62 asm volatile("mfmsr %0" : "=r"(regs->msr)); 63 64 regs->msr |= MSR_FP; 65 regs->msr |= MSR_VEC; 66 regs->msr |= MSR_VSX; 67 68 msr = regs->msr; 69 msr_cached = true; 70 } 71 72 static void __init show_result(char *mnemonic, char *result) 73 { 74 pr_info("%-14s : %s\n", mnemonic, result); 75 } 76 77 static void __init show_result_with_descr(char *mnemonic, char *descr, 78 char *result) 79 { 80 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result); 81 } 82 83 static void __init test_ld(void) 84 { 85 struct pt_regs regs; 86 unsigned long a = 0x23; 87 int stepped = -1; 88 89 init_pt_regs(®s); 90 regs.gpr[3] = (unsigned long) &a; 91 92 /* ld r5, 0(r3) */ 93 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LD(5, 3, 0))); 94 95 if (stepped == 1 && regs.gpr[5] == a) 96 show_result("ld", "PASS"); 97 else 98 show_result("ld", "FAIL"); 99 } 100 101 static void __init test_pld(void) 102 { 103 struct pt_regs regs; 104 unsigned long a = 0x23; 105 int stepped = -1; 106 107 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 108 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 109 return; 110 } 111 112 init_pt_regs(®s); 113 regs.gpr[3] = (unsigned long)&a; 114 115 /* pld r5, 0(r3), 0 */ 116 stepped = emulate_step(®s, TEST_PLD(5, 3, 0, 0)); 117 118 if (stepped == 1 && regs.gpr[5] == a) 119 show_result("pld", "PASS"); 120 else 121 show_result("pld", "FAIL"); 122 } 123 124 static void __init test_lwz(void) 125 { 126 struct pt_regs regs; 127 unsigned int a = 0x4545; 128 int stepped = -1; 129 130 init_pt_regs(®s); 131 regs.gpr[3] = (unsigned long) &a; 132 133 /* lwz r5, 0(r3) */ 134 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZ(5, 3, 0))); 135 136 if (stepped == 1 && regs.gpr[5] == a) 137 show_result("lwz", "PASS"); 138 else 139 show_result("lwz", "FAIL"); 140 } 141 142 static void __init test_plwz(void) 143 { 144 struct pt_regs regs; 145 unsigned int a = 0x4545; 146 int stepped = -1; 147 148 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 149 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)"); 150 return; 151 } 152 153 init_pt_regs(®s); 154 regs.gpr[3] = (unsigned long)&a; 155 156 /* plwz r5, 0(r3), 0 */ 157 158 stepped = emulate_step(®s, TEST_PLWZ(5, 3, 0, 0)); 159 160 if (stepped == 1 && regs.gpr[5] == a) 161 show_result("plwz", "PASS"); 162 else 163 show_result("plwz", "FAIL"); 164 } 165 166 static void __init test_lwzx(void) 167 { 168 struct pt_regs regs; 169 unsigned int a[3] = {0x0, 0x0, 0x1234}; 170 int stepped = -1; 171 172 init_pt_regs(®s); 173 regs.gpr[3] = (unsigned long) a; 174 regs.gpr[4] = 8; 175 regs.gpr[5] = 0x8765; 176 177 /* lwzx r5, r3, r4 */ 178 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZX(5, 3, 4))); 179 if (stepped == 1 && regs.gpr[5] == a[2]) 180 show_result("lwzx", "PASS"); 181 else 182 show_result("lwzx", "FAIL"); 183 } 184 185 static void __init test_std(void) 186 { 187 struct pt_regs regs; 188 unsigned long a = 0x1234; 189 int stepped = -1; 190 191 init_pt_regs(®s); 192 regs.gpr[3] = (unsigned long) &a; 193 regs.gpr[5] = 0x5678; 194 195 /* std r5, 0(r3) */ 196 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STD(5, 3, 0))); 197 if (stepped == 1 && regs.gpr[5] == a) 198 show_result("std", "PASS"); 199 else 200 show_result("std", "FAIL"); 201 } 202 203 static void __init test_pstd(void) 204 { 205 struct pt_regs regs; 206 unsigned long a = 0x1234; 207 int stepped = -1; 208 209 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 210 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)"); 211 return; 212 } 213 214 init_pt_regs(®s); 215 regs.gpr[3] = (unsigned long)&a; 216 regs.gpr[5] = 0x5678; 217 218 /* pstd r5, 0(r3), 0 */ 219 stepped = emulate_step(®s, TEST_PSTD(5, 3, 0, 0)); 220 if (stepped == 1 || regs.gpr[5] == a) 221 show_result("pstd", "PASS"); 222 else 223 show_result("pstd", "FAIL"); 224 } 225 226 static void __init test_ldarx_stdcx(void) 227 { 228 struct pt_regs regs; 229 unsigned long a = 0x1234; 230 int stepped = -1; 231 unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */ 232 233 init_pt_regs(®s); 234 asm volatile("mfcr %0" : "=r"(regs.ccr)); 235 236 237 /*** ldarx ***/ 238 239 regs.gpr[3] = (unsigned long) &a; 240 regs.gpr[4] = 0; 241 regs.gpr[5] = 0x5678; 242 243 /* ldarx r5, r3, r4, 0 */ 244 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0))); 245 246 /* 247 * Don't touch 'a' here. Touching 'a' can do Load/store 248 * of 'a' which result in failure of subsequent stdcx. 249 * Instead, use hardcoded value for comparison. 250 */ 251 if (stepped <= 0 || regs.gpr[5] != 0x1234) { 252 show_result("ldarx / stdcx.", "FAIL (ldarx)"); 253 return; 254 } 255 256 257 /*** stdcx. ***/ 258 259 regs.gpr[5] = 0x9ABC; 260 261 /* stdcx. r5, r3, r4 */ 262 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STDCX(5, 3, 4))); 263 264 /* 265 * Two possible scenarios that indicates successful emulation 266 * of stdcx. : 267 * 1. Reservation is active and store is performed. In this 268 * case cr0.eq bit will be set to 1. 269 * 2. Reservation is not active and store is not performed. 270 * In this case cr0.eq bit will be set to 0. 271 */ 272 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq)) 273 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq)))) 274 show_result("ldarx / stdcx.", "PASS"); 275 else 276 show_result("ldarx / stdcx.", "FAIL (stdcx.)"); 277 } 278 279 #ifdef CONFIG_PPC_FPU 280 static void __init test_lfsx_stfsx(void) 281 { 282 struct pt_regs regs; 283 union { 284 float a; 285 int b; 286 } c; 287 int cached_b; 288 int stepped = -1; 289 290 init_pt_regs(®s); 291 292 293 /*** lfsx ***/ 294 295 c.a = 123.45; 296 cached_b = c.b; 297 298 regs.gpr[3] = (unsigned long) &c.a; 299 regs.gpr[4] = 0; 300 301 /* lfsx frt10, r3, r4 */ 302 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFSX(10, 3, 4))); 303 304 if (stepped == 1) 305 show_result("lfsx", "PASS"); 306 else 307 show_result("lfsx", "FAIL"); 308 309 310 /*** stfsx ***/ 311 312 c.a = 678.91; 313 314 /* stfsx frs10, r3, r4 */ 315 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFSX(10, 3, 4))); 316 317 if (stepped == 1 && c.b == cached_b) 318 show_result("stfsx", "PASS"); 319 else 320 show_result("stfsx", "FAIL"); 321 } 322 323 static void __init test_plfs_pstfs(void) 324 { 325 struct pt_regs regs; 326 union { 327 float a; 328 int b; 329 } c; 330 int cached_b; 331 int stepped = -1; 332 333 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 334 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 335 return; 336 } 337 338 init_pt_regs(®s); 339 340 341 /*** plfs ***/ 342 343 c.a = 123.45; 344 cached_b = c.b; 345 346 regs.gpr[3] = (unsigned long)&c.a; 347 348 /* plfs frt10, 0(r3), 0 */ 349 stepped = emulate_step(®s, TEST_PLFS(10, 3, 0, 0)); 350 351 if (stepped == 1) 352 show_result("plfs", "PASS"); 353 else 354 show_result("plfs", "FAIL"); 355 356 357 /*** pstfs ***/ 358 359 c.a = 678.91; 360 361 /* pstfs frs10, 0(r3), 0 */ 362 stepped = emulate_step(®s, TEST_PSTFS(10, 3, 0, 0)); 363 364 if (stepped == 1 && c.b == cached_b) 365 show_result("pstfs", "PASS"); 366 else 367 show_result("pstfs", "FAIL"); 368 } 369 370 static void __init test_lfdx_stfdx(void) 371 { 372 struct pt_regs regs; 373 union { 374 double a; 375 long b; 376 } c; 377 long cached_b; 378 int stepped = -1; 379 380 init_pt_regs(®s); 381 382 383 /*** lfdx ***/ 384 385 c.a = 123456.78; 386 cached_b = c.b; 387 388 regs.gpr[3] = (unsigned long) &c.a; 389 regs.gpr[4] = 0; 390 391 /* lfdx frt10, r3, r4 */ 392 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFDX(10, 3, 4))); 393 394 if (stepped == 1) 395 show_result("lfdx", "PASS"); 396 else 397 show_result("lfdx", "FAIL"); 398 399 400 /*** stfdx ***/ 401 402 c.a = 987654.32; 403 404 /* stfdx frs10, r3, r4 */ 405 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFDX(10, 3, 4))); 406 407 if (stepped == 1 && c.b == cached_b) 408 show_result("stfdx", "PASS"); 409 else 410 show_result("stfdx", "FAIL"); 411 } 412 413 static void __init test_plfd_pstfd(void) 414 { 415 struct pt_regs regs; 416 union { 417 double a; 418 long b; 419 } c; 420 long cached_b; 421 int stepped = -1; 422 423 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 424 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 425 return; 426 } 427 428 init_pt_regs(®s); 429 430 431 /*** plfd ***/ 432 433 c.a = 123456.78; 434 cached_b = c.b; 435 436 regs.gpr[3] = (unsigned long)&c.a; 437 438 /* plfd frt10, 0(r3), 0 */ 439 stepped = emulate_step(®s, TEST_PLFD(10, 3, 0, 0)); 440 441 if (stepped == 1) 442 show_result("plfd", "PASS"); 443 else 444 show_result("plfd", "FAIL"); 445 446 447 /*** pstfd ***/ 448 449 c.a = 987654.32; 450 451 /* pstfd frs10, 0(r3), 0 */ 452 stepped = emulate_step(®s, TEST_PSTFD(10, 3, 0, 0)); 453 454 if (stepped == 1 && c.b == cached_b) 455 show_result("pstfd", "PASS"); 456 else 457 show_result("pstfd", "FAIL"); 458 } 459 #else 460 static void __init test_lfsx_stfsx(void) 461 { 462 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 463 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 464 } 465 466 static void __init test_plfs_pstfs(void) 467 { 468 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)"); 469 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)"); 470 } 471 472 static void __init test_lfdx_stfdx(void) 473 { 474 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 475 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 476 } 477 478 static void __init test_plfd_pstfd(void) 479 { 480 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)"); 481 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)"); 482 } 483 #endif /* CONFIG_PPC_FPU */ 484 485 #ifdef CONFIG_ALTIVEC 486 static void __init test_lvx_stvx(void) 487 { 488 struct pt_regs regs; 489 union { 490 vector128 a; 491 u32 b[4]; 492 } c; 493 u32 cached_b[4]; 494 int stepped = -1; 495 496 init_pt_regs(®s); 497 498 499 /*** lvx ***/ 500 501 cached_b[0] = c.b[0] = 923745; 502 cached_b[1] = c.b[1] = 2139478; 503 cached_b[2] = c.b[2] = 9012; 504 cached_b[3] = c.b[3] = 982134; 505 506 regs.gpr[3] = (unsigned long) &c.a; 507 regs.gpr[4] = 0; 508 509 /* lvx vrt10, r3, r4 */ 510 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LVX(10, 3, 4))); 511 512 if (stepped == 1) 513 show_result("lvx", "PASS"); 514 else 515 show_result("lvx", "FAIL"); 516 517 518 /*** stvx ***/ 519 520 c.b[0] = 4987513; 521 c.b[1] = 84313948; 522 c.b[2] = 71; 523 c.b[3] = 498532; 524 525 /* stvx vrs10, r3, r4 */ 526 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STVX(10, 3, 4))); 527 528 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 529 cached_b[2] == c.b[2] && cached_b[3] == c.b[3]) 530 show_result("stvx", "PASS"); 531 else 532 show_result("stvx", "FAIL"); 533 } 534 #else 535 static void __init test_lvx_stvx(void) 536 { 537 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)"); 538 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)"); 539 } 540 #endif /* CONFIG_ALTIVEC */ 541 542 #ifdef CONFIG_VSX 543 static void __init test_lxvd2x_stxvd2x(void) 544 { 545 struct pt_regs regs; 546 union { 547 vector128 a; 548 u32 b[4]; 549 } c; 550 u32 cached_b[4]; 551 int stepped = -1; 552 553 init_pt_regs(®s); 554 555 556 /*** lxvd2x ***/ 557 558 cached_b[0] = c.b[0] = 18233; 559 cached_b[1] = c.b[1] = 34863571; 560 cached_b[2] = c.b[2] = 834; 561 cached_b[3] = c.b[3] = 6138911; 562 563 regs.gpr[3] = (unsigned long) &c.a; 564 regs.gpr[4] = 0; 565 566 /* lxvd2x vsr39, r3, r4 */ 567 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4))); 568 569 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 570 show_result("lxvd2x", "PASS"); 571 } else { 572 if (!cpu_has_feature(CPU_FTR_VSX)) 573 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)"); 574 else 575 show_result("lxvd2x", "FAIL"); 576 } 577 578 579 /*** stxvd2x ***/ 580 581 c.b[0] = 21379463; 582 c.b[1] = 87; 583 c.b[2] = 374234; 584 c.b[3] = 4; 585 586 /* stxvd2x vsr39, r3, r4 */ 587 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4))); 588 589 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 590 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] && 591 cpu_has_feature(CPU_FTR_VSX)) { 592 show_result("stxvd2x", "PASS"); 593 } else { 594 if (!cpu_has_feature(CPU_FTR_VSX)) 595 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)"); 596 else 597 show_result("stxvd2x", "FAIL"); 598 } 599 } 600 #else 601 static void __init test_lxvd2x_stxvd2x(void) 602 { 603 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)"); 604 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)"); 605 } 606 #endif /* CONFIG_VSX */ 607 608 static void __init run_tests_load_store(void) 609 { 610 test_ld(); 611 test_pld(); 612 test_lwz(); 613 test_plwz(); 614 test_lwzx(); 615 test_std(); 616 test_pstd(); 617 test_ldarx_stdcx(); 618 test_lfsx_stfsx(); 619 test_plfs_pstfs(); 620 test_lfdx_stfdx(); 621 test_plfd_pstfd(); 622 test_lvx_stvx(); 623 test_lxvd2x_stxvd2x(); 624 } 625 626 struct compute_test { 627 char *mnemonic; 628 unsigned long cpu_feature; 629 struct { 630 char *descr; 631 unsigned long flags; 632 struct ppc_inst instr; 633 struct pt_regs regs; 634 } subtests[MAX_SUBTESTS + 1]; 635 }; 636 637 static struct compute_test compute_tests[] = { 638 { 639 .mnemonic = "nop", 640 .subtests = { 641 { 642 .descr = "R0 = LONG_MAX", 643 .instr = ppc_inst(PPC_INST_NOP), 644 .regs = { 645 .gpr[0] = LONG_MAX, 646 } 647 } 648 } 649 }, 650 { 651 .mnemonic = "add", 652 .subtests = { 653 { 654 .descr = "RA = LONG_MIN, RB = LONG_MIN", 655 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 656 .regs = { 657 .gpr[21] = LONG_MIN, 658 .gpr[22] = LONG_MIN, 659 } 660 }, 661 { 662 .descr = "RA = LONG_MIN, RB = LONG_MAX", 663 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 664 .regs = { 665 .gpr[21] = LONG_MIN, 666 .gpr[22] = LONG_MAX, 667 } 668 }, 669 { 670 .descr = "RA = LONG_MAX, RB = LONG_MAX", 671 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 672 .regs = { 673 .gpr[21] = LONG_MAX, 674 .gpr[22] = LONG_MAX, 675 } 676 }, 677 { 678 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 679 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 680 .regs = { 681 .gpr[21] = ULONG_MAX, 682 .gpr[22] = ULONG_MAX, 683 } 684 }, 685 { 686 .descr = "RA = ULONG_MAX, RB = 0x1", 687 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 688 .regs = { 689 .gpr[21] = ULONG_MAX, 690 .gpr[22] = 0x1, 691 } 692 }, 693 { 694 .descr = "RA = INT_MIN, RB = INT_MIN", 695 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 696 .regs = { 697 .gpr[21] = INT_MIN, 698 .gpr[22] = INT_MIN, 699 } 700 }, 701 { 702 .descr = "RA = INT_MIN, RB = INT_MAX", 703 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 704 .regs = { 705 .gpr[21] = INT_MIN, 706 .gpr[22] = INT_MAX, 707 } 708 }, 709 { 710 .descr = "RA = INT_MAX, RB = INT_MAX", 711 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 712 .regs = { 713 .gpr[21] = INT_MAX, 714 .gpr[22] = INT_MAX, 715 } 716 }, 717 { 718 .descr = "RA = UINT_MAX, RB = UINT_MAX", 719 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 720 .regs = { 721 .gpr[21] = UINT_MAX, 722 .gpr[22] = UINT_MAX, 723 } 724 }, 725 { 726 .descr = "RA = UINT_MAX, RB = 0x1", 727 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 728 .regs = { 729 .gpr[21] = UINT_MAX, 730 .gpr[22] = 0x1, 731 } 732 } 733 } 734 }, 735 { 736 .mnemonic = "add.", 737 .subtests = { 738 { 739 .descr = "RA = LONG_MIN, RB = LONG_MIN", 740 .flags = IGNORE_CCR, 741 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 742 .regs = { 743 .gpr[21] = LONG_MIN, 744 .gpr[22] = LONG_MIN, 745 } 746 }, 747 { 748 .descr = "RA = LONG_MIN, RB = LONG_MAX", 749 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 750 .regs = { 751 .gpr[21] = LONG_MIN, 752 .gpr[22] = LONG_MAX, 753 } 754 }, 755 { 756 .descr = "RA = LONG_MAX, RB = LONG_MAX", 757 .flags = IGNORE_CCR, 758 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 759 .regs = { 760 .gpr[21] = LONG_MAX, 761 .gpr[22] = LONG_MAX, 762 } 763 }, 764 { 765 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 766 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 767 .regs = { 768 .gpr[21] = ULONG_MAX, 769 .gpr[22] = ULONG_MAX, 770 } 771 }, 772 { 773 .descr = "RA = ULONG_MAX, RB = 0x1", 774 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 775 .regs = { 776 .gpr[21] = ULONG_MAX, 777 .gpr[22] = 0x1, 778 } 779 }, 780 { 781 .descr = "RA = INT_MIN, RB = INT_MIN", 782 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 783 .regs = { 784 .gpr[21] = INT_MIN, 785 .gpr[22] = INT_MIN, 786 } 787 }, 788 { 789 .descr = "RA = INT_MIN, RB = INT_MAX", 790 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 791 .regs = { 792 .gpr[21] = INT_MIN, 793 .gpr[22] = INT_MAX, 794 } 795 }, 796 { 797 .descr = "RA = INT_MAX, RB = INT_MAX", 798 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 799 .regs = { 800 .gpr[21] = INT_MAX, 801 .gpr[22] = INT_MAX, 802 } 803 }, 804 { 805 .descr = "RA = UINT_MAX, RB = UINT_MAX", 806 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 807 .regs = { 808 .gpr[21] = UINT_MAX, 809 .gpr[22] = UINT_MAX, 810 } 811 }, 812 { 813 .descr = "RA = UINT_MAX, RB = 0x1", 814 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 815 .regs = { 816 .gpr[21] = UINT_MAX, 817 .gpr[22] = 0x1, 818 } 819 } 820 } 821 }, 822 { 823 .mnemonic = "addc", 824 .subtests = { 825 { 826 .descr = "RA = LONG_MIN, RB = LONG_MIN", 827 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 828 .regs = { 829 .gpr[21] = LONG_MIN, 830 .gpr[22] = LONG_MIN, 831 } 832 }, 833 { 834 .descr = "RA = LONG_MIN, RB = LONG_MAX", 835 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 836 .regs = { 837 .gpr[21] = LONG_MIN, 838 .gpr[22] = LONG_MAX, 839 } 840 }, 841 { 842 .descr = "RA = LONG_MAX, RB = LONG_MAX", 843 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 844 .regs = { 845 .gpr[21] = LONG_MAX, 846 .gpr[22] = LONG_MAX, 847 } 848 }, 849 { 850 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 851 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 852 .regs = { 853 .gpr[21] = ULONG_MAX, 854 .gpr[22] = ULONG_MAX, 855 } 856 }, 857 { 858 .descr = "RA = ULONG_MAX, RB = 0x1", 859 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 860 .regs = { 861 .gpr[21] = ULONG_MAX, 862 .gpr[22] = 0x1, 863 } 864 }, 865 { 866 .descr = "RA = INT_MIN, RB = INT_MIN", 867 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 868 .regs = { 869 .gpr[21] = INT_MIN, 870 .gpr[22] = INT_MIN, 871 } 872 }, 873 { 874 .descr = "RA = INT_MIN, RB = INT_MAX", 875 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 876 .regs = { 877 .gpr[21] = INT_MIN, 878 .gpr[22] = INT_MAX, 879 } 880 }, 881 { 882 .descr = "RA = INT_MAX, RB = INT_MAX", 883 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 884 .regs = { 885 .gpr[21] = INT_MAX, 886 .gpr[22] = INT_MAX, 887 } 888 }, 889 { 890 .descr = "RA = UINT_MAX, RB = UINT_MAX", 891 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 892 .regs = { 893 .gpr[21] = UINT_MAX, 894 .gpr[22] = UINT_MAX, 895 } 896 }, 897 { 898 .descr = "RA = UINT_MAX, RB = 0x1", 899 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 900 .regs = { 901 .gpr[21] = UINT_MAX, 902 .gpr[22] = 0x1, 903 } 904 }, 905 { 906 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 907 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 908 .regs = { 909 .gpr[21] = LONG_MIN | (uint)INT_MIN, 910 .gpr[22] = LONG_MIN | (uint)INT_MIN, 911 } 912 } 913 } 914 }, 915 { 916 .mnemonic = "addc.", 917 .subtests = { 918 { 919 .descr = "RA = LONG_MIN, RB = LONG_MIN", 920 .flags = IGNORE_CCR, 921 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 922 .regs = { 923 .gpr[21] = LONG_MIN, 924 .gpr[22] = LONG_MIN, 925 } 926 }, 927 { 928 .descr = "RA = LONG_MIN, RB = LONG_MAX", 929 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 930 .regs = { 931 .gpr[21] = LONG_MIN, 932 .gpr[22] = LONG_MAX, 933 } 934 }, 935 { 936 .descr = "RA = LONG_MAX, RB = LONG_MAX", 937 .flags = IGNORE_CCR, 938 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 939 .regs = { 940 .gpr[21] = LONG_MAX, 941 .gpr[22] = LONG_MAX, 942 } 943 }, 944 { 945 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 946 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 947 .regs = { 948 .gpr[21] = ULONG_MAX, 949 .gpr[22] = ULONG_MAX, 950 } 951 }, 952 { 953 .descr = "RA = ULONG_MAX, RB = 0x1", 954 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 955 .regs = { 956 .gpr[21] = ULONG_MAX, 957 .gpr[22] = 0x1, 958 } 959 }, 960 { 961 .descr = "RA = INT_MIN, RB = INT_MIN", 962 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 963 .regs = { 964 .gpr[21] = INT_MIN, 965 .gpr[22] = INT_MIN, 966 } 967 }, 968 { 969 .descr = "RA = INT_MIN, RB = INT_MAX", 970 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 971 .regs = { 972 .gpr[21] = INT_MIN, 973 .gpr[22] = INT_MAX, 974 } 975 }, 976 { 977 .descr = "RA = INT_MAX, RB = INT_MAX", 978 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 979 .regs = { 980 .gpr[21] = INT_MAX, 981 .gpr[22] = INT_MAX, 982 } 983 }, 984 { 985 .descr = "RA = UINT_MAX, RB = UINT_MAX", 986 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 987 .regs = { 988 .gpr[21] = UINT_MAX, 989 .gpr[22] = UINT_MAX, 990 } 991 }, 992 { 993 .descr = "RA = UINT_MAX, RB = 0x1", 994 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 995 .regs = { 996 .gpr[21] = UINT_MAX, 997 .gpr[22] = 0x1, 998 } 999 }, 1000 { 1001 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 1002 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1003 .regs = { 1004 .gpr[21] = LONG_MIN | (uint)INT_MIN, 1005 .gpr[22] = LONG_MIN | (uint)INT_MIN, 1006 } 1007 } 1008 } 1009 } 1010 }; 1011 1012 static int __init emulate_compute_instr(struct pt_regs *regs, 1013 struct ppc_inst instr) 1014 { 1015 extern s32 patch__exec_instr; 1016 struct instruction_op op; 1017 1018 if (!regs || !ppc_inst_val(instr)) 1019 return -EINVAL; 1020 1021 regs->nip = patch_site_addr(&patch__exec_instr); 1022 1023 if (analyse_instr(&op, regs, instr) != 1 || 1024 GETTYPE(op.type) != COMPUTE) { 1025 pr_info("emulation failed, instruction = 0x%08x\n", ppc_inst_val(instr)); 1026 return -EFAULT; 1027 } 1028 1029 emulate_update_regs(regs, &op); 1030 return 0; 1031 } 1032 1033 static int __init execute_compute_instr(struct pt_regs *regs, 1034 struct ppc_inst instr) 1035 { 1036 extern int exec_instr(struct pt_regs *regs); 1037 extern s32 patch__exec_instr; 1038 1039 if (!regs || !ppc_inst_val(instr)) 1040 return -EINVAL; 1041 1042 /* Patch the NOP with the actual instruction */ 1043 patch_instruction_site(&patch__exec_instr, instr); 1044 if (exec_instr(regs)) { 1045 pr_info("execution failed, instruction = 0x%08x\n", ppc_inst_val(instr)); 1046 return -EFAULT; 1047 } 1048 1049 return 0; 1050 } 1051 1052 #define gpr_mismatch(gprn, exp, got) \ 1053 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1054 gprn, exp, got) 1055 1056 #define reg_mismatch(name, exp, got) \ 1057 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1058 name, exp, got) 1059 1060 static void __init run_tests_compute(void) 1061 { 1062 unsigned long flags; 1063 struct compute_test *test; 1064 struct pt_regs *regs, exp, got; 1065 unsigned int i, j, k; 1066 struct ppc_inst instr; 1067 bool ignore_gpr, ignore_xer, ignore_ccr, passed; 1068 1069 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) { 1070 test = &compute_tests[i]; 1071 1072 if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) { 1073 show_result(test->mnemonic, "SKIP (!CPU_FTR)"); 1074 continue; 1075 } 1076 1077 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) { 1078 instr = test->subtests[j].instr; 1079 flags = test->subtests[j].flags; 1080 regs = &test->subtests[j].regs; 1081 ignore_xer = flags & IGNORE_XER; 1082 ignore_ccr = flags & IGNORE_CCR; 1083 passed = true; 1084 1085 memcpy(&exp, regs, sizeof(struct pt_regs)); 1086 memcpy(&got, regs, sizeof(struct pt_regs)); 1087 1088 /* 1089 * Set a compatible MSR value explicitly to ensure 1090 * that XER and CR bits are updated appropriately 1091 */ 1092 exp.msr = MSR_KERNEL; 1093 got.msr = MSR_KERNEL; 1094 1095 if (emulate_compute_instr(&got, instr) || 1096 execute_compute_instr(&exp, instr)) { 1097 passed = false; 1098 goto print; 1099 } 1100 1101 /* Verify GPR values */ 1102 for (k = 0; k < 32; k++) { 1103 ignore_gpr = flags & IGNORE_GPR(k); 1104 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) { 1105 passed = false; 1106 gpr_mismatch(k, exp.gpr[k], got.gpr[k]); 1107 } 1108 } 1109 1110 /* Verify LR value */ 1111 if (exp.link != got.link) { 1112 passed = false; 1113 reg_mismatch("LR", exp.link, got.link); 1114 } 1115 1116 /* Verify XER value */ 1117 if (!ignore_xer && exp.xer != got.xer) { 1118 passed = false; 1119 reg_mismatch("XER", exp.xer, got.xer); 1120 } 1121 1122 /* Verify CR value */ 1123 if (!ignore_ccr && exp.ccr != got.ccr) { 1124 passed = false; 1125 reg_mismatch("CR", exp.ccr, got.ccr); 1126 } 1127 1128 print: 1129 show_result_with_descr(test->mnemonic, 1130 test->subtests[j].descr, 1131 passed ? "PASS" : "FAIL"); 1132 } 1133 } 1134 } 1135 1136 static int __init test_emulate_step(void) 1137 { 1138 printk(KERN_INFO "Running instruction emulation self-tests ...\n"); 1139 run_tests_load_store(); 1140 run_tests_compute(); 1141 1142 return 0; 1143 } 1144 late_initcall(test_emulate_step); 1145