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