root/arch/powerpc/lib/test_emulate_step.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. init_pt_regs
  2. show_result
  3. show_result_with_descr
  4. test_ld
  5. test_lwz
  6. test_lwzx
  7. test_std
  8. test_ldarx_stdcx
  9. test_lfsx_stfsx
  10. test_lfdx_stfdx
  11. test_lfsx_stfsx
  12. test_lfdx_stfdx
  13. test_lvx_stvx
  14. test_lvx_stvx
  15. test_lxvd2x_stxvd2x
  16. test_lxvd2x_stxvd2x
  17. run_tests_load_store
  18. emulate_compute_instr
  19. execute_compute_instr
  20. run_tests_compute
  21. test_emulate_step

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

/* [<][>][^][v][top][bottom][index][help] */