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 struct { 629 char *descr; 630 unsigned long flags; 631 struct ppc_inst instr; 632 struct pt_regs regs; 633 } subtests[MAX_SUBTESTS + 1]; 634 }; 635 636 static struct compute_test compute_tests[] = { 637 { 638 .mnemonic = "nop", 639 .subtests = { 640 { 641 .descr = "R0 = LONG_MAX", 642 .instr = ppc_inst(PPC_INST_NOP), 643 .regs = { 644 .gpr[0] = LONG_MAX, 645 } 646 } 647 } 648 }, 649 { 650 .mnemonic = "add", 651 .subtests = { 652 { 653 .descr = "RA = LONG_MIN, RB = LONG_MIN", 654 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 655 .regs = { 656 .gpr[21] = LONG_MIN, 657 .gpr[22] = LONG_MIN, 658 } 659 }, 660 { 661 .descr = "RA = LONG_MIN, RB = LONG_MAX", 662 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 663 .regs = { 664 .gpr[21] = LONG_MIN, 665 .gpr[22] = LONG_MAX, 666 } 667 }, 668 { 669 .descr = "RA = LONG_MAX, RB = LONG_MAX", 670 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 671 .regs = { 672 .gpr[21] = LONG_MAX, 673 .gpr[22] = LONG_MAX, 674 } 675 }, 676 { 677 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 678 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 679 .regs = { 680 .gpr[21] = ULONG_MAX, 681 .gpr[22] = ULONG_MAX, 682 } 683 }, 684 { 685 .descr = "RA = ULONG_MAX, RB = 0x1", 686 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 687 .regs = { 688 .gpr[21] = ULONG_MAX, 689 .gpr[22] = 0x1, 690 } 691 }, 692 { 693 .descr = "RA = INT_MIN, RB = INT_MIN", 694 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 695 .regs = { 696 .gpr[21] = INT_MIN, 697 .gpr[22] = INT_MIN, 698 } 699 }, 700 { 701 .descr = "RA = INT_MIN, RB = INT_MAX", 702 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 703 .regs = { 704 .gpr[21] = INT_MIN, 705 .gpr[22] = INT_MAX, 706 } 707 }, 708 { 709 .descr = "RA = INT_MAX, RB = INT_MAX", 710 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 711 .regs = { 712 .gpr[21] = INT_MAX, 713 .gpr[22] = INT_MAX, 714 } 715 }, 716 { 717 .descr = "RA = UINT_MAX, RB = UINT_MAX", 718 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 719 .regs = { 720 .gpr[21] = UINT_MAX, 721 .gpr[22] = UINT_MAX, 722 } 723 }, 724 { 725 .descr = "RA = UINT_MAX, RB = 0x1", 726 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 727 .regs = { 728 .gpr[21] = UINT_MAX, 729 .gpr[22] = 0x1, 730 } 731 } 732 } 733 }, 734 { 735 .mnemonic = "add.", 736 .subtests = { 737 { 738 .descr = "RA = LONG_MIN, RB = LONG_MIN", 739 .flags = IGNORE_CCR, 740 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 741 .regs = { 742 .gpr[21] = LONG_MIN, 743 .gpr[22] = LONG_MIN, 744 } 745 }, 746 { 747 .descr = "RA = LONG_MIN, RB = LONG_MAX", 748 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 749 .regs = { 750 .gpr[21] = LONG_MIN, 751 .gpr[22] = LONG_MAX, 752 } 753 }, 754 { 755 .descr = "RA = LONG_MAX, RB = LONG_MAX", 756 .flags = IGNORE_CCR, 757 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 758 .regs = { 759 .gpr[21] = LONG_MAX, 760 .gpr[22] = LONG_MAX, 761 } 762 }, 763 { 764 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 765 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 766 .regs = { 767 .gpr[21] = ULONG_MAX, 768 .gpr[22] = ULONG_MAX, 769 } 770 }, 771 { 772 .descr = "RA = ULONG_MAX, RB = 0x1", 773 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 774 .regs = { 775 .gpr[21] = ULONG_MAX, 776 .gpr[22] = 0x1, 777 } 778 }, 779 { 780 .descr = "RA = INT_MIN, RB = INT_MIN", 781 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 782 .regs = { 783 .gpr[21] = INT_MIN, 784 .gpr[22] = INT_MIN, 785 } 786 }, 787 { 788 .descr = "RA = INT_MIN, RB = INT_MAX", 789 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 790 .regs = { 791 .gpr[21] = INT_MIN, 792 .gpr[22] = INT_MAX, 793 } 794 }, 795 { 796 .descr = "RA = INT_MAX, RB = INT_MAX", 797 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 798 .regs = { 799 .gpr[21] = INT_MAX, 800 .gpr[22] = INT_MAX, 801 } 802 }, 803 { 804 .descr = "RA = UINT_MAX, RB = UINT_MAX", 805 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 806 .regs = { 807 .gpr[21] = UINT_MAX, 808 .gpr[22] = UINT_MAX, 809 } 810 }, 811 { 812 .descr = "RA = UINT_MAX, RB = 0x1", 813 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 814 .regs = { 815 .gpr[21] = UINT_MAX, 816 .gpr[22] = 0x1, 817 } 818 } 819 } 820 }, 821 { 822 .mnemonic = "addc", 823 .subtests = { 824 { 825 .descr = "RA = LONG_MIN, RB = LONG_MIN", 826 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 827 .regs = { 828 .gpr[21] = LONG_MIN, 829 .gpr[22] = LONG_MIN, 830 } 831 }, 832 { 833 .descr = "RA = LONG_MIN, RB = LONG_MAX", 834 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 835 .regs = { 836 .gpr[21] = LONG_MIN, 837 .gpr[22] = LONG_MAX, 838 } 839 }, 840 { 841 .descr = "RA = LONG_MAX, RB = LONG_MAX", 842 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 843 .regs = { 844 .gpr[21] = LONG_MAX, 845 .gpr[22] = LONG_MAX, 846 } 847 }, 848 { 849 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 850 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 851 .regs = { 852 .gpr[21] = ULONG_MAX, 853 .gpr[22] = ULONG_MAX, 854 } 855 }, 856 { 857 .descr = "RA = ULONG_MAX, RB = 0x1", 858 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 859 .regs = { 860 .gpr[21] = ULONG_MAX, 861 .gpr[22] = 0x1, 862 } 863 }, 864 { 865 .descr = "RA = INT_MIN, RB = INT_MIN", 866 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 867 .regs = { 868 .gpr[21] = INT_MIN, 869 .gpr[22] = INT_MIN, 870 } 871 }, 872 { 873 .descr = "RA = INT_MIN, RB = INT_MAX", 874 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 875 .regs = { 876 .gpr[21] = INT_MIN, 877 .gpr[22] = INT_MAX, 878 } 879 }, 880 { 881 .descr = "RA = INT_MAX, RB = INT_MAX", 882 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 883 .regs = { 884 .gpr[21] = INT_MAX, 885 .gpr[22] = INT_MAX, 886 } 887 }, 888 { 889 .descr = "RA = UINT_MAX, RB = UINT_MAX", 890 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 891 .regs = { 892 .gpr[21] = UINT_MAX, 893 .gpr[22] = UINT_MAX, 894 } 895 }, 896 { 897 .descr = "RA = UINT_MAX, RB = 0x1", 898 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 899 .regs = { 900 .gpr[21] = UINT_MAX, 901 .gpr[22] = 0x1, 902 } 903 }, 904 { 905 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 906 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 907 .regs = { 908 .gpr[21] = LONG_MIN | (uint)INT_MIN, 909 .gpr[22] = LONG_MIN | (uint)INT_MIN, 910 } 911 } 912 } 913 }, 914 { 915 .mnemonic = "addc.", 916 .subtests = { 917 { 918 .descr = "RA = LONG_MIN, RB = LONG_MIN", 919 .flags = IGNORE_CCR, 920 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 921 .regs = { 922 .gpr[21] = LONG_MIN, 923 .gpr[22] = LONG_MIN, 924 } 925 }, 926 { 927 .descr = "RA = LONG_MIN, RB = LONG_MAX", 928 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 929 .regs = { 930 .gpr[21] = LONG_MIN, 931 .gpr[22] = LONG_MAX, 932 } 933 }, 934 { 935 .descr = "RA = LONG_MAX, RB = LONG_MAX", 936 .flags = IGNORE_CCR, 937 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 938 .regs = { 939 .gpr[21] = LONG_MAX, 940 .gpr[22] = LONG_MAX, 941 } 942 }, 943 { 944 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 945 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 946 .regs = { 947 .gpr[21] = ULONG_MAX, 948 .gpr[22] = ULONG_MAX, 949 } 950 }, 951 { 952 .descr = "RA = ULONG_MAX, RB = 0x1", 953 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 954 .regs = { 955 .gpr[21] = ULONG_MAX, 956 .gpr[22] = 0x1, 957 } 958 }, 959 { 960 .descr = "RA = INT_MIN, RB = INT_MIN", 961 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 962 .regs = { 963 .gpr[21] = INT_MIN, 964 .gpr[22] = INT_MIN, 965 } 966 }, 967 { 968 .descr = "RA = INT_MIN, RB = INT_MAX", 969 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 970 .regs = { 971 .gpr[21] = INT_MIN, 972 .gpr[22] = INT_MAX, 973 } 974 }, 975 { 976 .descr = "RA = INT_MAX, RB = INT_MAX", 977 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 978 .regs = { 979 .gpr[21] = INT_MAX, 980 .gpr[22] = INT_MAX, 981 } 982 }, 983 { 984 .descr = "RA = UINT_MAX, RB = UINT_MAX", 985 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 986 .regs = { 987 .gpr[21] = UINT_MAX, 988 .gpr[22] = UINT_MAX, 989 } 990 }, 991 { 992 .descr = "RA = UINT_MAX, RB = 0x1", 993 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 994 .regs = { 995 .gpr[21] = UINT_MAX, 996 .gpr[22] = 0x1, 997 } 998 }, 999 { 1000 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 1001 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1002 .regs = { 1003 .gpr[21] = LONG_MIN | (uint)INT_MIN, 1004 .gpr[22] = LONG_MIN | (uint)INT_MIN, 1005 } 1006 } 1007 } 1008 } 1009 }; 1010 1011 static int __init emulate_compute_instr(struct pt_regs *regs, 1012 struct ppc_inst instr) 1013 { 1014 extern s32 patch__exec_instr; 1015 struct instruction_op op; 1016 1017 if (!regs || !ppc_inst_val(instr)) 1018 return -EINVAL; 1019 1020 regs->nip = patch_site_addr(&patch__exec_instr); 1021 1022 if (analyse_instr(&op, regs, instr) != 1 || 1023 GETTYPE(op.type) != COMPUTE) { 1024 pr_info("emulation failed, instruction = 0x%08x\n", ppc_inst_val(instr)); 1025 return -EFAULT; 1026 } 1027 1028 emulate_update_regs(regs, &op); 1029 return 0; 1030 } 1031 1032 static int __init execute_compute_instr(struct pt_regs *regs, 1033 struct ppc_inst instr) 1034 { 1035 extern int exec_instr(struct pt_regs *regs); 1036 extern s32 patch__exec_instr; 1037 1038 if (!regs || !ppc_inst_val(instr)) 1039 return -EINVAL; 1040 1041 /* Patch the NOP with the actual instruction */ 1042 patch_instruction_site(&patch__exec_instr, instr); 1043 if (exec_instr(regs)) { 1044 pr_info("execution failed, instruction = 0x%08x\n", ppc_inst_val(instr)); 1045 return -EFAULT; 1046 } 1047 1048 return 0; 1049 } 1050 1051 #define gpr_mismatch(gprn, exp, got) \ 1052 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1053 gprn, exp, got) 1054 1055 #define reg_mismatch(name, exp, got) \ 1056 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1057 name, exp, got) 1058 1059 static void __init run_tests_compute(void) 1060 { 1061 unsigned long flags; 1062 struct compute_test *test; 1063 struct pt_regs *regs, exp, got; 1064 unsigned int i, j, k; 1065 struct ppc_inst instr; 1066 bool ignore_gpr, ignore_xer, ignore_ccr, passed; 1067 1068 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) { 1069 test = &compute_tests[i]; 1070 1071 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) { 1072 instr = test->subtests[j].instr; 1073 flags = test->subtests[j].flags; 1074 regs = &test->subtests[j].regs; 1075 ignore_xer = flags & IGNORE_XER; 1076 ignore_ccr = flags & IGNORE_CCR; 1077 passed = true; 1078 1079 memcpy(&exp, regs, sizeof(struct pt_regs)); 1080 memcpy(&got, regs, sizeof(struct pt_regs)); 1081 1082 /* 1083 * Set a compatible MSR value explicitly to ensure 1084 * that XER and CR bits are updated appropriately 1085 */ 1086 exp.msr = MSR_KERNEL; 1087 got.msr = MSR_KERNEL; 1088 1089 if (emulate_compute_instr(&got, instr) || 1090 execute_compute_instr(&exp, instr)) { 1091 passed = false; 1092 goto print; 1093 } 1094 1095 /* Verify GPR values */ 1096 for (k = 0; k < 32; k++) { 1097 ignore_gpr = flags & IGNORE_GPR(k); 1098 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) { 1099 passed = false; 1100 gpr_mismatch(k, exp.gpr[k], got.gpr[k]); 1101 } 1102 } 1103 1104 /* Verify LR value */ 1105 if (exp.link != got.link) { 1106 passed = false; 1107 reg_mismatch("LR", exp.link, got.link); 1108 } 1109 1110 /* Verify XER value */ 1111 if (!ignore_xer && exp.xer != got.xer) { 1112 passed = false; 1113 reg_mismatch("XER", exp.xer, got.xer); 1114 } 1115 1116 /* Verify CR value */ 1117 if (!ignore_ccr && exp.ccr != got.ccr) { 1118 passed = false; 1119 reg_mismatch("CR", exp.ccr, got.ccr); 1120 } 1121 1122 print: 1123 show_result_with_descr(test->mnemonic, 1124 test->subtests[j].descr, 1125 passed ? "PASS" : "FAIL"); 1126 } 1127 } 1128 } 1129 1130 static int __init test_emulate_step(void) 1131 { 1132 printk(KERN_INFO "Running instruction emulation self-tests ...\n"); 1133 run_tests_load_store(); 1134 run_tests_compute(); 1135 1136 return 0; 1137 } 1138 late_initcall(test_emulate_step); 1139