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