linux/arch/powerpc/lib/test_emulate_step.c
<<
>>
Prefs
   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(&regs);
  99        regs.gpr[3] = (unsigned long) &a;
 100
 101        /* ld r5, 0(r3) */
 102        stepped = emulate_step(&regs, 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(&regs);
 122        regs.gpr[3] = (unsigned long)&a;
 123
 124        /* pld r5, 0(r3), 0 */
 125        stepped = emulate_step(&regs, 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(&regs);
 140        regs.gpr[3] = (unsigned long) &a;
 141
 142        /* lwz r5, 0(r3) */
 143        stepped = emulate_step(&regs, 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(&regs);
 163        regs.gpr[3] = (unsigned long)&a;
 164
 165        /* plwz r5, 0(r3), 0 */
 166
 167        stepped = emulate_step(&regs, 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(&regs);
 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(&regs, 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(&regs);
 201        regs.gpr[3] = (unsigned long) &a;
 202        regs.gpr[5] = 0x5678;
 203
 204        /* std r5, 0(r3) */
 205        stepped = emulate_step(&regs, 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(&regs);
 224        regs.gpr[3] = (unsigned long)&a;
 225        regs.gpr[5] = 0x5678;
 226
 227        /* pstd r5, 0(r3), 0 */
 228        stepped = emulate_step(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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(&regs);
 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(&regs, 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(&regs, 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        struct ppc_inst 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(&regs);
 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(&regs, 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(&regs, 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                struct ppc_inst 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                                        struct ppc_inst 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                                        struct ppc_inst 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        struct ppc_inst 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);
1745