xref: /kvm-unit-tests/powerpc/sprs.c (revision ccb37496f132d93e748c2a146d48835b7160a0cc)
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 */
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 
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, },
203 [285] = { "TBU",	32,	HV_WO, },
204 [286] = { "TBU40",	64,	HV_WO, },
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, },
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, },
232 [898] = { "PPR32",	32,	RW, },
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, },
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 
353 static void setup_sprs(void)
354 {
355 	int i;
356 
357 	for (i = 0; i < 1024; i++) {
358 		if (sprs_common[i].name) {
359 			memcpy(&sprs[i], &sprs_common[i], sizeof(struct spr));
360 		}
361 	}
362 
363 	switch (mfspr(SPR_PVR) & PVR_VERSION_MASK) {
364 	case PVR_VER_970:
365 	case PVR_VER_970FX:
366 	case PVR_VER_970MP:
367 		for (i = 0; i < 1024; i++) {
368 			if (sprs_201[i].name) {
369 				assert(!sprs[i].name);
370 				memcpy(&sprs[i], &sprs_201[i], sizeof(struct spr));
371 			}
372 			if (sprs_970_pmu[i].name) {
373 				assert(!sprs[i].name);
374 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
375 			}
376 		}
377 		break;
378 
379 	case PVR_VER_POWER8E:
380 	case PVR_VER_POWER8NVL:
381 	case PVR_VER_POWER8:
382 		for (i = 0; i < 1024; i++) {
383 			if (sprs_power_common[i].name) {
384 				assert(!sprs[i].name);
385 				memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr));
386 			}
387 			if (sprs_207[i].name) {
388 				assert(!sprs[i].name);
389 				memcpy(&sprs[i], &sprs_207[i], sizeof(struct spr));
390 			}
391 			if (sprs_tm[i].name) {
392 				assert(!sprs[i].name);
393 				memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr));
394 			}
395 			if (sprs_power_common_pmu[i].name) {
396 				assert(!sprs[i].name);
397 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
398 			}
399 		}
400 		break;
401 
402 	case PVR_VER_POWER9:
403 		for (i = 0; i < 1024; i++) {
404 			if (sprs_power_common[i].name) {
405 				assert(!sprs[i].name);
406 				memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr));
407 			}
408 			if (sprs_300[i].name) {
409 				assert(!sprs[i].name);
410 				memcpy(&sprs[i], &sprs_300[i], sizeof(struct spr));
411 			}
412 			if (sprs_tm[i].name) {
413 				assert(!sprs[i].name);
414 				memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr));
415 			}
416 			if (sprs_power9_10[i].name) {
417 				assert(!sprs[i].name);
418 				memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr));
419 			}
420 			if (sprs_power_common_pmu[i].name) {
421 				assert(!sprs[i].name);
422 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
423 			}
424 		}
425 		break;
426 
427 	case PVR_VER_POWER10:
428 		for (i = 0; i < 1024; i++) {
429 			if (sprs_power_common[i].name) {
430 				assert(!sprs[i].name);
431 				memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr));
432 			}
433 			if (sprs_31[i].name) {
434 				assert(!sprs[i].name);
435 				memcpy(&sprs[i], &sprs_31[i], sizeof(struct spr));
436 			}
437 			if (sprs_power9_10[i].name) {
438 				assert(!sprs[i].name);
439 				memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr));
440 			}
441 			if (sprs_power_common_pmu[i].name) {
442 				assert(!sprs[i].name);
443 				memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr));
444 			}
445 			if (sprs_power10_pmu[i].name) {
446 				assert(!sprs[i].name);
447 				memcpy(&sprs[i], &sprs_power10_pmu[i], sizeof(struct spr));
448 			}
449 		}
450 		break;
451 
452 	default:
453 		memcpy(sprs, sprs_common, sizeof(sprs));
454 		puts("Warning: Unknown processor version, falling back to common SPRs!\n");
455 		break;
456 	}
457 }
458 
459 static void get_sprs(uint64_t *v)
460 {
461 	int i;
462 
463 	for (i = 0; i < 1024; i++) {
464 		if (!(sprs[i].access & SPR_OS_READ))
465 			continue;
466 		v[i] = __mfspr(i);
467 	}
468 }
469 
470 static void set_sprs(uint64_t val)
471 {
472 	int i;
473 
474 	for (i = 0; i < 1024; i++) {
475 		if (!(sprs[i].access & SPR_OS_WRITE))
476 			continue;
477 		if (sprs[i].type & SPR_HARNESS)
478 			continue;
479 		__mtspr(i, val);
480 	}
481 }
482 
483 int main(int argc, char **argv)
484 {
485 	int i;
486 	bool pause = false;
487 	uint64_t pat = 0xcafefacec0debabeULL;
488 	const uint64_t patterns[] = {
489 		0xcafefacec0debabeULL, ~0xcafefacec0debabeULL,
490 		0xAAAA5555AAAA5555ULL, 0x5555AAAA5555AAAAULL,
491 		0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL,
492 		-1ULL,
493 	};
494 
495 	for (i = 1; i < argc; i++) {
496 		if (!strcmp(argv[i], "-w")) {
497 			pause = true;
498 		} else if (!strcmp(argv[i], "-p")) {
499 			i += 1;
500 			if (i >= argc || *argv[i] < '0'
501 			    || *argv[i] >= '0' + ARRAY_SIZE(patterns))
502 				report_abort("Error: bad value for -p");
503 			pat ^= patterns[*argv[i] - '0'];
504 		} else if (!strcmp(argv[i], "-t")) {
505 			/* Randomize with timebase register */
506 			asm volatile("mftb %0" : "=r"(i));
507 			pat ^= i;
508 			asm volatile("mftb %0" : "=r"(i));
509 			pat ^= ~(uint64_t)i << 32;
510 		} else {
511 			report_abort("Warning: Unsupported argument: %s",
512 			             argv[i]);
513 		}
514 	}
515 
516 	setup_sprs();
517 
518 	printf("Setting SPRs to 0x%lx...\n", pat);
519 	set_sprs(pat);
520 
521 	memset(before, 0, sizeof(before));
522 	memset(after, 0, sizeof(after));
523 
524 	get_sprs(before);
525 
526 	if (pause) {
527 		migrate_once();
528 		/* Reload regs changed by getchar/putchar hcalls */
529 		before[SPR_SRR0] = mfspr(SPR_SRR0);
530 		before[SPR_SRR1] = mfspr(SPR_SRR1);
531 
532 		/* WORT seems to go to 0 after KVM switch, perhaps CPU idle */
533 		if (sprs[895].name)
534 			before[895] = mfspr(895);
535 	} else {
536 		/*
537 		 * msleep will enable MSR[EE] and take a decrementer
538 		 * interrupt. Must account for changed registers and
539 		 * prevent taking unhandled interrupts.
540 		 */
541 		/* Prevent PMU interrupt */
542 		mtspr(SPR_MMCR0, (mfspr(SPR_MMCR0) | MMCR0_FC) &
543 					~(MMCR0_PMAO | MMCR0_PMAE));
544 		before[SPR_MMCR0] = mfspr(SPR_MMCR0);
545 		before[779] = mfspr(SPR_MMCR0);
546 		msleep(2000);
547 
548 		/* Reload regs changed by dec interrupt */
549 		before[SPR_SRR0] = mfspr(SPR_SRR0);
550 		before[SPR_SRR1] = mfspr(SPR_SRR1);
551 		before[SPR_SPRG1] = mfspr(SPR_SPRG1);
552 
553 		/* WORT seems to go to 0 after KVM switch, perhaps CPU idle */
554 		if (sprs[895].name)
555 			before[895] = mfspr(895);
556 	}
557 
558 	get_sprs(after);
559 
560 	puts("Checking SPRs...\n");
561 	for (i = 0; i < 1024; i++) {
562 		bool pass = true;
563 
564 		if (!(sprs[i].access & SPR_OS_READ))
565 			continue;
566 
567 		if (sprs[i].width == 32) {
568 			if (before[i] >> 32)
569 				pass = false;
570 		}
571 		if (!(sprs[i].type & (SPR_HARNESS|SPR_ASYNC)) && (before[i] != after[i]))
572 			pass = false;
573 
574 		if (sprs[i].width == 32 && !(before[i] >> 32) && !(after[i] >> 32)) {
575 			/* known failure KVM migration of CTRL */
576 			report_kfail(true && i == 136,
577 				"%-10s(%4d):\t        0x%08lx <==>         0x%08lx",
578 				sprs[i].name, i,
579 				before[i], after[i]);
580 		} else {
581 			report(pass, "%-10s(%4d):\t0x%016lx <==> 0x%016lx",
582 				sprs[i].name, i,
583 				before[i], after[i]);
584 		}
585 	}
586 
587 	return report_summary();
588 }
589