test_emulate_step.c (37794B)
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#define TEST_SETB(t, bfa) ppc_inst(PPC_INST_SETB | ___PPC_RT(t) | ___PPC_RA((bfa & 0x7) << 2)) 57 58 59static void __init init_pt_regs(struct pt_regs *regs) 60{ 61 static unsigned long msr; 62 static bool msr_cached; 63 64 memset(regs, 0, sizeof(struct pt_regs)); 65 66 if (likely(msr_cached)) { 67 regs->msr = msr; 68 return; 69 } 70 71 asm volatile("mfmsr %0" : "=r"(regs->msr)); 72 73 regs->msr |= MSR_FP; 74 regs->msr |= MSR_VEC; 75 regs->msr |= MSR_VSX; 76 77 msr = regs->msr; 78 msr_cached = true; 79} 80 81static void __init show_result(char *mnemonic, char *result) 82{ 83 pr_info("%-14s : %s\n", mnemonic, result); 84} 85 86static void __init show_result_with_descr(char *mnemonic, char *descr, 87 char *result) 88{ 89 pr_info("%-14s : %-50s %s\n", mnemonic, descr, result); 90} 91 92static void __init test_ld(void) 93{ 94 struct pt_regs regs; 95 unsigned long a = 0x23; 96 int stepped = -1; 97 98 init_pt_regs(®s); 99 regs.gpr[3] = (unsigned long) &a; 100 101 /* ld r5, 0(r3) */ 102 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LD(5, 3, 0))); 103 104 if (stepped == 1 && regs.gpr[5] == a) 105 show_result("ld", "PASS"); 106 else 107 show_result("ld", "FAIL"); 108} 109 110static void __init test_pld(void) 111{ 112 struct pt_regs regs; 113 unsigned long a = 0x23; 114 int stepped = -1; 115 116 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 117 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 118 return; 119 } 120 121 init_pt_regs(®s); 122 regs.gpr[3] = (unsigned long)&a; 123 124 /* pld r5, 0(r3), 0 */ 125 stepped = emulate_step(®s, TEST_PLD(5, 3, 0, 0)); 126 127 if (stepped == 1 && regs.gpr[5] == a) 128 show_result("pld", "PASS"); 129 else 130 show_result("pld", "FAIL"); 131} 132 133static void __init test_lwz(void) 134{ 135 struct pt_regs regs; 136 unsigned int a = 0x4545; 137 int stepped = -1; 138 139 init_pt_regs(®s); 140 regs.gpr[3] = (unsigned long) &a; 141 142 /* lwz r5, 0(r3) */ 143 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZ(5, 3, 0))); 144 145 if (stepped == 1 && regs.gpr[5] == a) 146 show_result("lwz", "PASS"); 147 else 148 show_result("lwz", "FAIL"); 149} 150 151static void __init test_plwz(void) 152{ 153 struct pt_regs regs; 154 unsigned int a = 0x4545; 155 int stepped = -1; 156 157 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 158 show_result("plwz", "SKIP (!CPU_FTR_ARCH_31)"); 159 return; 160 } 161 162 init_pt_regs(®s); 163 regs.gpr[3] = (unsigned long)&a; 164 165 /* plwz r5, 0(r3), 0 */ 166 167 stepped = emulate_step(®s, TEST_PLWZ(5, 3, 0, 0)); 168 169 if (stepped == 1 && regs.gpr[5] == a) 170 show_result("plwz", "PASS"); 171 else 172 show_result("plwz", "FAIL"); 173} 174 175static void __init test_lwzx(void) 176{ 177 struct pt_regs regs; 178 unsigned int a[3] = {0x0, 0x0, 0x1234}; 179 int stepped = -1; 180 181 init_pt_regs(®s); 182 regs.gpr[3] = (unsigned long) a; 183 regs.gpr[4] = 8; 184 regs.gpr[5] = 0x8765; 185 186 /* lwzx r5, r3, r4 */ 187 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LWZX(5, 3, 4))); 188 if (stepped == 1 && regs.gpr[5] == a[2]) 189 show_result("lwzx", "PASS"); 190 else 191 show_result("lwzx", "FAIL"); 192} 193 194static void __init test_std(void) 195{ 196 struct pt_regs regs; 197 unsigned long a = 0x1234; 198 int stepped = -1; 199 200 init_pt_regs(®s); 201 regs.gpr[3] = (unsigned long) &a; 202 regs.gpr[5] = 0x5678; 203 204 /* std r5, 0(r3) */ 205 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STD(5, 3, 0))); 206 if (stepped == 1 && regs.gpr[5] == a) 207 show_result("std", "PASS"); 208 else 209 show_result("std", "FAIL"); 210} 211 212static void __init test_pstd(void) 213{ 214 struct pt_regs regs; 215 unsigned long a = 0x1234; 216 int stepped = -1; 217 218 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 219 show_result("pstd", "SKIP (!CPU_FTR_ARCH_31)"); 220 return; 221 } 222 223 init_pt_regs(®s); 224 regs.gpr[3] = (unsigned long)&a; 225 regs.gpr[5] = 0x5678; 226 227 /* pstd r5, 0(r3), 0 */ 228 stepped = emulate_step(®s, TEST_PSTD(5, 3, 0, 0)); 229 if (stepped == 1 || regs.gpr[5] == a) 230 show_result("pstd", "PASS"); 231 else 232 show_result("pstd", "FAIL"); 233} 234 235static void __init test_ldarx_stdcx(void) 236{ 237 struct pt_regs regs; 238 unsigned long a = 0x1234; 239 int stepped = -1; 240 unsigned long cr0_eq = 0x1 << 29; /* eq bit of CR0 */ 241 242 init_pt_regs(®s); 243 asm volatile("mfcr %0" : "=r"(regs.ccr)); 244 245 246 /*** ldarx ***/ 247 248 regs.gpr[3] = (unsigned long) &a; 249 regs.gpr[4] = 0; 250 regs.gpr[5] = 0x5678; 251 252 /* ldarx r5, r3, r4, 0 */ 253 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LDARX(5, 3, 4, 0))); 254 255 /* 256 * Don't touch 'a' here. Touching 'a' can do Load/store 257 * of 'a' which result in failure of subsequent stdcx. 258 * Instead, use hardcoded value for comparison. 259 */ 260 if (stepped <= 0 || regs.gpr[5] != 0x1234) { 261 show_result("ldarx / stdcx.", "FAIL (ldarx)"); 262 return; 263 } 264 265 266 /*** stdcx. ***/ 267 268 regs.gpr[5] = 0x9ABC; 269 270 /* stdcx. r5, r3, r4 */ 271 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STDCX(5, 3, 4))); 272 273 /* 274 * Two possible scenarios that indicates successful emulation 275 * of stdcx. : 276 * 1. Reservation is active and store is performed. In this 277 * case cr0.eq bit will be set to 1. 278 * 2. Reservation is not active and store is not performed. 279 * In this case cr0.eq bit will be set to 0. 280 */ 281 if (stepped == 1 && ((regs.gpr[5] == a && (regs.ccr & cr0_eq)) 282 || (regs.gpr[5] != a && !(regs.ccr & cr0_eq)))) 283 show_result("ldarx / stdcx.", "PASS"); 284 else 285 show_result("ldarx / stdcx.", "FAIL (stdcx.)"); 286} 287 288#ifdef CONFIG_PPC_FPU 289static void __init test_lfsx_stfsx(void) 290{ 291 struct pt_regs regs; 292 union { 293 float a; 294 int b; 295 } c; 296 int cached_b; 297 int stepped = -1; 298 299 init_pt_regs(®s); 300 301 302 /*** lfsx ***/ 303 304 c.a = 123.45; 305 cached_b = c.b; 306 307 regs.gpr[3] = (unsigned long) &c.a; 308 regs.gpr[4] = 0; 309 310 /* lfsx frt10, r3, r4 */ 311 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFSX(10, 3, 4))); 312 313 if (stepped == 1) 314 show_result("lfsx", "PASS"); 315 else 316 show_result("lfsx", "FAIL"); 317 318 319 /*** stfsx ***/ 320 321 c.a = 678.91; 322 323 /* stfsx frs10, r3, r4 */ 324 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFSX(10, 3, 4))); 325 326 if (stepped == 1 && c.b == cached_b) 327 show_result("stfsx", "PASS"); 328 else 329 show_result("stfsx", "FAIL"); 330} 331 332static void __init test_plfs_pstfs(void) 333{ 334 struct pt_regs regs; 335 union { 336 float a; 337 int b; 338 } c; 339 int cached_b; 340 int stepped = -1; 341 342 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 343 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 344 return; 345 } 346 347 init_pt_regs(®s); 348 349 350 /*** plfs ***/ 351 352 c.a = 123.45; 353 cached_b = c.b; 354 355 regs.gpr[3] = (unsigned long)&c.a; 356 357 /* plfs frt10, 0(r3), 0 */ 358 stepped = emulate_step(®s, TEST_PLFS(10, 3, 0, 0)); 359 360 if (stepped == 1) 361 show_result("plfs", "PASS"); 362 else 363 show_result("plfs", "FAIL"); 364 365 366 /*** pstfs ***/ 367 368 c.a = 678.91; 369 370 /* pstfs frs10, 0(r3), 0 */ 371 stepped = emulate_step(®s, TEST_PSTFS(10, 3, 0, 0)); 372 373 if (stepped == 1 && c.b == cached_b) 374 show_result("pstfs", "PASS"); 375 else 376 show_result("pstfs", "FAIL"); 377} 378 379static void __init test_lfdx_stfdx(void) 380{ 381 struct pt_regs regs; 382 union { 383 double a; 384 long b; 385 } c; 386 long cached_b; 387 int stepped = -1; 388 389 init_pt_regs(®s); 390 391 392 /*** lfdx ***/ 393 394 c.a = 123456.78; 395 cached_b = c.b; 396 397 regs.gpr[3] = (unsigned long) &c.a; 398 regs.gpr[4] = 0; 399 400 /* lfdx frt10, r3, r4 */ 401 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LFDX(10, 3, 4))); 402 403 if (stepped == 1) 404 show_result("lfdx", "PASS"); 405 else 406 show_result("lfdx", "FAIL"); 407 408 409 /*** stfdx ***/ 410 411 c.a = 987654.32; 412 413 /* stfdx frs10, r3, r4 */ 414 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STFDX(10, 3, 4))); 415 416 if (stepped == 1 && c.b == cached_b) 417 show_result("stfdx", "PASS"); 418 else 419 show_result("stfdx", "FAIL"); 420} 421 422static void __init test_plfd_pstfd(void) 423{ 424 struct pt_regs regs; 425 union { 426 double a; 427 long b; 428 } c; 429 long cached_b; 430 int stepped = -1; 431 432 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 433 show_result("pld", "SKIP (!CPU_FTR_ARCH_31)"); 434 return; 435 } 436 437 init_pt_regs(®s); 438 439 440 /*** plfd ***/ 441 442 c.a = 123456.78; 443 cached_b = c.b; 444 445 regs.gpr[3] = (unsigned long)&c.a; 446 447 /* plfd frt10, 0(r3), 0 */ 448 stepped = emulate_step(®s, TEST_PLFD(10, 3, 0, 0)); 449 450 if (stepped == 1) 451 show_result("plfd", "PASS"); 452 else 453 show_result("plfd", "FAIL"); 454 455 456 /*** pstfd ***/ 457 458 c.a = 987654.32; 459 460 /* pstfd frs10, 0(r3), 0 */ 461 stepped = emulate_step(®s, TEST_PSTFD(10, 3, 0, 0)); 462 463 if (stepped == 1 && c.b == cached_b) 464 show_result("pstfd", "PASS"); 465 else 466 show_result("pstfd", "FAIL"); 467} 468#else 469static void __init test_lfsx_stfsx(void) 470{ 471 show_result("lfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 472 show_result("stfsx", "SKIP (CONFIG_PPC_FPU is not set)"); 473} 474 475static void __init test_plfs_pstfs(void) 476{ 477 show_result("plfs", "SKIP (CONFIG_PPC_FPU is not set)"); 478 show_result("pstfs", "SKIP (CONFIG_PPC_FPU is not set)"); 479} 480 481static void __init test_lfdx_stfdx(void) 482{ 483 show_result("lfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 484 show_result("stfdx", "SKIP (CONFIG_PPC_FPU is not set)"); 485} 486 487static void __init test_plfd_pstfd(void) 488{ 489 show_result("plfd", "SKIP (CONFIG_PPC_FPU is not set)"); 490 show_result("pstfd", "SKIP (CONFIG_PPC_FPU is not set)"); 491} 492#endif /* CONFIG_PPC_FPU */ 493 494#ifdef CONFIG_ALTIVEC 495static void __init test_lvx_stvx(void) 496{ 497 struct pt_regs regs; 498 union { 499 vector128 a; 500 u32 b[4]; 501 } c; 502 u32 cached_b[4]; 503 int stepped = -1; 504 505 init_pt_regs(®s); 506 507 508 /*** lvx ***/ 509 510 cached_b[0] = c.b[0] = 923745; 511 cached_b[1] = c.b[1] = 2139478; 512 cached_b[2] = c.b[2] = 9012; 513 cached_b[3] = c.b[3] = 982134; 514 515 regs.gpr[3] = (unsigned long) &c.a; 516 regs.gpr[4] = 0; 517 518 /* lvx vrt10, r3, r4 */ 519 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LVX(10, 3, 4))); 520 521 if (stepped == 1) 522 show_result("lvx", "PASS"); 523 else 524 show_result("lvx", "FAIL"); 525 526 527 /*** stvx ***/ 528 529 c.b[0] = 4987513; 530 c.b[1] = 84313948; 531 c.b[2] = 71; 532 c.b[3] = 498532; 533 534 /* stvx vrs10, r3, r4 */ 535 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STVX(10, 3, 4))); 536 537 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 538 cached_b[2] == c.b[2] && cached_b[3] == c.b[3]) 539 show_result("stvx", "PASS"); 540 else 541 show_result("stvx", "FAIL"); 542} 543#else 544static void __init test_lvx_stvx(void) 545{ 546 show_result("lvx", "SKIP (CONFIG_ALTIVEC is not set)"); 547 show_result("stvx", "SKIP (CONFIG_ALTIVEC is not set)"); 548} 549#endif /* CONFIG_ALTIVEC */ 550 551#ifdef CONFIG_VSX 552static void __init test_lxvd2x_stxvd2x(void) 553{ 554 struct pt_regs regs; 555 union { 556 vector128 a; 557 u32 b[4]; 558 } c; 559 u32 cached_b[4]; 560 int stepped = -1; 561 562 init_pt_regs(®s); 563 564 565 /*** lxvd2x ***/ 566 567 cached_b[0] = c.b[0] = 18233; 568 cached_b[1] = c.b[1] = 34863571; 569 cached_b[2] = c.b[2] = 834; 570 cached_b[3] = c.b[3] = 6138911; 571 572 regs.gpr[3] = (unsigned long) &c.a; 573 regs.gpr[4] = 0; 574 575 /* lxvd2x vsr39, r3, r4 */ 576 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVD2X(39, R3, R4))); 577 578 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 579 show_result("lxvd2x", "PASS"); 580 } else { 581 if (!cpu_has_feature(CPU_FTR_VSX)) 582 show_result("lxvd2x", "PASS (!CPU_FTR_VSX)"); 583 else 584 show_result("lxvd2x", "FAIL"); 585 } 586 587 588 /*** stxvd2x ***/ 589 590 c.b[0] = 21379463; 591 c.b[1] = 87; 592 c.b[2] = 374234; 593 c.b[3] = 4; 594 595 /* stxvd2x vsr39, r3, r4 */ 596 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVD2X(39, R3, R4))); 597 598 if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && 599 cached_b[2] == c.b[2] && cached_b[3] == c.b[3] && 600 cpu_has_feature(CPU_FTR_VSX)) { 601 show_result("stxvd2x", "PASS"); 602 } else { 603 if (!cpu_has_feature(CPU_FTR_VSX)) 604 show_result("stxvd2x", "PASS (!CPU_FTR_VSX)"); 605 else 606 show_result("stxvd2x", "FAIL"); 607 } 608} 609#else 610static void __init test_lxvd2x_stxvd2x(void) 611{ 612 show_result("lxvd2x", "SKIP (CONFIG_VSX is not set)"); 613 show_result("stxvd2x", "SKIP (CONFIG_VSX is not set)"); 614} 615#endif /* CONFIG_VSX */ 616 617#ifdef CONFIG_VSX 618static void __init test_lxvp_stxvp(void) 619{ 620 struct pt_regs regs; 621 union { 622 vector128 a; 623 u32 b[4]; 624 } c[2]; 625 u32 cached_b[8]; 626 int stepped = -1; 627 628 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 629 show_result("lxvp", "SKIP (!CPU_FTR_ARCH_31)"); 630 show_result("stxvp", "SKIP (!CPU_FTR_ARCH_31)"); 631 return; 632 } 633 634 init_pt_regs(®s); 635 636 /*** lxvp ***/ 637 638 cached_b[0] = c[0].b[0] = 18233; 639 cached_b[1] = c[0].b[1] = 34863571; 640 cached_b[2] = c[0].b[2] = 834; 641 cached_b[3] = c[0].b[3] = 6138911; 642 cached_b[4] = c[1].b[0] = 1234; 643 cached_b[5] = c[1].b[1] = 5678; 644 cached_b[6] = c[1].b[2] = 91011; 645 cached_b[7] = c[1].b[3] = 121314; 646 647 regs.gpr[4] = (unsigned long)&c[0].a; 648 649 /* 650 * lxvp XTp,DQ(RA) 651 * XTp = 32xTX + 2xTp 652 * let TX=1 Tp=1 RA=4 DQ=0 653 */ 654 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVP(34, 4, 0))); 655 656 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 657 show_result("lxvp", "PASS"); 658 } else { 659 if (!cpu_has_feature(CPU_FTR_VSX)) 660 show_result("lxvp", "PASS (!CPU_FTR_VSX)"); 661 else 662 show_result("lxvp", "FAIL"); 663 } 664 665 /*** stxvp ***/ 666 667 c[0].b[0] = 21379463; 668 c[0].b[1] = 87; 669 c[0].b[2] = 374234; 670 c[0].b[3] = 4; 671 c[1].b[0] = 90; 672 c[1].b[1] = 122; 673 c[1].b[2] = 555; 674 c[1].b[3] = 32144; 675 676 /* 677 * stxvp XSp,DQ(RA) 678 * XSp = 32xSX + 2xSp 679 * let SX=1 Sp=1 RA=4 DQ=0 680 */ 681 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVP(34, 4, 0))); 682 683 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] && 684 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] && 685 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] && 686 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] && 687 cpu_has_feature(CPU_FTR_VSX)) { 688 show_result("stxvp", "PASS"); 689 } else { 690 if (!cpu_has_feature(CPU_FTR_VSX)) 691 show_result("stxvp", "PASS (!CPU_FTR_VSX)"); 692 else 693 show_result("stxvp", "FAIL"); 694 } 695} 696#else 697static void __init test_lxvp_stxvp(void) 698{ 699 show_result("lxvp", "SKIP (CONFIG_VSX is not set)"); 700 show_result("stxvp", "SKIP (CONFIG_VSX is not set)"); 701} 702#endif /* CONFIG_VSX */ 703 704#ifdef CONFIG_VSX 705static void __init test_lxvpx_stxvpx(void) 706{ 707 struct pt_regs regs; 708 union { 709 vector128 a; 710 u32 b[4]; 711 } c[2]; 712 u32 cached_b[8]; 713 int stepped = -1; 714 715 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 716 show_result("lxvpx", "SKIP (!CPU_FTR_ARCH_31)"); 717 show_result("stxvpx", "SKIP (!CPU_FTR_ARCH_31)"); 718 return; 719 } 720 721 init_pt_regs(®s); 722 723 /*** lxvpx ***/ 724 725 cached_b[0] = c[0].b[0] = 18233; 726 cached_b[1] = c[0].b[1] = 34863571; 727 cached_b[2] = c[0].b[2] = 834; 728 cached_b[3] = c[0].b[3] = 6138911; 729 cached_b[4] = c[1].b[0] = 1234; 730 cached_b[5] = c[1].b[1] = 5678; 731 cached_b[6] = c[1].b[2] = 91011; 732 cached_b[7] = c[1].b[3] = 121314; 733 734 regs.gpr[3] = (unsigned long)&c[0].a; 735 regs.gpr[4] = 0; 736 737 /* 738 * lxvpx XTp,RA,RB 739 * XTp = 32xTX + 2xTp 740 * let TX=1 Tp=1 RA=3 RB=4 741 */ 742 stepped = emulate_step(®s, ppc_inst(PPC_RAW_LXVPX(34, 3, 4))); 743 744 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 745 show_result("lxvpx", "PASS"); 746 } else { 747 if (!cpu_has_feature(CPU_FTR_VSX)) 748 show_result("lxvpx", "PASS (!CPU_FTR_VSX)"); 749 else 750 show_result("lxvpx", "FAIL"); 751 } 752 753 /*** stxvpx ***/ 754 755 c[0].b[0] = 21379463; 756 c[0].b[1] = 87; 757 c[0].b[2] = 374234; 758 c[0].b[3] = 4; 759 c[1].b[0] = 90; 760 c[1].b[1] = 122; 761 c[1].b[2] = 555; 762 c[1].b[3] = 32144; 763 764 /* 765 * stxvpx XSp,RA,RB 766 * XSp = 32xSX + 2xSp 767 * let SX=1 Sp=1 RA=3 RB=4 768 */ 769 stepped = emulate_step(®s, ppc_inst(PPC_RAW_STXVPX(34, 3, 4))); 770 771 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] && 772 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] && 773 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] && 774 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] && 775 cpu_has_feature(CPU_FTR_VSX)) { 776 show_result("stxvpx", "PASS"); 777 } else { 778 if (!cpu_has_feature(CPU_FTR_VSX)) 779 show_result("stxvpx", "PASS (!CPU_FTR_VSX)"); 780 else 781 show_result("stxvpx", "FAIL"); 782 } 783} 784#else 785static void __init test_lxvpx_stxvpx(void) 786{ 787 show_result("lxvpx", "SKIP (CONFIG_VSX is not set)"); 788 show_result("stxvpx", "SKIP (CONFIG_VSX is not set)"); 789} 790#endif /* CONFIG_VSX */ 791 792#ifdef CONFIG_VSX 793static void __init test_plxvp_pstxvp(void) 794{ 795 ppc_inst_t instr; 796 struct pt_regs regs; 797 union { 798 vector128 a; 799 u32 b[4]; 800 } c[2]; 801 u32 cached_b[8]; 802 int stepped = -1; 803 804 if (!cpu_has_feature(CPU_FTR_ARCH_31)) { 805 show_result("plxvp", "SKIP (!CPU_FTR_ARCH_31)"); 806 show_result("pstxvp", "SKIP (!CPU_FTR_ARCH_31)"); 807 return; 808 } 809 810 /*** plxvp ***/ 811 812 cached_b[0] = c[0].b[0] = 18233; 813 cached_b[1] = c[0].b[1] = 34863571; 814 cached_b[2] = c[0].b[2] = 834; 815 cached_b[3] = c[0].b[3] = 6138911; 816 cached_b[4] = c[1].b[0] = 1234; 817 cached_b[5] = c[1].b[1] = 5678; 818 cached_b[6] = c[1].b[2] = 91011; 819 cached_b[7] = c[1].b[3] = 121314; 820 821 init_pt_regs(®s); 822 regs.gpr[3] = (unsigned long)&c[0].a; 823 824 /* 825 * plxvp XTp,D(RA),R 826 * XTp = 32xTX + 2xTp 827 * let RA=3 R=0 D=d0||d1=0 R=0 Tp=1 TX=1 828 */ 829 instr = ppc_inst_prefix(PPC_RAW_PLXVP_P(34, 0, 3, 0), PPC_RAW_PLXVP_S(34, 0, 3, 0)); 830 831 stepped = emulate_step(®s, instr); 832 if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { 833 show_result("plxvp", "PASS"); 834 } else { 835 if (!cpu_has_feature(CPU_FTR_VSX)) 836 show_result("plxvp", "PASS (!CPU_FTR_VSX)"); 837 else 838 show_result("plxvp", "FAIL"); 839 } 840 841 /*** pstxvp ***/ 842 843 c[0].b[0] = 21379463; 844 c[0].b[1] = 87; 845 c[0].b[2] = 374234; 846 c[0].b[3] = 4; 847 c[1].b[0] = 90; 848 c[1].b[1] = 122; 849 c[1].b[2] = 555; 850 c[1].b[3] = 32144; 851 852 /* 853 * pstxvp XSp,D(RA),R 854 * XSp = 32xSX + 2xSp 855 * let RA=3 D=d0||d1=0 R=0 Sp=1 SX=1 856 */ 857 instr = ppc_inst_prefix(PPC_RAW_PSTXVP_P(34, 0, 3, 0), PPC_RAW_PSTXVP_S(34, 0, 3, 0)); 858 859 stepped = emulate_step(®s, instr); 860 861 if (stepped == 1 && cached_b[0] == c[0].b[0] && cached_b[1] == c[0].b[1] && 862 cached_b[2] == c[0].b[2] && cached_b[3] == c[0].b[3] && 863 cached_b[4] == c[1].b[0] && cached_b[5] == c[1].b[1] && 864 cached_b[6] == c[1].b[2] && cached_b[7] == c[1].b[3] && 865 cpu_has_feature(CPU_FTR_VSX)) { 866 show_result("pstxvp", "PASS"); 867 } else { 868 if (!cpu_has_feature(CPU_FTR_VSX)) 869 show_result("pstxvp", "PASS (!CPU_FTR_VSX)"); 870 else 871 show_result("pstxvp", "FAIL"); 872 } 873} 874#else 875static void __init test_plxvp_pstxvp(void) 876{ 877 show_result("plxvp", "SKIP (CONFIG_VSX is not set)"); 878 show_result("pstxvp", "SKIP (CONFIG_VSX is not set)"); 879} 880#endif /* CONFIG_VSX */ 881 882static void __init run_tests_load_store(void) 883{ 884 test_ld(); 885 test_pld(); 886 test_lwz(); 887 test_plwz(); 888 test_lwzx(); 889 test_std(); 890 test_pstd(); 891 test_ldarx_stdcx(); 892 test_lfsx_stfsx(); 893 test_plfs_pstfs(); 894 test_lfdx_stfdx(); 895 test_plfd_pstfd(); 896 test_lvx_stvx(); 897 test_lxvd2x_stxvd2x(); 898 test_lxvp_stxvp(); 899 test_lxvpx_stxvpx(); 900 test_plxvp_pstxvp(); 901} 902 903struct compute_test { 904 char *mnemonic; 905 unsigned long cpu_feature; 906 struct { 907 char *descr; 908 unsigned long flags; 909 ppc_inst_t instr; 910 struct pt_regs regs; 911 } subtests[MAX_SUBTESTS + 1]; 912}; 913 914/* Extreme values for si0||si1 (the MLS:D-form 34 bit immediate field) */ 915#define SI_MIN BIT(33) 916#define SI_MAX (BIT(33) - 1) 917#define SI_UMAX (BIT(34) - 1) 918 919static struct compute_test compute_tests[] = { 920 { 921 .mnemonic = "nop", 922 .subtests = { 923 { 924 .descr = "R0 = LONG_MAX", 925 .instr = ppc_inst(PPC_RAW_NOP()), 926 .regs = { 927 .gpr[0] = LONG_MAX, 928 } 929 } 930 } 931 }, 932 { 933 .mnemonic = "setb", 934 .cpu_feature = CPU_FTR_ARCH_300, 935 .subtests = { 936 { 937 .descr = "BFA = 1, CR = GT", 938 .instr = TEST_SETB(20, 1), 939 .regs = { 940 .ccr = 0x4000000, 941 } 942 }, 943 { 944 .descr = "BFA = 4, CR = LT", 945 .instr = TEST_SETB(20, 4), 946 .regs = { 947 .ccr = 0x8000, 948 } 949 }, 950 { 951 .descr = "BFA = 5, CR = EQ", 952 .instr = TEST_SETB(20, 5), 953 .regs = { 954 .ccr = 0x200, 955 } 956 } 957 } 958 }, 959 { 960 .mnemonic = "add", 961 .subtests = { 962 { 963 .descr = "RA = LONG_MIN, RB = LONG_MIN", 964 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 965 .regs = { 966 .gpr[21] = LONG_MIN, 967 .gpr[22] = LONG_MIN, 968 } 969 }, 970 { 971 .descr = "RA = LONG_MIN, RB = LONG_MAX", 972 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 973 .regs = { 974 .gpr[21] = LONG_MIN, 975 .gpr[22] = LONG_MAX, 976 } 977 }, 978 { 979 .descr = "RA = LONG_MAX, RB = LONG_MAX", 980 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 981 .regs = { 982 .gpr[21] = LONG_MAX, 983 .gpr[22] = LONG_MAX, 984 } 985 }, 986 { 987 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 988 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 989 .regs = { 990 .gpr[21] = ULONG_MAX, 991 .gpr[22] = ULONG_MAX, 992 } 993 }, 994 { 995 .descr = "RA = ULONG_MAX, RB = 0x1", 996 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 997 .regs = { 998 .gpr[21] = ULONG_MAX, 999 .gpr[22] = 0x1, 1000 } 1001 }, 1002 { 1003 .descr = "RA = INT_MIN, RB = INT_MIN", 1004 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1005 .regs = { 1006 .gpr[21] = INT_MIN, 1007 .gpr[22] = INT_MIN, 1008 } 1009 }, 1010 { 1011 .descr = "RA = INT_MIN, RB = INT_MAX", 1012 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1013 .regs = { 1014 .gpr[21] = INT_MIN, 1015 .gpr[22] = INT_MAX, 1016 } 1017 }, 1018 { 1019 .descr = "RA = INT_MAX, RB = INT_MAX", 1020 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1021 .regs = { 1022 .gpr[21] = INT_MAX, 1023 .gpr[22] = INT_MAX, 1024 } 1025 }, 1026 { 1027 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1028 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1029 .regs = { 1030 .gpr[21] = UINT_MAX, 1031 .gpr[22] = UINT_MAX, 1032 } 1033 }, 1034 { 1035 .descr = "RA = UINT_MAX, RB = 0x1", 1036 .instr = ppc_inst(PPC_RAW_ADD(20, 21, 22)), 1037 .regs = { 1038 .gpr[21] = UINT_MAX, 1039 .gpr[22] = 0x1, 1040 } 1041 } 1042 } 1043 }, 1044 { 1045 .mnemonic = "add.", 1046 .subtests = { 1047 { 1048 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1049 .flags = IGNORE_CCR, 1050 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1051 .regs = { 1052 .gpr[21] = LONG_MIN, 1053 .gpr[22] = LONG_MIN, 1054 } 1055 }, 1056 { 1057 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1058 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1059 .regs = { 1060 .gpr[21] = LONG_MIN, 1061 .gpr[22] = LONG_MAX, 1062 } 1063 }, 1064 { 1065 .descr = "RA = LONG_MAX, RB = LONG_MAX", 1066 .flags = IGNORE_CCR, 1067 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1068 .regs = { 1069 .gpr[21] = LONG_MAX, 1070 .gpr[22] = LONG_MAX, 1071 } 1072 }, 1073 { 1074 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 1075 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1076 .regs = { 1077 .gpr[21] = ULONG_MAX, 1078 .gpr[22] = ULONG_MAX, 1079 } 1080 }, 1081 { 1082 .descr = "RA = ULONG_MAX, RB = 0x1", 1083 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1084 .regs = { 1085 .gpr[21] = ULONG_MAX, 1086 .gpr[22] = 0x1, 1087 } 1088 }, 1089 { 1090 .descr = "RA = INT_MIN, RB = INT_MIN", 1091 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1092 .regs = { 1093 .gpr[21] = INT_MIN, 1094 .gpr[22] = INT_MIN, 1095 } 1096 }, 1097 { 1098 .descr = "RA = INT_MIN, RB = INT_MAX", 1099 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1100 .regs = { 1101 .gpr[21] = INT_MIN, 1102 .gpr[22] = INT_MAX, 1103 } 1104 }, 1105 { 1106 .descr = "RA = INT_MAX, RB = INT_MAX", 1107 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1108 .regs = { 1109 .gpr[21] = INT_MAX, 1110 .gpr[22] = INT_MAX, 1111 } 1112 }, 1113 { 1114 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1115 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1116 .regs = { 1117 .gpr[21] = UINT_MAX, 1118 .gpr[22] = UINT_MAX, 1119 } 1120 }, 1121 { 1122 .descr = "RA = UINT_MAX, RB = 0x1", 1123 .instr = ppc_inst(PPC_RAW_ADD_DOT(20, 21, 22)), 1124 .regs = { 1125 .gpr[21] = UINT_MAX, 1126 .gpr[22] = 0x1, 1127 } 1128 } 1129 } 1130 }, 1131 { 1132 .mnemonic = "addc", 1133 .subtests = { 1134 { 1135 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1136 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1137 .regs = { 1138 .gpr[21] = LONG_MIN, 1139 .gpr[22] = LONG_MIN, 1140 } 1141 }, 1142 { 1143 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1144 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1145 .regs = { 1146 .gpr[21] = LONG_MIN, 1147 .gpr[22] = LONG_MAX, 1148 } 1149 }, 1150 { 1151 .descr = "RA = LONG_MAX, RB = LONG_MAX", 1152 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1153 .regs = { 1154 .gpr[21] = LONG_MAX, 1155 .gpr[22] = LONG_MAX, 1156 } 1157 }, 1158 { 1159 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 1160 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1161 .regs = { 1162 .gpr[21] = ULONG_MAX, 1163 .gpr[22] = ULONG_MAX, 1164 } 1165 }, 1166 { 1167 .descr = "RA = ULONG_MAX, RB = 0x1", 1168 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1169 .regs = { 1170 .gpr[21] = ULONG_MAX, 1171 .gpr[22] = 0x1, 1172 } 1173 }, 1174 { 1175 .descr = "RA = INT_MIN, RB = INT_MIN", 1176 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1177 .regs = { 1178 .gpr[21] = INT_MIN, 1179 .gpr[22] = INT_MIN, 1180 } 1181 }, 1182 { 1183 .descr = "RA = INT_MIN, RB = INT_MAX", 1184 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1185 .regs = { 1186 .gpr[21] = INT_MIN, 1187 .gpr[22] = INT_MAX, 1188 } 1189 }, 1190 { 1191 .descr = "RA = INT_MAX, RB = INT_MAX", 1192 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1193 .regs = { 1194 .gpr[21] = INT_MAX, 1195 .gpr[22] = INT_MAX, 1196 } 1197 }, 1198 { 1199 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1200 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1201 .regs = { 1202 .gpr[21] = UINT_MAX, 1203 .gpr[22] = UINT_MAX, 1204 } 1205 }, 1206 { 1207 .descr = "RA = UINT_MAX, RB = 0x1", 1208 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1209 .regs = { 1210 .gpr[21] = UINT_MAX, 1211 .gpr[22] = 0x1, 1212 } 1213 }, 1214 { 1215 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 1216 .instr = ppc_inst(PPC_RAW_ADDC(20, 21, 22)), 1217 .regs = { 1218 .gpr[21] = LONG_MIN | (uint)INT_MIN, 1219 .gpr[22] = LONG_MIN | (uint)INT_MIN, 1220 } 1221 } 1222 } 1223 }, 1224 { 1225 .mnemonic = "addc.", 1226 .subtests = { 1227 { 1228 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1229 .flags = IGNORE_CCR, 1230 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1231 .regs = { 1232 .gpr[21] = LONG_MIN, 1233 .gpr[22] = LONG_MIN, 1234 } 1235 }, 1236 { 1237 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1238 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1239 .regs = { 1240 .gpr[21] = LONG_MIN, 1241 .gpr[22] = LONG_MAX, 1242 } 1243 }, 1244 { 1245 .descr = "RA = LONG_MAX, RB = LONG_MAX", 1246 .flags = IGNORE_CCR, 1247 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1248 .regs = { 1249 .gpr[21] = LONG_MAX, 1250 .gpr[22] = LONG_MAX, 1251 } 1252 }, 1253 { 1254 .descr = "RA = ULONG_MAX, RB = ULONG_MAX", 1255 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1256 .regs = { 1257 .gpr[21] = ULONG_MAX, 1258 .gpr[22] = ULONG_MAX, 1259 } 1260 }, 1261 { 1262 .descr = "RA = ULONG_MAX, RB = 0x1", 1263 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1264 .regs = { 1265 .gpr[21] = ULONG_MAX, 1266 .gpr[22] = 0x1, 1267 } 1268 }, 1269 { 1270 .descr = "RA = INT_MIN, RB = INT_MIN", 1271 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1272 .regs = { 1273 .gpr[21] = INT_MIN, 1274 .gpr[22] = INT_MIN, 1275 } 1276 }, 1277 { 1278 .descr = "RA = INT_MIN, RB = INT_MAX", 1279 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1280 .regs = { 1281 .gpr[21] = INT_MIN, 1282 .gpr[22] = INT_MAX, 1283 } 1284 }, 1285 { 1286 .descr = "RA = INT_MAX, RB = INT_MAX", 1287 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1288 .regs = { 1289 .gpr[21] = INT_MAX, 1290 .gpr[22] = INT_MAX, 1291 } 1292 }, 1293 { 1294 .descr = "RA = UINT_MAX, RB = UINT_MAX", 1295 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1296 .regs = { 1297 .gpr[21] = UINT_MAX, 1298 .gpr[22] = UINT_MAX, 1299 } 1300 }, 1301 { 1302 .descr = "RA = UINT_MAX, RB = 0x1", 1303 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1304 .regs = { 1305 .gpr[21] = UINT_MAX, 1306 .gpr[22] = 0x1, 1307 } 1308 }, 1309 { 1310 .descr = "RA = LONG_MIN | INT_MIN, RB = LONG_MIN | INT_MIN", 1311 .instr = ppc_inst(PPC_RAW_ADDC_DOT(20, 21, 22)), 1312 .regs = { 1313 .gpr[21] = LONG_MIN | (uint)INT_MIN, 1314 .gpr[22] = LONG_MIN | (uint)INT_MIN, 1315 } 1316 } 1317 } 1318 }, 1319 { 1320 .mnemonic = "divde", 1321 .subtests = { 1322 { 1323 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1324 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 1325 .regs = { 1326 .gpr[21] = LONG_MIN, 1327 .gpr[22] = LONG_MIN, 1328 } 1329 }, 1330 { 1331 .descr = "RA = 1L, RB = 0", 1332 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 1333 .flags = IGNORE_GPR(20), 1334 .regs = { 1335 .gpr[21] = 1L, 1336 .gpr[22] = 0, 1337 } 1338 }, 1339 { 1340 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1341 .instr = ppc_inst(PPC_RAW_DIVDE(20, 21, 22)), 1342 .regs = { 1343 .gpr[21] = LONG_MIN, 1344 .gpr[22] = LONG_MAX, 1345 } 1346 } 1347 } 1348 }, 1349 { 1350 .mnemonic = "divde.", 1351 .subtests = { 1352 { 1353 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1354 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 1355 .regs = { 1356 .gpr[21] = LONG_MIN, 1357 .gpr[22] = LONG_MIN, 1358 } 1359 }, 1360 { 1361 .descr = "RA = 1L, RB = 0", 1362 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 1363 .flags = IGNORE_GPR(20), 1364 .regs = { 1365 .gpr[21] = 1L, 1366 .gpr[22] = 0, 1367 } 1368 }, 1369 { 1370 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1371 .instr = ppc_inst(PPC_RAW_DIVDE_DOT(20, 21, 22)), 1372 .regs = { 1373 .gpr[21] = LONG_MIN, 1374 .gpr[22] = LONG_MAX, 1375 } 1376 } 1377 } 1378 }, 1379 { 1380 .mnemonic = "divdeu", 1381 .subtests = { 1382 { 1383 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1384 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1385 .flags = IGNORE_GPR(20), 1386 .regs = { 1387 .gpr[21] = LONG_MIN, 1388 .gpr[22] = LONG_MIN, 1389 } 1390 }, 1391 { 1392 .descr = "RA = 1L, RB = 0", 1393 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1394 .flags = IGNORE_GPR(20), 1395 .regs = { 1396 .gpr[21] = 1L, 1397 .gpr[22] = 0, 1398 } 1399 }, 1400 { 1401 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1402 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1403 .regs = { 1404 .gpr[21] = LONG_MIN, 1405 .gpr[22] = LONG_MAX, 1406 } 1407 }, 1408 { 1409 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX", 1410 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1411 .regs = { 1412 .gpr[21] = LONG_MAX - 1, 1413 .gpr[22] = LONG_MAX, 1414 } 1415 }, 1416 { 1417 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN", 1418 .instr = ppc_inst(PPC_RAW_DIVDEU(20, 21, 22)), 1419 .flags = IGNORE_GPR(20), 1420 .regs = { 1421 .gpr[21] = LONG_MIN + 1, 1422 .gpr[22] = LONG_MIN, 1423 } 1424 } 1425 } 1426 }, 1427 { 1428 .mnemonic = "divdeu.", 1429 .subtests = { 1430 { 1431 .descr = "RA = LONG_MIN, RB = LONG_MIN", 1432 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1433 .flags = IGNORE_GPR(20), 1434 .regs = { 1435 .gpr[21] = LONG_MIN, 1436 .gpr[22] = LONG_MIN, 1437 } 1438 }, 1439 { 1440 .descr = "RA = 1L, RB = 0", 1441 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1442 .flags = IGNORE_GPR(20), 1443 .regs = { 1444 .gpr[21] = 1L, 1445 .gpr[22] = 0, 1446 } 1447 }, 1448 { 1449 .descr = "RA = LONG_MIN, RB = LONG_MAX", 1450 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1451 .regs = { 1452 .gpr[21] = LONG_MIN, 1453 .gpr[22] = LONG_MAX, 1454 } 1455 }, 1456 { 1457 .descr = "RA = LONG_MAX - 1, RB = LONG_MAX", 1458 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1459 .regs = { 1460 .gpr[21] = LONG_MAX - 1, 1461 .gpr[22] = LONG_MAX, 1462 } 1463 }, 1464 { 1465 .descr = "RA = LONG_MIN + 1, RB = LONG_MIN", 1466 .instr = ppc_inst(PPC_RAW_DIVDEU_DOT(20, 21, 22)), 1467 .flags = IGNORE_GPR(20), 1468 .regs = { 1469 .gpr[21] = LONG_MIN + 1, 1470 .gpr[22] = LONG_MIN, 1471 } 1472 } 1473 } 1474 }, 1475 { 1476 .mnemonic = "paddi", 1477 .cpu_feature = CPU_FTR_ARCH_31, 1478 .subtests = { 1479 { 1480 .descr = "RA = LONG_MIN, SI = SI_MIN, R = 0", 1481 .instr = TEST_PADDI(21, 22, SI_MIN, 0), 1482 .regs = { 1483 .gpr[21] = 0, 1484 .gpr[22] = LONG_MIN, 1485 } 1486 }, 1487 { 1488 .descr = "RA = LONG_MIN, SI = SI_MAX, R = 0", 1489 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1490 .regs = { 1491 .gpr[21] = 0, 1492 .gpr[22] = LONG_MIN, 1493 } 1494 }, 1495 { 1496 .descr = "RA = LONG_MAX, SI = SI_MAX, R = 0", 1497 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1498 .regs = { 1499 .gpr[21] = 0, 1500 .gpr[22] = LONG_MAX, 1501 } 1502 }, 1503 { 1504 .descr = "RA = ULONG_MAX, SI = SI_UMAX, R = 0", 1505 .instr = TEST_PADDI(21, 22, SI_UMAX, 0), 1506 .regs = { 1507 .gpr[21] = 0, 1508 .gpr[22] = ULONG_MAX, 1509 } 1510 }, 1511 { 1512 .descr = "RA = ULONG_MAX, SI = 0x1, R = 0", 1513 .instr = TEST_PADDI(21, 22, 0x1, 0), 1514 .regs = { 1515 .gpr[21] = 0, 1516 .gpr[22] = ULONG_MAX, 1517 } 1518 }, 1519 { 1520 .descr = "RA = INT_MIN, SI = SI_MIN, R = 0", 1521 .instr = TEST_PADDI(21, 22, SI_MIN, 0), 1522 .regs = { 1523 .gpr[21] = 0, 1524 .gpr[22] = INT_MIN, 1525 } 1526 }, 1527 { 1528 .descr = "RA = INT_MIN, SI = SI_MAX, R = 0", 1529 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1530 .regs = { 1531 .gpr[21] = 0, 1532 .gpr[22] = INT_MIN, 1533 } 1534 }, 1535 { 1536 .descr = "RA = INT_MAX, SI = SI_MAX, R = 0", 1537 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1538 .regs = { 1539 .gpr[21] = 0, 1540 .gpr[22] = INT_MAX, 1541 } 1542 }, 1543 { 1544 .descr = "RA = UINT_MAX, SI = 0x1, R = 0", 1545 .instr = TEST_PADDI(21, 22, 0x1, 0), 1546 .regs = { 1547 .gpr[21] = 0, 1548 .gpr[22] = UINT_MAX, 1549 } 1550 }, 1551 { 1552 .descr = "RA = UINT_MAX, SI = SI_MAX, R = 0", 1553 .instr = TEST_PADDI(21, 22, SI_MAX, 0), 1554 .regs = { 1555 .gpr[21] = 0, 1556 .gpr[22] = UINT_MAX, 1557 } 1558 }, 1559 { 1560 .descr = "RA is r0, SI = SI_MIN, R = 0", 1561 .instr = TEST_PADDI(21, 0, SI_MIN, 0), 1562 .regs = { 1563 .gpr[21] = 0x0, 1564 } 1565 }, 1566 { 1567 .descr = "RA = 0, SI = SI_MIN, R = 0", 1568 .instr = TEST_PADDI(21, 22, SI_MIN, 0), 1569 .regs = { 1570 .gpr[21] = 0x0, 1571 .gpr[22] = 0x0, 1572 } 1573 }, 1574 { 1575 .descr = "RA is r0, SI = 0, R = 1", 1576 .instr = TEST_PADDI(21, 0, 0, 1), 1577 .regs = { 1578 .gpr[21] = 0, 1579 } 1580 }, 1581 { 1582 .descr = "RA is r0, SI = SI_MIN, R = 1", 1583 .instr = TEST_PADDI(21, 0, SI_MIN, 1), 1584 .regs = { 1585 .gpr[21] = 0, 1586 } 1587 }, 1588 /* Invalid instruction form with R = 1 and RA != 0 */ 1589 { 1590 .descr = "RA = R22(0), SI = 0, R = 1", 1591 .instr = TEST_PADDI(21, 22, 0, 1), 1592 .flags = NEGATIVE_TEST, 1593 .regs = { 1594 .gpr[21] = 0, 1595 .gpr[22] = 0, 1596 } 1597 } 1598 } 1599 } 1600}; 1601 1602static int __init emulate_compute_instr(struct pt_regs *regs, 1603 ppc_inst_t instr, 1604 bool negative) 1605{ 1606 int analysed; 1607 struct instruction_op op; 1608 1609 if (!regs || !ppc_inst_val(instr)) 1610 return -EINVAL; 1611 1612 /* This is not a return frame regs */ 1613 regs->nip = patch_site_addr(&patch__exec_instr); 1614 1615 analysed = analyse_instr(&op, regs, instr); 1616 if (analysed != 1 || GETTYPE(op.type) != COMPUTE) { 1617 if (negative) 1618 return -EFAULT; 1619 pr_info("emulation failed, instruction = %s\n", ppc_inst_as_str(instr)); 1620 return -EFAULT; 1621 } 1622 if (analysed == 1 && negative) 1623 pr_info("negative test failed, instruction = %s\n", ppc_inst_as_str(instr)); 1624 if (!negative) 1625 emulate_update_regs(regs, &op); 1626 return 0; 1627} 1628 1629static int __init execute_compute_instr(struct pt_regs *regs, 1630 ppc_inst_t instr) 1631{ 1632 extern int exec_instr(struct pt_regs *regs); 1633 1634 if (!regs || !ppc_inst_val(instr)) 1635 return -EINVAL; 1636 1637 /* Patch the NOP with the actual instruction */ 1638 patch_instruction_site(&patch__exec_instr, instr); 1639 if (exec_instr(regs)) { 1640 pr_info("execution failed, instruction = %s\n", ppc_inst_as_str(instr)); 1641 return -EFAULT; 1642 } 1643 1644 return 0; 1645} 1646 1647#define gpr_mismatch(gprn, exp, got) \ 1648 pr_info("GPR%u mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1649 gprn, exp, got) 1650 1651#define reg_mismatch(name, exp, got) \ 1652 pr_info("%s mismatch, exp = 0x%016lx, got = 0x%016lx\n", \ 1653 name, exp, got) 1654 1655static void __init run_tests_compute(void) 1656{ 1657 unsigned long flags; 1658 struct compute_test *test; 1659 struct pt_regs *regs, exp, got; 1660 unsigned int i, j, k; 1661 ppc_inst_t instr; 1662 bool ignore_gpr, ignore_xer, ignore_ccr, passed, rc, negative; 1663 1664 for (i = 0; i < ARRAY_SIZE(compute_tests); i++) { 1665 test = &compute_tests[i]; 1666 1667 if (test->cpu_feature && !early_cpu_has_feature(test->cpu_feature)) { 1668 show_result(test->mnemonic, "SKIP (!CPU_FTR)"); 1669 continue; 1670 } 1671 1672 for (j = 0; j < MAX_SUBTESTS && test->subtests[j].descr; j++) { 1673 instr = test->subtests[j].instr; 1674 flags = test->subtests[j].flags; 1675 regs = &test->subtests[j].regs; 1676 negative = flags & NEGATIVE_TEST; 1677 ignore_xer = flags & IGNORE_XER; 1678 ignore_ccr = flags & IGNORE_CCR; 1679 passed = true; 1680 1681 memcpy(&exp, regs, sizeof(struct pt_regs)); 1682 memcpy(&got, regs, sizeof(struct pt_regs)); 1683 1684 /* 1685 * Set a compatible MSR value explicitly to ensure 1686 * that XER and CR bits are updated appropriately 1687 */ 1688 exp.msr = MSR_KERNEL; 1689 got.msr = MSR_KERNEL; 1690 1691 rc = emulate_compute_instr(&got, instr, negative) != 0; 1692 if (negative) { 1693 /* skip executing instruction */ 1694 passed = rc; 1695 goto print; 1696 } else if (rc || execute_compute_instr(&exp, instr)) { 1697 passed = false; 1698 goto print; 1699 } 1700 1701 /* Verify GPR values */ 1702 for (k = 0; k < 32; k++) { 1703 ignore_gpr = flags & IGNORE_GPR(k); 1704 if (!ignore_gpr && exp.gpr[k] != got.gpr[k]) { 1705 passed = false; 1706 gpr_mismatch(k, exp.gpr[k], got.gpr[k]); 1707 } 1708 } 1709 1710 /* Verify LR value */ 1711 if (exp.link != got.link) { 1712 passed = false; 1713 reg_mismatch("LR", exp.link, got.link); 1714 } 1715 1716 /* Verify XER value */ 1717 if (!ignore_xer && exp.xer != got.xer) { 1718 passed = false; 1719 reg_mismatch("XER", exp.xer, got.xer); 1720 } 1721 1722 /* Verify CR value */ 1723 if (!ignore_ccr && exp.ccr != got.ccr) { 1724 passed = false; 1725 reg_mismatch("CR", exp.ccr, got.ccr); 1726 } 1727 1728print: 1729 show_result_with_descr(test->mnemonic, 1730 test->subtests[j].descr, 1731 passed ? "PASS" : "FAIL"); 1732 } 1733 } 1734} 1735 1736static int __init test_emulate_step(void) 1737{ 1738 printk(KERN_INFO "Running instruction emulation self-tests ...\n"); 1739 run_tests_load_store(); 1740 run_tests_compute(); 1741 1742 return 0; 1743} 1744late_initcall(test_emulate_step);