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