~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/lib/test_emulate_step.c

Version: ~ [ linux-5.12-rc7 ] ~ [ linux-5.11.13 ] ~ [ linux-5.10.29 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.111 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.186 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.230 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.266 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.266 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.18.140 ] ~ [ linux-3.16.85 ] ~ [ linux-3.14.79 ] ~ [ linux-3.12.74 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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);
967 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp