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