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