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