xref: /kvm-unit-tests/powerpc/sprs.c (revision 851ef5165069857e56e35b01c8ed43b115c2737e)
1 /*
2  * Test Special Purpose Registers
3  *
4  * Copyright 2017  Thomas Huth, Red Hat Inc.
5  *
6  * This work is licensed under the terms of the GNU LGPL, version 2.
7  *
8  * The basic idea of this test is to check whether the contents of the Special
9  * Purpose Registers (SPRs) are preserved correctly during migration. So we
10  * fill in the SPRs with a well-known value, read the values back (since not
11  * all bits might be retained in the SPRs), then wait for migration to complete
12  * (if the '-w' option has been specified) so that the user has a chance to
13  * migrate the VM. Alternatively, the test can also simply sleep a little bit
14  * with the H_CEDE hypercall, in the hope that we'll get scheduled to another
15  * host CPU and thus register contents might have changed, too (in case of
16  * bugs). Finally, we read back the values from the SPRs and compare them with
17  * the values before the migration. Mismatches are reported as test failures.
18  * Note that we do not test all SPRs since some of the registers change their
19  * content automatically, and some are only accessible with hypervisor privi-
20  * leges or have bad side effects, so we have to omit those registers.
21  */
22 #include <libcflat.h>
23 #include <util.h>
24 #include <migrate.h>
25 #include <alloc.h>
26 #include <asm/ppc_asm.h>
27 #include <asm/handlers.h>
28 #include <asm/hcall.h>
29 #include <asm/processor.h>
30 #include <asm/time.h>
31 #include <asm/barrier.h>
32 
33 /* "Indirect" mfspr/mtspr which accept a non-constant spr number */
__mfspr(unsigned spr)34 static uint64_t __mfspr(unsigned spr)
35 {
36 	uint64_t tmp;
37 	uint64_t ret;
38 
39 	asm volatile(
40 "	bcl	20, 31, 1f		\n"
41 "1:	mflr	%0			\n"
42 "	addi	%0, %0, (2f-1b)		\n"
43 "	add	%0, %0, %2		\n"
44 "	mtctr	%0			\n"
45 "	bctr				\n"
46 "2:					\n"
47 ".LSPR=0				\n"
48 ".rept 1024				\n"
49 "	mfspr	%1, .LSPR		\n"
50 "	b	3f			\n"
51 "	.LSPR=.LSPR+1			\n"
52 ".endr					\n"
53 "3:					\n"
54 	: "=&r"(tmp),
55 	  "=r"(ret)
56 	: "r"(spr*8) /* 8 bytes per 'mfspr ; b' block */
57 	: "lr", "ctr");
58 
59 	return ret;
60 }
61 
__mtspr(unsigned spr,uint64_t val)62 static void __mtspr(unsigned spr, uint64_t val)
63 {
64 	uint64_t tmp;
65 
66 	asm volatile(
67 "	bcl	20, 31, 1f		\n"
68 "1:	mflr	%0			\n"
69 "	addi	%0, %0, (2f-1b)		\n"
70 "	add	%0, %0, %2		\n"
71 "	mtctr	%0			\n"
72 "	bctr				\n"
73 "2:					\n"
74 ".LSPR=0				\n"
75 ".rept 1024				\n"
76 "	mtspr	.LSPR, %1		\n"
77 "	b	3f			\n"
78 "	.LSPR=.LSPR+1			\n"
79 ".endr					\n"
80 "3:					\n"
81 	: "=&r"(tmp)
82 	: "r"(val),
83 	  "r"(spr*8) /* 8 bytes per 'mfspr ; b' block */
84 	: "lr", "ctr", "xer");
85 }
86 
87 static uint64_t before[1024], after[1024];
88 
89 #define SPR_PR_READ	0x0001
90 #define SPR_PR_WRITE	0x0002
91 #define SPR_OS_READ	0x0010
92 #define SPR_OS_WRITE	0x0020
93 #define SPR_HV_READ	0x0100
94 #define SPR_HV_WRITE	0x0200
95 
96 #define RW		0x333
97 #define RO		0x111
98 #define WO		0x222
99 #define OS_RW		0x330
100 #define OS_RO		0x110
101 #define OS_WO		0x220
102 #define HV_RW		0x300
103 #define HV_RO		0x100
104 #define HV_WO		0x200
105 
106 #define SPR_ASYNC	0x1000	/* May be updated asynchronously */
107 #define SPR_INT		0x2000	/* May be updated by synchronous interrupt */
108 #define SPR_HARNESS	0x4000	/* Test harness uses the register */
109 
110 struct spr {
111 	const char	*name;
112 	uint8_t		width;
113 	uint16_t	access;
114 	uint16_t	type;
115 };
116 
117 /* SPRs common denominator back to PowerPC Operating Environment Architecture */
118 static const struct spr sprs_common[1024] = {
119   [1] = { "XER",	64,	RW,		SPR_HARNESS, }, /* Used by compiler */
120   [8] = { "LR", 	64,	RW,		SPR_HARNESS, }, /* Compiler, mfspr/mtspr */
121   [9] = { "CTR",	64,	RW,		SPR_HARNESS, }, /* Compiler, mfspr/mtspr */
122  [18] = { "DSISR",	32,	OS_RW,		SPR_INT, },
123  [19] = { "DAR",	64,	OS_RW,		SPR_INT, },
124  [26] = { "SRR0",	64,	OS_RW,		SPR_INT, },
125  [27] = { "SRR1",	64,	OS_RW,		SPR_INT, },
126 [268] = { "TB",		64,	RO	,	SPR_ASYNC, },
127 [269] = { "TBU",	32,	RO,		SPR_ASYNC, },
128 [272] = { "SPRG0",	64,	OS_RW,		SPR_HARNESS, }, /* Interrupt stacr */
129 [273] = { "SPRG1",	64,	OS_RW,		SPR_HARNESS, }, /* Interrupt Scratch */
130 [274] = { "SPRG2",	64,	OS_RW, },
131 [275] = { "SPRG3",	64,	OS_RW, },
132 [287] = { "PVR",	32,	OS_RO, },
133 };
134 
135 /* SPRs from PowerPC Operating Environment Architecture, Book III, Vers. 2.01 */
136 static const struct spr sprs_201[1024] = {
137  [22] = { "DEC",	32,	OS_RW,		SPR_ASYNC, },
138  [25] = { "SDR1",	64,	HV_RW | OS_RO, },
139  [29] = { "ACCR",	64,	OS_RW, },
140 [136] = { "CTRL",	32,	RO, },
141 [152] = { "CTRL",	32,	OS_WO, },
142 [259] = { "SPRG3",	64,	RO, },
143 /* ASR, EAR omitted */
144 [284] = { "TBL",	32,	HV_WO, },
145 [285] = { "TBU",	32,	HV_WO, },
146 [310] = { "HDEC",	32,	HV_RW,		SPR_ASYNC, },
147 [1013]= { "DABR",	64,	HV_RW | OS_RO, },
148 [1023]= { "PIR",	32,	OS_RO,		SPR_ASYNC, }, /* Can't be virtualised, appears to be async */
149 };
150 
151 static const struct spr sprs_970_pmu[1024] = {
152 /* POWER4+ PMU, should confirm with PPC970 */
153 [770] = { "MMCRA",	64,	RO, },
154 [771] = { "PMC1",	32,	RO, },
155 [772] = { "PMC2",	32,	RO, },
156 [773] = { "PMC3",	32,	RO, },
157 [774] = { "PMC4",	32,	RO, },
158 [775] = { "PMC5",	32,	RO, },
159 [776] = { "PMC6",	32,	RO, },
160 [777] = { "PMC7",	32,	RO, },
161 [778] = { "PMC8",	32,	RO, },
162 [779] = { "MMCR0",	64,	RO, },
163 [780] = { "SIAR",	64,	RO, },
164 [781] = { "SDAR",	64,	RO, },
165 [782] = { "MMCR1",	64,	RO, },
166 [786] = { "MMCRA",	64,	OS_RW, },
167 [787] = { "PMC1",	32,	OS_RW, },
168 [788] = { "PMC2",	32,	OS_RW, },
169 [789] = { "PMC3",	32,	OS_RW, },
170 [790] = { "PMC4",	32,	OS_RW, },
171 [791] = { "PMC5",	32,	OS_RW, },
172 [792] = { "PMC6",	32,	OS_RW, },
173 [793] = { "PMC7",	32,	OS_RW, },
174 [794] = { "PMC8",	32,	OS_RW, },
175 [795] = { "MMCR0",	64,	OS_RW, },
176 [796] = { "SIAR",	64,	OS_RW, },
177 [797] = { "SDAR",	64,	OS_RW, },
178 [798] = { "MMCR1",	64,	OS_RW, },
179 };
180 
181 /* These are common SPRs from 2.07S onward (POWER CPUs that support KVM HV) */
182 static const struct spr sprs_power_common[1024] = {
183   [3] = { "DSCR",	64,	RW, },
184  [13] = { "AMR",	64,	RW, },
185  [17] = { "DSCR",	64,	OS_RW, },
186  [28] = { "CFAR",	64,	OS_RW,		SPR_ASYNC, }, /* Effectively async */
187  [29] = { "AMR",	64,	OS_RW, },
188  [61] = { "IAMR",	64,	OS_RW, },
189 [136] = { "CTRL",	32,	RO, },
190 [152] = { "CTRL",	32,	OS_WO, },
191 [153] = { "FSCR",	64,	OS_RW, },
192 [157] = { "UAMOR",	64,	OS_RW, },
193 [159] = { "PSPB",	32,	OS_RW, },
194 [176] = { "DPDES",	64,	HV_RW | OS_RO, },
195 [180] = { "DAWR0",	64,	HV_RW, },
196 [186] = { "RPR",	64,	HV_RW, },
197 [187] = { "CIABR",	64,	HV_RW, },
198 [188] = { "DAWRX0",	32,	HV_RW, },
199 [190] = { "HFSCR",	64,	HV_RW, },
200 [256] = { "VRSAVE",	32,	RW, },
201 [259] = { "SPRG3",	64,	RO, },
202 [284] = { "TBL",	32,	HV_WO, }, /* Things can go a bit wonky with */
203 [285] = { "TBU",	32,	HV_WO, }, /* Timebase changing. Should save */
204 [286] = { "TBU40",	64,	HV_WO, }, /* and restore it. */
205 [304] = { "HSPRG0",	64,	HV_RW, },
206 [305] = { "HSPRG1",	64,	HV_RW, },
207 [306] = { "HDSISR",	32,	HV_RW,		SPR_INT, },
208 [307] = { "HDAR",	64,	HV_RW,		SPR_INT, },
209 [308] = { "SPURR",	64,	HV_RW | OS_RO,	SPR_ASYNC, },
210 [309] = { "PURR",	64,	HV_RW | OS_RO,	SPR_ASYNC, },
211 [313] = { "HRMOR",	64,	HV_RW,		SPR_HARNESS, }, /* Harness can't cope with HRMOR changing */
212 [314] = { "HSRR0",	64,	HV_RW,		SPR_INT, },
213 [315] = { "HSRR1",	64,	HV_RW,		SPR_INT, },
214 [318] = { "LPCR",	64,	HV_RW, },
215 [319] = { "LPIDR",	32,	HV_RW, },
216 [336] = { "HMER",	64,	HV_RW, },
217 [337] = { "HMEER",	64,	HV_RW, },
218 [338] = { "PCR",	64,	HV_RW, },
219 [349] = { "AMOR",	64,	HV_RW, },
220 [446] = { "TIR",	64,	OS_RO, },
221 [800] = { "BESCRS",	64,	RW, },
222 [801] = { "BESCRSU",	32,	RW, },
223 [802] = { "BESCRR",	64,	RW, },
224 [803] = { "BESCRRU",	32,	RW, },
225 [804] = { "EBBHR",	64,	RW, },
226 [805] = { "EBBRR",	64,	RW, },
227 [806] = { "BESCR",	64,	RW, },
228 [815] = { "TAR",	64,	RW, },
229 [848] = { "IC",		64,	HV_RW | OS_RO,	SPR_ASYNC, },
230 [849] = { "VTB",	64,	HV_RW | OS_RO,	SPR_ASYNC, },
231 [896] = { "PPR",	64,	RW,		SPR_ASYNC, }, /* PPR(32) is changed by cpu_relax(), appears to be async */
232 [898] = { "PPR32",	32,	RW,		SPR_ASYNC, },
233 [1023]= { "PIR",	32,	OS_RO,		SPR_ASYNC, }, /* Can't be virtualised, appears to be async */
234 };
235 
236 static const struct spr sprs_tm[1024] = {
237 #if 0
238 	/* XXX: leave these out until enabling TM facility (and more testing) */
239 [128] = { "TFHAR",	64,	RW, },
240 [129] = { "TFIAR",	64,	RW, },
241 [130] = { "TEXASR",	64,	RW, },
242 [131] = { "TEXASRU",	32,	RW, },
243 #endif
244 };
245 
246 /* SPRs from PowerISA 2.07 Book III-S */
247 static const struct spr sprs_207[1024] = {
248  [22] = { "DEC",	32,	OS_RW,		SPR_ASYNC, },
249  [25] = { "SDR1",	64,	HV_RW, },
250 [177] = { "DHDES",	64,	HV_RW, },
251 [283] = { "CIR",	32,	OS_RO, },
252 [310] = { "HDEC",	32,	HV_RW,		SPR_ASYNC, },
253 [312] = { "RMOR",	64,	HV_RW, },
254 [339] = { "HEIR",	32,	HV_RW,		SPR_INT, },
255 };
256 
257 /* SPRs from PowerISA 3.00 Book III */
258 static const struct spr sprs_300[1024] = {
259  [22] = { "DEC",	64,	OS_RW,		SPR_ASYNC, },
260  [48] = { "PIDR",	32,	OS_RW, },
261 [144] = { "TIDR",	64,	OS_RW, },
262 [283] = { "CIR",	32,	OS_RO, },
263 [310] = { "HDEC",	64,	HV_RW,		SPR_ASYNC, },
264 [339] = { "HEIR",	32,	HV_RW,		SPR_INT, },
265 [464] = { "PTCR",	64,	HV_RW, },
266 [816] = { "ASDR",	64,	HV_RW,		SPR_INT, },
267 [823] = { "PSSCR",	64,	OS_RW, },
268 [855] = { "PSSCR",	64,	HV_RW, },
269 };
270 
271 /* SPRs from PowerISA 3.1B Book III */
272 static const struct spr sprs_31[1024] = {
273  [22] = { "DEC",	64,	OS_RW,		SPR_ASYNC, },
274  [48] = { "PIDR",	32,	OS_RW, },
275 [181] = { "DAWR1",	64,	HV_RW, },
276 [189] = { "DAWRX1",	32,	HV_RW, },
277 [310] = { "HDEC",	64,	HV_RW,		SPR_ASYNC, },
278 [339] = { "HEIR",	64,	HV_RW,		SPR_INT, },
279 [455] = { "HDEXCR",	32,	RO, },
280 [464] = { "PTCR",	64,	HV_RW, },
281 [468] = { "HASHKEYR",	64,	OS_RW, },
282 [469] = { "HASHPKEYR",	64,	HV_RW, },
283 [471] = { "HDEXCR",	64,	HV_RW, },
284 [812] = { "DEXCR",	32,	RO, },
285 [816] = { "ASDR",	64,	HV_RW,		SPR_INT, },
286 [823] = { "PSSCR",	64,	OS_RW, },
287 [828] = { "DEXCR",	64,	OS_RW, },
288 [855] = { "PSSCR",	64,	HV_RW, },
289 };
290 
291 /* SPRs POWER9, POWER10 User Manual */
292 static const struct spr sprs_power9_10[1024] = {
293 [276] = { "SPRC",	64,	HV_RW, },
294 [277] = { "SPRD",	64,	HV_RW, },
295 [317] = { "TFMR",	64,	HV_RW, },
296 [799] = { "IMC",	64,	HV_RW, },
297 [850] = { "LDBAR",	64,	HV_RO, },
298 [851] = { "MMCRC",	32,	HV_RW, },
299 [853] = { "PMSR",	32,	HV_RO, },
300 [861] = { "L2QOSR",	64,	HV_WO, },
301 [881] = { "TRIG1",	64,	OS_WO, },
302 [882] = { "TRIG2",	64,	OS_WO, },
303 [884] = { "PMCR",	64,	HV_RW, },
304 [885] = { "RWMR",	64,	HV_RW, },
305 [895] = { "WORT",	64,	OS_RW, }, /* UM says 18-bits! */
306 [921] = { "TSCR",	32,	HV_RW, },
307 [922] = { "TTR",	64,	HV_RW, },
308 [1006]= { "TRACE",	64,	WO, },
309 [1008]= { "HID",	64,	HV_RW,		SPR_HARNESS, }, /* HILE would be unhelpful to change */
310 };
311 
312 /* This covers POWER8 and POWER9 PMUs */
313 static const struct spr sprs_power_common_pmu[1024] = {
314 [768] = { "SIER",	64,	RO, },
315 [769] = { "MMCR2",	64,	RW, },
316 [770] = { "MMCRA",	64,	RW, },
317 [771] = { "PMC1",	32,	RW, },
318 [772] = { "PMC2",	32,	RW, },
319 [773] = { "PMC3",	32,	RW, },
320 [774] = { "PMC4",	32,	RW, },
321 [775] = { "PMC5",	32,	RW, },
322 [776] = { "PMC6",	32,	RW, },
323 [779] = { "MMCR0",	64,	RW, },
324 [780] = { "SIAR",	64,	RO, },
325 [781] = { "SDAR",	64,	RO, },
326 [782] = { "MMCR1",	64,	RO, },
327 [784] = { "SIER",	64,	OS_RW, },
328 [785] = { "MMCR2",	64,	OS_RW, },
329 [786] = { "MMCRA",	64,	OS_RW, },
330 [787] = { "PMC1",	32,	OS_RW, },
331 [788] = { "PMC2",	32,	OS_RW, },
332 [789] = { "PMC3",	32,	OS_RW, },
333 [790] = { "PMC4",	32,	OS_RW, },
334 [791] = { "PMC5",	32,	OS_RW, },
335 [792] = { "PMC6",	32,	OS_RW, },
336 [795] = { "MMCR0",	64,	OS_RW, },
337 [796] = { "SIAR",	64,	OS_RW, },
338 [797] = { "SDAR",	64,	OS_RW, },
339 [798] = { "MMCR1",	64,	OS_RW, },
340 };
341 
342 static const struct spr sprs_power10_pmu[1024] = {
343 [736] = { "SIER2",	64,	RO, },
344 [737] = { "SIER3",	64,	RO, },
345 [738] = { "MMCR3",	64,	RO, },
346 [752] = { "SIER2",	64,	OS_RW, },
347 [753] = { "SIER3",	64,	OS_RW, },
348 [754] = { "MMCR3",	64,	OS_RW, },
349 };
350 
351 static struct spr sprs[1024];
352 
spr_read_perms(int spr)353 static bool spr_read_perms(int spr)
354 {
355 	if (cpu_has_hv)
356 		return !!(sprs[spr].access & SPR_HV_READ);
357 	else
358 		return !!(sprs[spr].access & SPR_OS_READ);
359 }
360 
spr_write_perms(int spr)361 static bool spr_write_perms(int spr)
362 {
363 	if (cpu_has_hv)
364 		return !!(sprs[spr].access & SPR_HV_WRITE);
365 	else
366 		return !!(sprs[spr].access & SPR_OS_WRITE);
367 }
368 
setup_sprs(void)369 static void setup_sprs(void)
370 {
371 	int i;
372 
373 	for (i = 0; i < 1024; i++) {
374 		if (sprs_common[i].name) {
375 			memcpy(&sprs[i], &sprs_common[i], sizeof(struct spr));
376 		}
377 	}
378 
379 	switch (mfspr(SPR_PVR) & PVR_VERSION_MASK) {
380 	case PVR_VER_970:
381 	case PVR_VER_970FX:
382 	case PVR_VER_970MP:
383 		for (i = 0; i < 1024; i++) {
384 			if (sprs_201[i].name) {
385 				assert(!sprs[i].name);
386 				memcpy(&sprs[i], &sprs_201[i], sizeof(struct spr));
387 			}
388 			if (sprs_970_pmu[i].name) {
389 				assert(!sprs[i].name);
390 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
391 			}
392 		}
393 		break;
394 
395 	case PVR_VER_POWER8E:
396 	case PVR_VER_POWER8NVL:
397 	case PVR_VER_POWER8:
398 		for (i = 0; i < 1024; i++) {
399 			if (sprs_power_common[i].name) {
400 				assert(!sprs[i].name);
401 				memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr));
402 			}
403 			if (sprs_207[i].name) {
404 				assert(!sprs[i].name);
405 				memcpy(&sprs[i], &sprs_207[i], sizeof(struct spr));
406 			}
407 			if (sprs_tm[i].name) {
408 				assert(!sprs[i].name);
409 				memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr));
410 			}
411 			if (sprs_power_common_pmu[i].name) {
412 				assert(!sprs[i].name);
413 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
414 			}
415 		}
416 		break;
417 
418 	case PVR_VER_POWER9:
419 		for (i = 0; i < 1024; i++) {
420 			if (sprs_power_common[i].name) {
421 				assert(!sprs[i].name);
422 				memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr));
423 			}
424 			if (sprs_300[i].name) {
425 				assert(!sprs[i].name);
426 				memcpy(&sprs[i], &sprs_300[i], sizeof(struct spr));
427 			}
428 			if (sprs_tm[i].name) {
429 				assert(!sprs[i].name);
430 				memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr));
431 			}
432 			if (sprs_power9_10[i].name) {
433 				assert(!sprs[i].name);
434 				memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr));
435 			}
436 			if (sprs_power_common_pmu[i].name) {
437 				assert(!sprs[i].name);
438 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
439 			}
440 		}
441 		break;
442 
443 	case PVR_VER_POWER10:
444 		for (i = 0; i < 1024; i++) {
445 			if (sprs_power_common[i].name) {
446 				assert(!sprs[i].name);
447 				memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr));
448 			}
449 			if (sprs_31[i].name) {
450 				assert(!sprs[i].name);
451 				memcpy(&sprs[i], &sprs_31[i], sizeof(struct spr));
452 			}
453 			if (sprs_power9_10[i].name) {
454 				assert(!sprs[i].name);
455 				memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr));
456 			}
457 			if (sprs_power_common_pmu[i].name) {
458 				assert(!sprs[i].name);
459 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
460 			}
461 			if (sprs_power10_pmu[i].name) {
462 				assert(!sprs[i].name);
463 				memcpy(&sprs[i], &sprs_power10_pmu[i], sizeof(struct spr));
464 			}
465 		}
466 		break;
467 
468 	default:
469 		memcpy(sprs, sprs_common, sizeof(sprs));
470 		puts("Warning: Unknown processor version, falling back to common SPRs!\n");
471 		break;
472 	}
473 }
474 
get_sprs(uint64_t * v)475 static void get_sprs(uint64_t *v)
476 {
477 	int i;
478 
479 	for (i = 0; i < 1024; i++) {
480 		if (!spr_read_perms(i))
481 			continue;
482 		v[i] = __mfspr(i);
483 	}
484 }
485 
set_sprs(uint64_t val)486 static void set_sprs(uint64_t val)
487 {
488 	int i;
489 
490 	for (i = 0; i < 1024; i++) {
491 		if (!spr_write_perms(i))
492 			continue;
493 
494 		if (sprs[i].type & SPR_HARNESS)
495 			continue;
496 		__mtspr(i, val);
497 	}
498 }
499 
main(int argc,char ** argv)500 int main(int argc, char **argv)
501 {
502 	int i;
503 	bool pause = false;
504 	uint64_t pat = 0xcafefacec0debabeULL;
505 	const uint64_t patterns[] = {
506 		0xcafefacec0debabeULL, ~0xcafefacec0debabeULL,
507 		0xAAAA5555AAAA5555ULL, 0x5555AAAA5555AAAAULL,
508 		0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL,
509 		-1ULL,
510 	};
511 
512 	for (i = 1; i < argc; i++) {
513 		if (!strcmp(argv[i], "-w")) {
514 			pause = true;
515 		} else if (!strcmp(argv[i], "-p")) {
516 			i += 1;
517 			if (i >= argc || *argv[i] < '0'
518 			    || *argv[i] >= '0' + ARRAY_SIZE(patterns))
519 				report_abort("Error: bad value for -p");
520 			pat ^= patterns[*argv[i] - '0'];
521 		} else if (!strcmp(argv[i], "-t")) {
522 			/* Randomize with timebase register */
523 			asm volatile("mftb %0" : "=r"(i));
524 			pat ^= i;
525 			asm volatile("mftb %0" : "=r"(i));
526 			pat ^= ~(uint64_t)i << 32;
527 		} else {
528 			report_abort("Warning: Unsupported argument: %s",
529 			             argv[i]);
530 		}
531 	}
532 
533 	setup_sprs();
534 
535 	printf("Setting SPRs to 0x%lx...\n", pat);
536 	set_sprs(pat);
537 
538 	memset(before, 0, sizeof(before));
539 	memset(after, 0, sizeof(after));
540 
541 	get_sprs(before);
542 
543 	if (pause) {
544 		migrate_once();
545 		/* Reload regs changed by getchar/putchar hcalls */
546 		before[SPR_SRR0] = mfspr(SPR_SRR0);
547 		before[SPR_SRR1] = mfspr(SPR_SRR1);
548 
549 		/* WORT seems to go to 0 after KVM switch, perhaps CPU idle */
550 		if (sprs[895].name)
551 			before[895] = mfspr(895);
552 	} else {
553 		/*
554 		 * msleep will enable MSR[EE] and take a decrementer
555 		 * interrupt. Must account for changed registers and
556 		 * prevent taking unhandled interrupts.
557 		 */
558 		/* Prevent PMU interrupt */
559 		mtspr(SPR_MMCR0, (mfspr(SPR_MMCR0) | MMCR0_FC) &
560 					~(MMCR0_PMAO | MMCR0_PMAE));
561 		before[SPR_MMCR0] = mfspr(SPR_MMCR0);
562 		before[779] = mfspr(SPR_MMCR0);
563 		msleep(2000);
564 
565 		/* Reload regs changed by dec interrupt */
566 		before[SPR_SRR0] = mfspr(SPR_SRR0);
567 		before[SPR_SRR1] = mfspr(SPR_SRR1);
568 		before[SPR_SPRG1] = mfspr(SPR_SPRG1);
569 
570 		/* WORT seems to go to 0 after KVM switch, perhaps CPU idle */
571 		if (sprs[895].name)
572 			before[895] = mfspr(895);
573 	}
574 
575 	get_sprs(after);
576 
577 	puts("Checking SPRs...\n");
578 	for (i = 0; i < 1024; i++) {
579 		bool pass = true;
580 
581 		if (!spr_read_perms(i))
582 			continue;
583 
584 		if (sprs[i].width == 32) {
585 			if (before[i] >> 32)
586 				pass = false;
587 		}
588 		if (!(sprs[i].type & (SPR_HARNESS|SPR_ASYNC)) && (before[i] != after[i]))
589 			pass = false;
590 
591 		if (sprs[i].width == 32 && !(before[i] >> 32) && !(after[i] >> 32)) {
592 			/* known failure KVM migration of CTRL */
593 			report_kfail(host_is_kvm && i == 136, pass,
594 				"%-10s(%4d):\t        0x%08lx <==>         0x%08lx",
595 				sprs[i].name, i,
596 				before[i], after[i]);
597 		} else {
598 			report(pass, "%-10s(%4d):\t0x%016lx <==> 0x%016lx",
599 				sprs[i].name, i,
600 				before[i], after[i]);
601 		}
602 	}
603 
604 	return report_summary();
605 }
606