1ee30cf14SThomas Huth /* 2ee30cf14SThomas Huth * Test Special Purpose Registers 3ee30cf14SThomas Huth * 4ee30cf14SThomas Huth * Copyright 2017 Thomas Huth, Red Hat Inc. 5ee30cf14SThomas Huth * 6ee30cf14SThomas Huth * This work is licensed under the terms of the GNU LGPL, version 2. 7ee30cf14SThomas Huth * 8ee30cf14SThomas Huth * The basic idea of this test is to check whether the contents of the Special 9ee30cf14SThomas Huth * Purpose Registers (SPRs) are preserved correctly during migration. So we 10ee30cf14SThomas Huth * fill in the SPRs with a well-known value, read the values back (since not 11ffd9da55SAndrew Jones * all bits might be retained in the SPRs), then wait for migration to complete 12ffd9da55SAndrew Jones * (if the '-w' option has been specified) so that the user has a chance to 13ffd9da55SAndrew Jones * migrate the VM. Alternatively, the test can also simply sleep a little bit 14ffd9da55SAndrew Jones * with the H_CEDE hypercall, in the hope that we'll get scheduled to another 15ffd9da55SAndrew Jones * host CPU and thus register contents might have changed, too (in case of 16ffd9da55SAndrew Jones * bugs). Finally, we read back the values from the SPRs and compare them with 17ffd9da55SAndrew Jones * the values before the migration. Mismatches are reported as test failures. 18ee30cf14SThomas Huth * Note that we do not test all SPRs since some of the registers change their 19ee30cf14SThomas Huth * content automatically, and some are only accessible with hypervisor privi- 20ee30cf14SThomas Huth * leges or have bad side effects, so we have to omit those registers. 21ee30cf14SThomas Huth */ 22ee30cf14SThomas Huth #include <libcflat.h> 23ee30cf14SThomas Huth #include <util.h> 2477a59d17SNico Boehr #include <migrate.h> 25ee30cf14SThomas Huth #include <alloc.h> 26*9c5e1913SNicholas Piggin #include <asm/ppc_asm.h> 27ee30cf14SThomas Huth #include <asm/handlers.h> 28ee30cf14SThomas Huth #include <asm/hcall.h> 29ee30cf14SThomas Huth #include <asm/processor.h> 308b10d4faSNicholas Piggin #include <asm/time.h> 31ee30cf14SThomas Huth #include <asm/barrier.h> 32ee30cf14SThomas Huth 33ee30cf14SThomas Huth uint64_t before[1024], after[1024]; 34ee30cf14SThomas Huth 35ee30cf14SThomas Huth /* Common SPRs for all PowerPC CPUs */ 36ee30cf14SThomas Huth static void set_sprs_common(uint64_t val) 37ee30cf14SThomas Huth { 38ee30cf14SThomas Huth mtspr(9, val); /* CTR */ 39ee30cf14SThomas Huth // mtspr(273, val); /* SPRG1 */ /* Used by our exception handler */ 40ee30cf14SThomas Huth mtspr(274, val); /* SPRG2 */ 41ee30cf14SThomas Huth mtspr(275, val); /* SPRG3 */ 42ee30cf14SThomas Huth } 43ee30cf14SThomas Huth 44ee30cf14SThomas Huth /* SPRs from PowerPC Operating Environment Architecture, Book III, Vers. 2.01 */ 45ee30cf14SThomas Huth static void set_sprs_book3s_201(uint64_t val) 46ee30cf14SThomas Huth { 47ee30cf14SThomas Huth mtspr(18, val); /* DSISR */ 48ee30cf14SThomas Huth mtspr(19, val); /* DAR */ 49ee30cf14SThomas Huth mtspr(152, val); /* CTRL */ 50ee30cf14SThomas Huth mtspr(256, val); /* VRSAVE */ 51ee30cf14SThomas Huth mtspr(786, val); /* MMCRA */ 52ee30cf14SThomas Huth mtspr(795, val); /* MMCR0 */ 53ee30cf14SThomas Huth mtspr(798, val); /* MMCR1 */ 54ee30cf14SThomas Huth } 55ee30cf14SThomas Huth 56ee30cf14SThomas Huth /* SPRs from PowerISA 2.07 Book III-S */ 57ee30cf14SThomas Huth static void set_sprs_book3s_207(uint64_t val) 58ee30cf14SThomas Huth { 59ee30cf14SThomas Huth mtspr(3, val); /* DSCR */ 60ee30cf14SThomas Huth mtspr(13, val); /* AMR */ 61ee30cf14SThomas Huth mtspr(17, val); /* DSCR */ 62ee30cf14SThomas Huth mtspr(18, val); /* DSISR */ 63ee30cf14SThomas Huth mtspr(19, val); /* DAR */ 64ee30cf14SThomas Huth mtspr(29, val); /* AMR */ 65ee30cf14SThomas Huth mtspr(61, val); /* IAMR */ 66ee30cf14SThomas Huth // mtspr(152, val); /* CTRL */ /* TODO: Needs a fix in KVM */ 67ee30cf14SThomas Huth mtspr(153, val); /* FSCR */ 68ee30cf14SThomas Huth mtspr(157, val); /* UAMOR */ 69ee30cf14SThomas Huth mtspr(159, val); /* PSPB */ 70ee30cf14SThomas Huth mtspr(256, val); /* VRSAVE */ 71ee30cf14SThomas Huth // mtspr(272, val); /* SPRG0 */ /* Used by our exception handler */ 72ee30cf14SThomas Huth mtspr(769, val); /* MMCR2 */ 73ee30cf14SThomas Huth mtspr(770, val); /* MMCRA */ 74ee30cf14SThomas Huth mtspr(771, val); /* PMC1 */ 75ee30cf14SThomas Huth mtspr(772, val); /* PMC2 */ 76ee30cf14SThomas Huth mtspr(773, val); /* PMC3 */ 77ee30cf14SThomas Huth mtspr(774, val); /* PMC4 */ 78ee30cf14SThomas Huth mtspr(775, val); /* PMC5 */ 79ee30cf14SThomas Huth mtspr(776, val); /* PMC6 */ 80ee30cf14SThomas Huth mtspr(779, (val & 0xfffffffffbab3fffULL) | 0xfa0b2070); /* MMCR0 */ 81ee30cf14SThomas Huth mtspr(784, val); /* SIER */ 82ee30cf14SThomas Huth mtspr(785, val); /* MMCR2 */ 83ee30cf14SThomas Huth mtspr(786, val); /* MMCRA */ 84ee30cf14SThomas Huth mtspr(787, val); /* PMC1 */ 85ee30cf14SThomas Huth mtspr(788, val); /* PMC2 */ 86ee30cf14SThomas Huth mtspr(789, val); /* PMC3 */ 87ee30cf14SThomas Huth mtspr(790, val); /* PMC4 */ 88ee30cf14SThomas Huth mtspr(791, val); /* PMC5 */ 89ee30cf14SThomas Huth mtspr(792, val); /* PMC6 */ 90ee30cf14SThomas Huth mtspr(795, (val & 0xfffffffffbab3fffULL) | 0xfa0b2070); /* MMCR0 */ 91ee30cf14SThomas Huth mtspr(796, val); /* SIAR */ 92ee30cf14SThomas Huth mtspr(797, val); /* SDAR */ 93ee30cf14SThomas Huth mtspr(798, val); /* MMCR1 */ 94ee30cf14SThomas Huth mtspr(800, val); /* BESCRS */ 95ee30cf14SThomas Huth mtspr(801, val); /* BESCCRSU */ 96ee30cf14SThomas Huth mtspr(802, val); /* BESCRR */ 97ee30cf14SThomas Huth mtspr(803, val); /* BESCRRU */ 98ee30cf14SThomas Huth mtspr(804, val); /* EBBHR */ 99ee30cf14SThomas Huth mtspr(805, val); /* EBBRR */ 100ee30cf14SThomas Huth mtspr(806, val); /* BESCR */ 101ee30cf14SThomas Huth mtspr(815, val); /* TAR */ 102ee30cf14SThomas Huth } 103ee30cf14SThomas Huth 10425a302cbSThomas Huth /* SPRs from PowerISA 3.00 Book III */ 10525a302cbSThomas Huth static void set_sprs_book3s_300(uint64_t val) 10625a302cbSThomas Huth { 10725a302cbSThomas Huth set_sprs_book3s_207(val); 10825a302cbSThomas Huth mtspr(48, val); /* PIDR */ 10925a302cbSThomas Huth mtspr(144, val); /* TIDR */ 11025a302cbSThomas Huth mtspr(823, val); /* PSSCR */ 11125a302cbSThomas Huth } 11225a302cbSThomas Huth 113faaddcb0SNicholas Piggin /* SPRs from Power ISA Version 3.1B */ 114faaddcb0SNicholas Piggin static void set_sprs_book3s_31(uint64_t val) 115faaddcb0SNicholas Piggin { 116faaddcb0SNicholas Piggin set_sprs_book3s_207(val); 117faaddcb0SNicholas Piggin mtspr(48, val); /* PIDR */ 118faaddcb0SNicholas Piggin /* 3.1 removes TIDR */ 119faaddcb0SNicholas Piggin mtspr(823, val); /* PSSCR */ 120faaddcb0SNicholas Piggin } 121faaddcb0SNicholas Piggin 122ee30cf14SThomas Huth static void set_sprs(uint64_t val) 123ee30cf14SThomas Huth { 124ee30cf14SThomas Huth set_sprs_common(val); 125ee30cf14SThomas Huth 126*9c5e1913SNicholas Piggin switch (mfspr(SPR_PVR) & PVR_VERSION_MASK) { 127*9c5e1913SNicholas Piggin case PVR_VER_970: 128*9c5e1913SNicholas Piggin case PVR_VER_970FX: 129*9c5e1913SNicholas Piggin case PVR_VER_970MP: 130ee30cf14SThomas Huth set_sprs_book3s_201(val); 131ee30cf14SThomas Huth break; 132*9c5e1913SNicholas Piggin case PVR_VER_POWER8E: 133*9c5e1913SNicholas Piggin case PVR_VER_POWER8NVL: 134*9c5e1913SNicholas Piggin case PVR_VER_POWER8: 135ee30cf14SThomas Huth set_sprs_book3s_207(val); 136ee30cf14SThomas Huth break; 137*9c5e1913SNicholas Piggin case PVR_VER_POWER9: 13825a302cbSThomas Huth set_sprs_book3s_300(val); 13925a302cbSThomas Huth break; 140*9c5e1913SNicholas Piggin case PVR_VER_POWER10: 141faaddcb0SNicholas Piggin set_sprs_book3s_31(val); 142faaddcb0SNicholas Piggin break; 143ee30cf14SThomas Huth default: 144ee30cf14SThomas Huth puts("Warning: Unknown processor version!\n"); 145ee30cf14SThomas Huth } 146ee30cf14SThomas Huth } 147ee30cf14SThomas Huth 148ee30cf14SThomas Huth static void get_sprs_common(uint64_t *v) 149ee30cf14SThomas Huth { 150ee30cf14SThomas Huth v[9] = mfspr(9); /* CTR */ 151ee30cf14SThomas Huth // v[273] = mfspr(273); /* SPRG1 */ /* Used by our exception handler */ 152ee30cf14SThomas Huth v[274] = mfspr(274); /* SPRG2 */ 153ee30cf14SThomas Huth v[275] = mfspr(275); /* SPRG3 */ 154ee30cf14SThomas Huth } 155ee30cf14SThomas Huth 156ee30cf14SThomas Huth static void get_sprs_book3s_201(uint64_t *v) 157ee30cf14SThomas Huth { 158ee30cf14SThomas Huth v[18] = mfspr(18); /* DSISR */ 159ee30cf14SThomas Huth v[19] = mfspr(19); /* DAR */ 160ee30cf14SThomas Huth v[136] = mfspr(136); /* CTRL */ 161ee30cf14SThomas Huth v[256] = mfspr(256); /* VRSAVE */ 162ee30cf14SThomas Huth v[786] = mfspr(786); /* MMCRA */ 163ee30cf14SThomas Huth v[795] = mfspr(795); /* MMCR0 */ 164ee30cf14SThomas Huth v[798] = mfspr(798); /* MMCR1 */ 165ee30cf14SThomas Huth } 166ee30cf14SThomas Huth 167ee30cf14SThomas Huth static void get_sprs_book3s_207(uint64_t *v) 168ee30cf14SThomas Huth { 169ee30cf14SThomas Huth v[3] = mfspr(3); /* DSCR */ 170ee30cf14SThomas Huth v[13] = mfspr(13); /* AMR */ 171ee30cf14SThomas Huth v[17] = mfspr(17); /* DSCR */ 172ee30cf14SThomas Huth v[18] = mfspr(18); /* DSISR */ 173ee30cf14SThomas Huth v[19] = mfspr(19); /* DAR */ 174ee30cf14SThomas Huth v[29] = mfspr(29); /* AMR */ 175ee30cf14SThomas Huth v[61] = mfspr(61); /* IAMR */ 176ee30cf14SThomas Huth // v[136] = mfspr(136); /* CTRL */ /* TODO: Needs a fix in KVM */ 177ee30cf14SThomas Huth v[153] = mfspr(153); /* FSCR */ 178ee30cf14SThomas Huth v[157] = mfspr(157); /* UAMOR */ 179ee30cf14SThomas Huth v[159] = mfspr(159); /* PSPB */ 180ee30cf14SThomas Huth v[256] = mfspr(256); /* VRSAVE */ 181ee30cf14SThomas Huth v[259] = mfspr(259); /* SPRG3 (read only) */ 182ee30cf14SThomas Huth // v[272] = mfspr(272); /* SPRG0 */ /* Used by our exception handler */ 183ee30cf14SThomas Huth v[769] = mfspr(769); /* MMCR2 */ 184ee30cf14SThomas Huth v[770] = mfspr(770); /* MMCRA */ 185ee30cf14SThomas Huth v[771] = mfspr(771); /* PMC1 */ 186ee30cf14SThomas Huth v[772] = mfspr(772); /* PMC2 */ 187ee30cf14SThomas Huth v[773] = mfspr(773); /* PMC3 */ 188ee30cf14SThomas Huth v[774] = mfspr(774); /* PMC4 */ 189ee30cf14SThomas Huth v[775] = mfspr(775); /* PMC5 */ 190ee30cf14SThomas Huth v[776] = mfspr(776); /* PMC6 */ 191ee30cf14SThomas Huth v[779] = mfspr(779); /* MMCR0 */ 192ee30cf14SThomas Huth v[780] = mfspr(780); /* SIAR (read only) */ 193ee30cf14SThomas Huth v[781] = mfspr(781); /* SDAR (read only) */ 194ee30cf14SThomas Huth v[782] = mfspr(782); /* MMCR1 (read only) */ 195ee30cf14SThomas Huth v[784] = mfspr(784); /* SIER */ 196ee30cf14SThomas Huth v[785] = mfspr(785); /* MMCR2 */ 197ee30cf14SThomas Huth v[786] = mfspr(786); /* MMCRA */ 198ee30cf14SThomas Huth v[787] = mfspr(787); /* PMC1 */ 199ee30cf14SThomas Huth v[788] = mfspr(788); /* PMC2 */ 200ee30cf14SThomas Huth v[789] = mfspr(789); /* PMC3 */ 201ee30cf14SThomas Huth v[790] = mfspr(790); /* PMC4 */ 202ee30cf14SThomas Huth v[791] = mfspr(791); /* PMC5 */ 203ee30cf14SThomas Huth v[792] = mfspr(792); /* PMC6 */ 204ee30cf14SThomas Huth v[795] = mfspr(795); /* MMCR0 */ 205ee30cf14SThomas Huth v[796] = mfspr(796); /* SIAR */ 206ee30cf14SThomas Huth v[797] = mfspr(797); /* SDAR */ 207ee30cf14SThomas Huth v[798] = mfspr(798); /* MMCR1 */ 208ee30cf14SThomas Huth v[800] = mfspr(800); /* BESCRS */ 209ee30cf14SThomas Huth v[801] = mfspr(801); /* BESCCRSU */ 210ee30cf14SThomas Huth v[802] = mfspr(802); /* BESCRR */ 211ee30cf14SThomas Huth v[803] = mfspr(803); /* BESCRRU */ 212ee30cf14SThomas Huth v[804] = mfspr(804); /* EBBHR */ 213ee30cf14SThomas Huth v[805] = mfspr(805); /* EBBRR */ 214ee30cf14SThomas Huth v[806] = mfspr(806); /* BESCR */ 215ee30cf14SThomas Huth v[815] = mfspr(815); /* TAR */ 216ee30cf14SThomas Huth } 217ee30cf14SThomas Huth 21825a302cbSThomas Huth static void get_sprs_book3s_300(uint64_t *v) 21925a302cbSThomas Huth { 22025a302cbSThomas Huth get_sprs_book3s_207(v); 22125a302cbSThomas Huth v[48] = mfspr(48); /* PIDR */ 22225a302cbSThomas Huth v[144] = mfspr(144); /* TIDR */ 22325a302cbSThomas Huth v[823] = mfspr(823); /* PSSCR */ 22425a302cbSThomas Huth } 22525a302cbSThomas Huth 226faaddcb0SNicholas Piggin static void get_sprs_book3s_31(uint64_t *v) 227faaddcb0SNicholas Piggin { 228faaddcb0SNicholas Piggin get_sprs_book3s_207(v); 229faaddcb0SNicholas Piggin v[48] = mfspr(48); /* PIDR */ 230faaddcb0SNicholas Piggin v[823] = mfspr(823); /* PSSCR */ 231faaddcb0SNicholas Piggin } 232faaddcb0SNicholas Piggin 233ee30cf14SThomas Huth static void get_sprs(uint64_t *v) 234ee30cf14SThomas Huth { 235ee30cf14SThomas Huth uint32_t pvr = mfspr(287); /* Processor Version Register */ 236ee30cf14SThomas Huth 237ee30cf14SThomas Huth get_sprs_common(v); 238ee30cf14SThomas Huth 239ee30cf14SThomas Huth switch (pvr >> 16) { 240ee30cf14SThomas Huth case 0x39: /* PPC970 */ 241ee30cf14SThomas Huth case 0x3C: /* PPC970FX */ 242ee30cf14SThomas Huth case 0x44: /* PPC970MP */ 243ee30cf14SThomas Huth get_sprs_book3s_201(v); 244ee30cf14SThomas Huth break; 245ee30cf14SThomas Huth case 0x4b: /* POWER8E */ 246ee30cf14SThomas Huth case 0x4c: /* POWER8NVL */ 247ee30cf14SThomas Huth case 0x4d: /* POWER8 */ 248ee30cf14SThomas Huth get_sprs_book3s_207(v); 249ee30cf14SThomas Huth break; 25025a302cbSThomas Huth case 0x4e: /* POWER9 */ 25125a302cbSThomas Huth get_sprs_book3s_300(v); 25225a302cbSThomas Huth break; 253faaddcb0SNicholas Piggin case 0x80: /* POWER10 */ 254faaddcb0SNicholas Piggin get_sprs_book3s_31(v); 255faaddcb0SNicholas Piggin break; 256ee30cf14SThomas Huth } 257ee30cf14SThomas Huth } 258ee30cf14SThomas Huth 259ee30cf14SThomas Huth int main(int argc, char **argv) 260ee30cf14SThomas Huth { 261ee30cf14SThomas Huth int i; 262ee30cf14SThomas Huth bool pause = false; 263ee30cf14SThomas Huth uint64_t pat = 0xcafefacec0debabeULL; 264ee30cf14SThomas Huth const uint64_t patterns[] = { 265ee30cf14SThomas Huth 0xcafefacec0debabeULL, ~0xcafefacec0debabeULL, 266ee30cf14SThomas Huth 0xAAAA5555AAAA5555ULL, 0x5555AAAA5555AAAAULL, 267ee30cf14SThomas Huth 0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL, 268ee30cf14SThomas Huth -1ULL, 269ee30cf14SThomas Huth }; 270ee30cf14SThomas Huth 271ee30cf14SThomas Huth for (i = 1; i < argc; i++) { 272ee30cf14SThomas Huth if (!strcmp(argv[i], "-w")) { 273ee30cf14SThomas Huth pause = true; 274ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-p")) { 275ee30cf14SThomas Huth i += 1; 276ee30cf14SThomas Huth if (i >= argc || *argv[i] < '0' 277ee30cf14SThomas Huth || *argv[i] >= '0' + ARRAY_SIZE(patterns)) 278ee30cf14SThomas Huth report_abort("Error: bad value for -p"); 279ee30cf14SThomas Huth pat ^= patterns[*argv[i] - '0']; 280ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-t")) { 281ee30cf14SThomas Huth /* Randomize with timebase register */ 282ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 283ee30cf14SThomas Huth pat ^= i; 284ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 285ee30cf14SThomas Huth pat ^= ~(uint64_t)i << 32; 286ee30cf14SThomas Huth } else { 287ee30cf14SThomas Huth report_abort("Warning: Unsupported argument: %s", 288ee30cf14SThomas Huth argv[i]); 289ee30cf14SThomas Huth } 290ee30cf14SThomas Huth } 291ee30cf14SThomas Huth 292fd6aada0SRadim Krčmář printf("Settings SPRs to %#lx...\n", pat); 293ee30cf14SThomas Huth set_sprs(pat); 294ee30cf14SThomas Huth 295ee30cf14SThomas Huth memset(before, 0, sizeof(before)); 296ee30cf14SThomas Huth memset(after, 0, sizeof(after)); 297ee30cf14SThomas Huth 298ee30cf14SThomas Huth get_sprs(before); 299ee30cf14SThomas Huth 300ee30cf14SThomas Huth if (pause) { 30177a59d17SNico Boehr migrate_once(); 302ee30cf14SThomas Huth } else { 303ba33a96fSNicholas Piggin msleep(2000); 304ee30cf14SThomas Huth } 305ee30cf14SThomas Huth 306ee30cf14SThomas Huth get_sprs(after); 307ee30cf14SThomas Huth 308ee30cf14SThomas Huth puts("Checking SPRs...\n"); 309ee30cf14SThomas Huth for (i = 0; i < 1024; i++) { 310ee30cf14SThomas Huth if (before[i] != 0 || after[i] != 0) 311a299895bSThomas Huth report(before[i] == after[i], 312a299895bSThomas Huth "SPR %d:\t%#018lx <==> %#018lx", i, before[i], 313a299895bSThomas Huth after[i]); 314ee30cf14SThomas Huth } 315ee30cf14SThomas Huth 316ee30cf14SThomas Huth return report_summary(); 317ee30cf14SThomas Huth } 318