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