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, }, /* 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 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 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 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 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 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 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(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