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