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