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