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/cpu_has_feature.h> 12 #include <asm/sstep.h> 13 #include <asm/ppc-opcode.h> 14 #include <asm/code-patching.h> 15 #include <asm/inst.h> 16 17 #define MAX_SUBTESTS 16 18 19 #define IGNORE_GPR(n) (0x1UL << (n)) 20 #define IGNORE_XER (0x1UL << 32) 21 #define IGNORE_CCR (0x1UL << 33) 22 #define NEGATIVE_TEST (0x1UL << 63) 23 24 #define TEST_PLD(r, base, i, pr) \ 25 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \ 26 PPC_INST_PLD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 27 28 #define TEST_PLWZ(r, base, i, pr) \ 29 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 30 PPC_RAW_LWZ(r, base, i)) 31 32 #define TEST_PSTD(r, base, i, pr) \ 33 ppc_inst_prefix(PPC_PREFIX_8LS | __PPC_PRFX_R(pr) | IMM_H(i), \ 34 PPC_INST_PSTD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 35 36 #define TEST_PLFS(r, base, i, pr) \ 37 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 38 PPC_INST_LFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 39 40 #define TEST_PSTFS(r, base, i, pr) \ 41 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 42 PPC_INST_STFS | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 43 44 #define TEST_PLFD(r, base, i, pr) \ 45 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 46 PPC_INST_LFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 47 48 #define TEST_PSTFD(r, base, i, pr) \ 49 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 50 PPC_INST_STFD | ___PPC_RT(r) | ___PPC_RA(base) | IMM_L(i)) 51 52 #define TEST_PADDI(t, a, i, pr) \ 53 ppc_inst_prefix(PPC_PREFIX_MLS | __PPC_PRFX_R(pr) | IMM_H(i), \ 54 PPC_RAW_ADDI(t, a, i)) 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 #ifdef CONFIG_VSX 615 static void __init test_lxvp_stxvp(void) 616 { 617 struct pt_regs regs; 618 union { 619 vector128 a; 620 u32 b[4]; 621 } c[2]; 622 u32 cached_b[8]; 623 int stepped = -1; 624 625 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 626 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)"); 627 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)"); 628 return; 629 } 630 631 init_pt_regs(®s); 632 633 /*** lxvp ***/ 634 635 cached_b[0] = c[0].b[0] = 18233; 636 cached_b[1] = c[0].b[1] = 34863571; 637 cached_b[2] = c[0].b[2] = 834; 638 cached_b[3] = c[0].b[3] = 6138911; 639 cached_b[4] = c[1].b[0] = 1234; 640 cached_b[5] = c[1].b[1] = 5678; 641 cached_b[6] = c[1].b[2] = 91011; 642 cached_b[7] = c[1].b[3] = 121314; 643 644 regs.gpr[4] = (unsigned long)&c[0].a; 645 646 /* 647 * lxvp XTp,DQ(RA) 648 * XTp = 32xTX + 2xTp 649 * let TX=1 Tp=1 RA=4 DQ=0 650 */ 651 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVP(34, 4, 0))); 652 653 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 654 show_result("lxvp", "PASS"); 655 } else { 656 if (!cpu_has_feature(CPU_FTR_VSX)) 657 show_result("lxvp", "PASS (!CPU_FTR_VSX)"); 658 else 659 show_result("lxvp", "FAIL"); 660 } 661 662 /*** stxvp ***/ 663 664 c[0].b[0] = 21379463; 665 c[0].b[1] = 87; 666 c[0].b[2] = 374234; 667 c[0].b[3] = 4; 668 c[1].b[0] = 90; 669 c[1].b[1] = 122; 670 c[1].b[2] = 555; 671 c[1].b[3] = 32144; 672 673 /* 674 * stxvp XSp,DQ(RA) 675 * XSp = 32xSX + 2xSp 676 * let SX=1 Sp=1 RA=4 DQ=0 677 */ 678 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVP(34, 4, 0))); 679 680 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] && 681 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] && 682 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] && 683 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] && 684 cpu_has_feature(CPU_FTR_VSX)) { 685 show_result("stxvp", "PASS"); 686 } else { 687 if (!cpu_has_feature(CPU_FTR_VSX)) 688 show_result("stxvp", "PASS (!CPU_FTR_VSX)"); 689 else 690 show_result("stxvp", "FAIL"); 691 } 692 } 693 #else 694 static void __init test_lxvp_stxvp(void) 695 { 696 show_result("lxvp", "SKIP (CONFIG_VSX is not set)"); 697 show_result("stxvp", "SKIP (CONFIG_VSX is not set)"); 698 } 699 #endif /* CONFIG_VSX */ 700 701 #ifdef CONFIG_VSX 702 static void __init test_lxvpx_stxvpx(void) 703 { 704 struct pt_regs regs; 705 union { 706 vector128 a; 707 u32 b[4]; 708 } c[2]; 709 u32 cached_b[8]; 710 int stepped = -1; 711 712 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 713 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)"); 714 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)"); 715 return; 716 } 717 718 init_pt_regs(®s); 719 720 /*** lxvpx ***/ 721 722 cached_b[0] = c[0].b[0] = 18233; 723 cached_b[1] = c[0].b[1] = 34863571; 724 cached_b[2] = c[0].b[2] = 834; 725 cached_b[3] = c[0].b[3] = 6138911; 726 cached_b[4] = c[1].b[0] = 1234; 727 cached_b[5] = c[1].b[1] = 5678; 728 cached_b[6] = c[1].b[2] = 91011; 729 cached_b[7] = c[1].b[3] = 121314; 730 731 regs.gpr[3] = (unsigned long)&c[0].a; 732 regs.gpr[4] = 0; 733 734 /* 735 * lxvpx XTp,RA,RB 736 * XTp = 32xTX + 2xTp 737 * let TX=1 Tp=1 RA=3 RB=4 738 */ 739 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVPX(34, 3, 4))); 740 741 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 742 show_result("lxvpx", "PASS"); 743 } else { 744 if (!cpu_has_feature(CPU_FTR_VSX)) 745 show_result("lxvpx", "PASS (!CPU_FTR_VSX)"); 746 else 747 show_result("lxvpx", "FAIL"); 748 } 749 750 /*** stxvpx ***/ 751 752 c[0].b[0] = 21379463; 753 c[0].b[1] = 87; 754 c[0].b[2] = 374234; 755 c[0].b[3] = 4; 756 c[1].b[0] = 90; 757 c[1].b[1] = 122; 758 c[1].b[2] = 555; 759 c[1].b[3] = 32144; 760 761 /* 762 * stxvpx XSp,RA,RB 763 * XSp = 32xSX + 2xSp 764 * let SX=1 Sp=1 RA=3 RB=4 765 */ 766 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVPX(34, 3, 4))); 767 768 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] && 769 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] && 770 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] && 771 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] && 772 cpu_has_feature(CPU_FTR_VSX)) { 773 show_result("stxvpx", "PASS"); 774 } else { 775 if (!cpu_has_feature(CPU_FTR_VSX)) 776 show_result("stxvpx", "PASS (!CPU_FTR_VSX)"); 777 else 778 show_result("stxvpx", "FAIL"); 779 } 780 } 781 #else 782 static void __init test_lxvpx_stxvpx(void) 783 { 784 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)"); 785 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)"); 786 } 787 #endif /* CONFIG_VSX */ 788 789 #ifdef CONFIG_VSX 790 static void __init test_plxvp_pstxvp(void) 791 { 792 ppc_inst_t instr; 793 struct pt_regs regs; 794 union { 795 vector128 a; 796 u32 b[4]; 797 } c[2]; 798 u32 cached_b[8]; 799 int stepped = -1; 800 801 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 802 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)"); 803 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)"); 804 return; 805 } 806 807 /*** plxvp ***/ 808 809 cached_b[0] = c[0].b[0] = 18233; 810 cached_b[1] = c[0].b[1] = 34863571; 811 cached_b[2] = c[0].b[2] = 834; 812 cached_b[3] = c[0].b[3] = 6138911; 813 cached_b[4] = c[1].b[0] = 1234; 814 cached_b[5] = c[1].b[1] = 5678; 815 cached_b[6] = c[1].b[2] = 91011; 816 cached_b[7] = c[1].b[3] = 121314; 817 818 init_pt_regs(®s); 819 regs.gpr[3] = (unsigned long)&c[0].a; 820 821 /* 822 * plxvp XTp,D(RA),R 823 * XTp = 32xTX + 2xTp 824 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1 825 */ 826 instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0)); 827 828 stepped = emulate_step(®s, instr); 829 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 830 show_result("plxvp", "PASS"); 831 } else { 832 if (!cpu_has_feature(CPU_FTR_VSX)) 833 show_result("plxvp", "PASS (!CPU_FTR_VSX)"); 834 else 835 show_result("plxvp", "FAIL"); 836 } 837 838 /*** pstxvp ***/ 839 840 c[0].b[0] = 21379463; 841 c[0].b[1] = 87; 842 c[0].b[2] = 374234; 843 c[0].b[3] = 4; 844 c[1].b[0] = 90; 845 c[1].b[1] = 122; 846 c[1].b[2] = 555; 847 c[1].b[3] = 32144; 848 849 /* 850 * pstxvp XSp,D(RA),R 851 * XSp = 32xSX + 2xSp 852 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1 853 */ 854 instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0)); 855 856 stepped = emulate_step(®s, instr); 857 858 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] && 859 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] && 860 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] && 861 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] && 862 cpu_has_feature(CPU_FTR_VSX)) { 863 show_result("pstxvp", "PASS"); 864 } else { 865 if (!cpu_has_feature(CPU_FTR_VSX)) 866 show_result("pstxvp", "PASS (!CPU_FTR_VSX)"); 867 else 868 show_result("pstxvp", "FAIL"); 869 } 870 } 871 #else 872 static void __init test_plxvp_pstxvp(void) 873 { 874 show_result("plxvp", "SKIP (CONFIG_VSX is not set)"); 875 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)"); 876 } 877 #endif /* CONFIG_VSX */ 878 879 static void __init run_tests_load_store(void) 880 { 881 test_ld(); 882 test_pld(); 883 test_lwz(); 884 test_plwz(); 885 test_lwzx(); 886 test_std(); 887 test_pstd(); 888 test_ldarx_stdcx(); 889 test_lfsx_stfsx(); 890 test_plfs_pstfs(); 891 test_lfdx_stfdx(); 892 test_plfd_pstfd(); 893 test_lvx_stvx(); 894 test_lxvd2x_stxvd2x(); 895 test_lxvp_stxvp(); 896 test_lxvpx_stxvpx(); 897 test_plxvp_pstxvp(); 898 } 899 900 struct compute_test { 901 char *mnemonic; 902 unsigned long cpu_feature; 903 struct { 904 char *descr; 905 unsigned long flags; 906 ppc_inst_t instr; 907 struct pt_regs regs; 908 } subtests[MAX_SUBTESTS + 1]; 909 }; 910 911 /* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */ 912 #define SI_MIN BIT(33) 913 #define SI_MAX (BIT(33) - 1) 914 #define SI_UMAX (BIT(34) - 1) 915 916 static struct compute_test compute_tests[] = { 917 { 918 .mnemonic = "nop", 919 .subtests = { 920 { 921 .descr = "R0 = LONG_MAX", 922 .instr = ppc_inst(PPC_RAW_NOP()), 923 .regs = { 924 .gpr[0] = LONG_MAX, 925 } 926 } 927 } 928 }, 929 { 930 .mnemonic = "setb", 931 .cpu_feature = CPU_FTR_ARCH_300, 932 .subtests = { 933 { 934 .descr = "BFA = 1, CR = GT", 935 .instr = ppc_inst(PPC_RAW_SETB(20, 1)), 936 .regs = { 937 .ccr = 0x4000000, 938 } 939 }, 940 { 941 .descr = "BFA = 4, CR = LT", 942 .instr = ppc_inst(PPC_RAW_SETB(20, 4)), 943 .regs = { 944 .ccr = 0x8000, 945 } 946 }, 947 { 948 .descr = "BFA = 5, CR = EQ", 949 .instr = ppc_inst(PPC_RAW_SETB(20, 5)), 950 .regs = { 951 .ccr = 0x200, 952 } 953 } 954 } 955 }, 956 { 957 .mnemonic = "add", 958 .subtests = { 959 { 960 .descr = "RA = LONG_MIN, RB = LONG_MIN", 961 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 962 .regs = { 963 .gpr[21] = LONG_MIN, 964 .gpr[22] = LONG_MIN, 965 } 966 }, 967 { 968 .descr = "RA = LONG_MIN, RB = LONG_MAX", 969 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 970 .regs = { 971 .gpr[21] = LONG_MIN, 972 .gpr[22] = LONG_MAX, 973 } 974 }, 975 { 976 .descr = "RA = LONG_MAX, RB = LONG_MAX", 977 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 978 .regs = { 979 .gpr[21] = LONG_MAX, 980 .gpr[22] = LONG_MAX, 981 } 982 }, 983 { 984 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 985 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 986 .regs = { 987 .gpr[21] = ULONG_MAX, 988 .gpr[22] = ULONG_MAX, 989 } 990 }, 991 { 992 .descr = "RA = ULONG_MAX, RB = 0x1", 993 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 994 .regs = { 995 .gpr[21] = ULONG_MAX, 996 .gpr[22] = 0x1, 997 } 998 }, 999 { 1000 .descr = "RA = INT_MIN, RB = INT_MIN", 1001 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1002 .regs = { 1003 .gpr[21] = INT_MIN, 1004 .gpr[22] = INT_MIN, 1005 } 1006 }, 1007 { 1008 .descr = "RA = INT_MIN, RB = INT_MAX", 1009 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1010 .regs = { 1011 .gpr[21] = INT_MIN, 1012 .gpr[22] = INT_MAX, 1013 } 1014 }, 1015 { 1016 .descr = "RA = INT_MAX, RB = INT_MAX", 1017 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1018 .regs = { 1019 .gpr[21] = INT_MAX, 1020 .gpr[22] = INT_MAX, 1021 } 1022 }, 1023 { 1024 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1025 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1026 .regs = { 1027 .gpr[21] = UINT_MAX, 1028 .gpr[22] = UINT_MAX, 1029 } 1030 }, 1031 { 1032 .descr = "RA = UINT_MAX, RB = 0x1", 1033 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1034 .regs = { 1035 .gpr[21] = UINT_MAX, 1036 .gpr[22] = 0x1, 1037 } 1038 } 1039 } 1040 }, 1041 { 1042 .mnemonic = "add.", 1043 .subtests = { 1044 { 1045 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1046 .flags = IGNORE_CCR, 1047 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1048 .regs = { 1049 .gpr[21] = LONG_MIN, 1050 .gpr[22] = LONG_MIN, 1051 } 1052 }, 1053 { 1054 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1055 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1056 .regs = { 1057 .gpr[21] = LONG_MIN, 1058 .gpr[22] = LONG_MAX, 1059 } 1060 }, 1061 { 1062 .descr = "RA = LONG_MAX, RB = LONG_MAX", 1063 .flags = IGNORE_CCR, 1064 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1065 .regs = { 1066 .gpr[21] = LONG_MAX, 1067 .gpr[22] = LONG_MAX, 1068 } 1069 }, 1070 { 1071 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 1072 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1073 .regs = { 1074 .gpr[21] = ULONG_MAX, 1075 .gpr[22] = ULONG_MAX, 1076 } 1077 }, 1078 { 1079 .descr = "RA = ULONG_MAX, RB = 0x1", 1080 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1081 .regs = { 1082 .gpr[21] = ULONG_MAX, 1083 .gpr[22] = 0x1, 1084 } 1085 }, 1086 { 1087 .descr = "RA = INT_MIN, RB = INT_MIN", 1088 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1089 .regs = { 1090 .gpr[21] = INT_MIN, 1091 .gpr[22] = INT_MIN, 1092 } 1093 }, 1094 { 1095 .descr = "RA = INT_MIN, RB = INT_MAX", 1096 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1097 .regs = { 1098 .gpr[21] = INT_MIN, 1099 .gpr[22] = INT_MAX, 1100 } 1101 }, 1102 { 1103 .descr = "RA = INT_MAX, RB = INT_MAX", 1104 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1105 .regs = { 1106 .gpr[21] = INT_MAX, 1107 .gpr[22] = INT_MAX, 1108 } 1109 }, 1110 { 1111 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1112 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1113 .regs = { 1114 .gpr[21] = UINT_MAX, 1115 .gpr[22] = UINT_MAX, 1116 } 1117 }, 1118 { 1119 .descr = "RA = UINT_MAX, RB = 0x1", 1120 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1121 .regs = { 1122 .gpr[21] = UINT_MAX, 1123 .gpr[22] = 0x1, 1124 } 1125 } 1126 } 1127 }, 1128 { 1129 .mnemonic = "addc", 1130 .subtests = { 1131 { 1132 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1133 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1134 .regs = { 1135 .gpr[21] = LONG_MIN, 1136 .gpr[22] = LONG_MIN, 1137 } 1138 }, 1139 { 1140 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1141 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1142 .regs = { 1143 .gpr[21] = LONG_MIN, 1144 .gpr[22] = LONG_MAX, 1145 } 1146 }, 1147 { 1148 .descr = "RA = LONG_MAX, RB = LONG_MAX", 1149 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1150 .regs = { 1151 .gpr[21] = LONG_MAX, 1152 .gpr[22] = LONG_MAX, 1153 } 1154 }, 1155 { 1156 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 1157 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1158 .regs = { 1159 .gpr[21] = ULONG_MAX, 1160 .gpr[22] = ULONG_MAX, 1161 } 1162 }, 1163 { 1164 .descr = "RA = ULONG_MAX, RB = 0x1", 1165 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1166 .regs = { 1167 .gpr[21] = ULONG_MAX, 1168 .gpr[22] = 0x1, 1169 } 1170 }, 1171 { 1172 .descr = "RA = INT_MIN, RB = INT_MIN", 1173 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1174 .regs = { 1175 .gpr[21] = INT_MIN, 1176 .gpr[22] = INT_MIN, 1177 } 1178 }, 1179 { 1180 .descr = "RA = INT_MIN, RB = INT_MAX", 1181 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1182 .regs = { 1183 .gpr[21] = INT_MIN, 1184 .gpr[22] = INT_MAX, 1185 } 1186 }, 1187 { 1188 .descr = "RA = INT_MAX, RB = INT_MAX", 1189 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1190 .regs = { 1191 .gpr[21] = INT_MAX, 1192 .gpr[22] = INT_MAX, 1193 } 1194 }, 1195 { 1196 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1197 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1198 .regs = { 1199 .gpr[21] = UINT_MAX, 1200 .gpr[22] = UINT_MAX, 1201 } 1202 }, 1203 { 1204 .descr = "RA = UINT_MAX, RB = 0x1", 1205 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1206 .regs = { 1207 .gpr[21] = UINT_MAX, 1208 .gpr[22] = 0x1, 1209 } 1210 }, 1211 { 1212 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 1213 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1214 .regs = { 1215 .gpr[21] = LONG_MIN | (uint)INT_MIN, 1216 .gpr[22] = LONG_MIN | (uint)INT_MIN, 1217 } 1218 } 1219 } 1220 }, 1221 { 1222 .mnemonic = "addc.", 1223 .subtests = { 1224 { 1225 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1226 .flags = IGNORE_CCR, 1227 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1228 .regs = { 1229 .gpr[21] = LONG_MIN, 1230 .gpr[22] = LONG_MIN, 1231 } 1232 }, 1233 { 1234 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1235 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1236 .regs = { 1237 .gpr[21] = LONG_MIN, 1238 .gpr[22] = LONG_MAX, 1239 } 1240 }, 1241 { 1242 .descr = "RA = LONG_MAX, RB = LONG_MAX", 1243 .flags = IGNORE_CCR, 1244 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1245 .regs = { 1246 .gpr[21] = LONG_MAX, 1247 .gpr[22] = LONG_MAX, 1248 } 1249 }, 1250 { 1251 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 1252 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1253 .regs = { 1254 .gpr[21] = ULONG_MAX, 1255 .gpr[22] = ULONG_MAX, 1256 } 1257 }, 1258 { 1259 .descr = "RA = ULONG_MAX, RB = 0x1", 1260 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1261 .regs = { 1262 .gpr[21] = ULONG_MAX, 1263 .gpr[22] = 0x1, 1264 } 1265 }, 1266 { 1267 .descr = "RA = INT_MIN, RB = INT_MIN", 1268 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1269 .regs = { 1270 .gpr[21] = INT_MIN, 1271 .gpr[22] = INT_MIN, 1272 } 1273 }, 1274 { 1275 .descr = "RA = INT_MIN, RB = INT_MAX", 1276 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1277 .regs = { 1278 .gpr[21] = INT_MIN, 1279 .gpr[22] = INT_MAX, 1280 } 1281 }, 1282 { 1283 .descr = "RA = INT_MAX, RB = INT_MAX", 1284 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1285 .regs = { 1286 .gpr[21] = INT_MAX, 1287 .gpr[22] = INT_MAX, 1288 } 1289 }, 1290 { 1291 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1292 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1293 .regs = { 1294 .gpr[21] = UINT_MAX, 1295 .gpr[22] = UINT_MAX, 1296 } 1297 }, 1298 { 1299 .descr = "RA = UINT_MAX, RB = 0x1", 1300 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1301 .regs = { 1302 .gpr[21] = UINT_MAX, 1303 .gpr[22] = 0x1, 1304 } 1305 }, 1306 { 1307 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 1308 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1309 .regs = { 1310 .gpr[21] = LONG_MIN | (uint)INT_MIN, 1311 .gpr[22] = LONG_MIN | (uint)INT_MIN, 1312 } 1313 } 1314 } 1315 }, 1316 { 1317 .mnemonic = "divde", 1318 .subtests = { 1319 { 1320 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1321 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 1322 .regs = { 1323 .gpr[21] = LONG_MIN, 1324 .gpr[22] = LONG_MIN, 1325 } 1326 }, 1327 { 1328 .descr = "RA = 1L, RB = 0", 1329 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 1330 .flags = IGNORE_GPR(20), 1331 .regs = { 1332 .gpr[21] = 1L, 1333 .gpr[22] = 0, 1334 } 1335 }, 1336 { 1337 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1338 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 1339 .regs = { 1340 .gpr[21] = LONG_MIN, 1341 .gpr[22] = LONG_MAX, 1342 } 1343 } 1344 } 1345 }, 1346 { 1347 .mnemonic = "divde.", 1348 .subtests = { 1349 { 1350 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1351 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 1352 .regs = { 1353 .gpr[21] = LONG_MIN, 1354 .gpr[22] = LONG_MIN, 1355 } 1356 }, 1357 { 1358 .descr = "RA = 1L, RB = 0", 1359 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 1360 .flags = IGNORE_GPR(20), 1361 .regs = { 1362 .gpr[21] = 1L, 1363 .gpr[22] = 0, 1364 } 1365 }, 1366 { 1367 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1368 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 1369 .regs = { 1370 .gpr[21] = LONG_MIN, 1371 .gpr[22] = LONG_MAX, 1372 } 1373 } 1374 } 1375 }, 1376 { 1377 .mnemonic = "divdeu", 1378 .subtests = { 1379 { 1380 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1381 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1382 .flags = IGNORE_GPR(20), 1383 .regs = { 1384 .gpr[21] = LONG_MIN, 1385 .gpr[22] = LONG_MIN, 1386 } 1387 }, 1388 { 1389 .descr = "RA = 1L, RB = 0", 1390 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1391 .flags = IGNORE_GPR(20), 1392 .regs = { 1393 .gpr[21] = 1L, 1394 .gpr[22] = 0, 1395 } 1396 }, 1397 { 1398 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1399 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1400 .regs = { 1401 .gpr[21] = LONG_MIN, 1402 .gpr[22] = LONG_MAX, 1403 } 1404 }, 1405 { 1406 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX", 1407 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1408 .regs = { 1409 .gpr[21] = LONG_MAX - 1, 1410 .gpr[22] = LONG_MAX, 1411 } 1412 }, 1413 { 1414 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN", 1415 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1416 .flags = IGNORE_GPR(20), 1417 .regs = { 1418 .gpr[21] = LONG_MIN + 1, 1419 .gpr[22] = LONG_MIN, 1420 } 1421 } 1422 } 1423 }, 1424 { 1425 .mnemonic = "divdeu.", 1426 .subtests = { 1427 { 1428 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1429 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1430 .flags = IGNORE_GPR(20), 1431 .regs = { 1432 .gpr[21] = LONG_MIN, 1433 .gpr[22] = LONG_MIN, 1434 } 1435 }, 1436 { 1437 .descr = "RA = 1L, RB = 0", 1438 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1439 .flags = IGNORE_GPR(20), 1440 .regs = { 1441 .gpr[21] = 1L, 1442 .gpr[22] = 0, 1443 } 1444 }, 1445 { 1446 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1447 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1448 .regs = { 1449 .gpr[21] = LONG_MIN, 1450 .gpr[22] = LONG_MAX, 1451 } 1452 }, 1453 { 1454 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX", 1455 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1456 .regs = { 1457 .gpr[21] = LONG_MAX - 1, 1458 .gpr[22] = LONG_MAX, 1459 } 1460 }, 1461 { 1462 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN", 1463 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1464 .flags = IGNORE_GPR(20), 1465 .regs = { 1466 .gpr[21] = LONG_MIN + 1, 1467 .gpr[22] = LONG_MIN, 1468 } 1469 } 1470 } 1471 }, 1472 { 1473 .mnemonic = "paddi", 1474 .cpu_feature = CPU_FTR_ARCH_31, 1475 .subtests = { 1476 { 1477 .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0", 1478 .instr = TEST_PADDI(21, 22, SI_MIN, 0), 1479 .regs = { 1480 .gpr[21] = 0, 1481 .gpr[22] = LONG_MIN, 1482 } 1483 }, 1484 { 1485 .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0", 1486 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1487 .regs = { 1488 .gpr[21] = 0, 1489 .gpr[22] = LONG_MIN, 1490 } 1491 }, 1492 { 1493 .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0", 1494 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1495 .regs = { 1496 .gpr[21] = 0, 1497 .gpr[22] = LONG_MAX, 1498 } 1499 }, 1500 { 1501 .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0", 1502 .instr = TEST_PADDI(21, 22, SI_UMAX, 0), 1503 .regs = { 1504 .gpr[21] = 0, 1505 .gpr[22] = ULONG_MAX, 1506 } 1507 }, 1508 { 1509 .descr = "RA = ULONG_MAX, SI = 0x1, R = 0", 1510 .instr = TEST_PADDI(21, 22, 0x1, 0), 1511 .regs = { 1512 .gpr[21] = 0, 1513 .gpr[22] = ULONG_MAX, 1514 } 1515 }, 1516 { 1517 .descr = "RA = INT_MIN, SI = SI_MIN, R = 0", 1518 .instr = TEST_PADDI(21, 22, SI_MIN, 0), 1519 .regs = { 1520 .gpr[21] = 0, 1521 .gpr[22] = INT_MIN, 1522 } 1523 }, 1524 { 1525 .descr = "RA = INT_MIN, SI = SI_MAX, R = 0", 1526 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1527 .regs = { 1528 .gpr[21] = 0, 1529 .gpr[22] = INT_MIN, 1530 } 1531 }, 1532 { 1533 .descr = "RA = INT_MAX, SI = SI_MAX, R = 0", 1534 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1535 .regs = { 1536 .gpr[21] = 0, 1537 .gpr[22] = INT_MAX, 1538 } 1539 }, 1540 { 1541 .descr = "RA = UINT_MAX, SI = 0x1, R = 0", 1542 .instr = TEST_PADDI(21, 22, 0x1, 0), 1543 .regs = { 1544 .gpr[21] = 0, 1545 .gpr[22] = UINT_MAX, 1546 } 1547 }, 1548 { 1549 .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0", 1550 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1551 .regs = { 1552 .gpr[21] = 0, 1553 .gpr[22] = UINT_MAX, 1554 } 1555 }, 1556 { 1557 .descr = "RA is r0, SI = SI_MIN, R = 0", 1558 .instr = TEST_PADDI(21, 0, SI_MIN, 0), 1559 .regs = { 1560 .gpr[21] = 0x0, 1561 } 1562 }, 1563 { 1564 .descr = "RA = 0, SI = SI_MIN, R = 0", 1565 .instr = TEST_PADDI(21, 22, SI_MIN, 0), 1566 .regs = { 1567 .gpr[21] = 0x0, 1568 .gpr[22] = 0x0, 1569 } 1570 }, 1571 { 1572 .descr = "RA is r0, SI = 0, R = 1", 1573 .instr = TEST_PADDI(21, 0, 0, 1), 1574 .regs = { 1575 .gpr[21] = 0, 1576 } 1577 }, 1578 { 1579 .descr = "RA is r0, SI = SI_MIN, R = 1", 1580 .instr = TEST_PADDI(21, 0, SI_MIN, 1), 1581 .regs = { 1582 .gpr[21] = 0, 1583 } 1584 }, 1585 /* Invalid instruction form with R = 1 and RA != 0 */ 1586 { 1587 .descr = "RA = R22(0), SI = 0, R = 1", 1588 .instr = TEST_PADDI(21, 22, 0, 1), 1589 .flags = NEGATIVE_TEST, 1590 .regs = { 1591 .gpr[21] = 0, 1592 .gpr[22] = 0, 1593 } 1594 } 1595 } 1596 } 1597 }; 1598 1599 static int __init emulate_compute_instr(struct pt_regs *regs, 1600 ppc_inst_t instr, 1601 bool negative) 1602 { 1603 int analysed; 1604 struct instruction_op op; 1605 1606 if (!regs || !ppc_inst_val(instr)) 1607 return -EINVAL; 1608 1609 /* This is not a return frame regs */ 1610 regs->nip = patch_site_addr(&patch__exec_instr); 1611 1612 analysed = analyse_instr(&op, regs, instr); 1613 if (analysed != 1 || GETTYPE(op.type) != COMPUTE) { 1614 if (negative) 1615 return -EFAULT; 1616 pr_info("emulation failed, instruction = %08lx\n", ppc_inst_as_ulong(instr)); 1617 return -EFAULT; 1618 } 1619 if (analysed == 1 && negative) 1620 pr_info("negative test failed, instruction = %08lx\n", ppc_inst_as_ulong(instr)); 1621 if (!negative) 1622 emulate_update_regs(regs, &op); 1623 return 0; 1624 } 1625 1626 static int __init execute_compute_instr(struct pt_regs *regs, 1627 ppc_inst_t instr) 1628 { 1629 extern int exec_instr(struct pt_regs *regs); 1630 1631 if (!regs || !ppc_inst_val(instr)) 1632 return -EINVAL; 1633 1634 /* Patch the NOP with the actual instruction */ 1635 patch_instruction_site(&patch__exec_instr, instr); 1636 if (exec_instr(regs)) { 1637 pr_info("execution failed, instruction = %08lx\n", ppc_inst_as_ulong(instr)); 1638 return -EFAULT; 1639 } 1640 1641 return 0; 1642 } 1643 1644 #define gpr_mismatch(gprn, exp, got) \ 1645 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1646 gprn, exp, got) 1647 1648 #define reg_mismatch(name, exp, got) \ 1649 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1650 name, exp, got) 1651 1652 static void __init run_tests_compute(void) 1653 { 1654 unsigned long flags; 1655 struct compute_test *test; 1656 struct pt_regs *regs, exp, got; 1657 unsigned int i, j, k; 1658 ppc_inst_t instr; 1659 bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative; 1660 1661 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) { 1662 test = &compute_tests[i]; 1663 1664 if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) { 1665 show_result(test->mnemonic, "SKIP (!CPU_FTR)"); 1666 continue; 1667 } 1668 1669 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) { 1670 instr = test->subtests[j].instr; 1671 flags = test->subtests[j].flags; 1672 regs = &test->subtests[j].regs; 1673 negative = flags & NEGATIVE_TEST; 1674 ignore_xer = flags & IGNORE_XER; 1675 ignore_ccr = flags & IGNORE_CCR; 1676 passed = true; 1677 1678 memcpy(&exp, regs, sizeof(struct pt_regs)); 1679 memcpy(&got, regs, sizeof(struct pt_regs)); 1680 1681 /* 1682 * Set a compatible MSR value explicitly to ensure 1683 * that XER and CR bits are updated appropriately 1684 */ 1685 exp.msr = MSR_KERNEL; 1686 got.msr = MSR_KERNEL; 1687 1688 rc = emulate_compute_instr(&got, instr, negative) != 0; 1689 if (negative) { 1690 /* skip executing instruction */ 1691 passed = rc; 1692 goto print; 1693 } else if (rc || execute_compute_instr(&exp, instr)) { 1694 passed = false; 1695 goto print; 1696 } 1697 1698 /* Verify GPR values */ 1699 for (k = 0; k < 32; k++) { 1700 ignore_gpr = flags & IGNORE_GPR(k); 1701 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) { 1702 passed = false; 1703 gpr_mismatch(k, exp.gpr[k], got.gpr[k]); 1704 } 1705 } 1706 1707 /* Verify LR value */ 1708 if (exp.link != got.link) { 1709 passed = false; 1710 reg_mismatch("LR", exp.link, got.link); 1711 } 1712 1713 /* Verify XER value */ 1714 if (!ignore_xer && exp.xer != got.xer) { 1715 passed = false; 1716 reg_mismatch("XER", exp.xer, got.xer); 1717 } 1718 1719 /* Verify CR value */ 1720 if (!ignore_ccr && exp.ccr != got.ccr) { 1721 passed = false; 1722 reg_mismatch("CR", exp.ccr, got.ccr); 1723 } 1724 1725 print: 1726 show_result_with_descr(test->mnemonic, 1727 test->subtests[j].descr, 1728 passed ? "PASS" : "FAIL"); 1729 } 1730 } 1731 } 1732 1733 static int __init test_emulate_step(void) 1734 { 1735 printk(KERN_INFO "Running instruction emulation self-tests ...\n"); 1736 run_tests_load_store(); 1737 run_tests_compute(); 1738 1739 return 0; 1740 } 1741 late_initcall(test_emulate_step); 1742
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.