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/handlers.h> 27 #include <asm/hcall.h> 28 #include <asm/processor.h> 29 #include <asm/time.h> 30 #include <asm/barrier.h> 31 32 uint64_t before[1024], after[1024]; 33 34 /* Common SPRs for all PowerPC CPUs */ 35 static void set_sprs_common(uint64_t val) 36 { 37 mtspr(9, val); /* CTR */ 38 // mtspr(273, val); /* SPRG1 */ /* Used by our exception handler */ 39 mtspr(274, val); /* SPRG2 */ 40 mtspr(275, val); /* SPRG3 */ 41 } 42 43 /* SPRs from PowerPC Operating Environment Architecture, Book III, Vers. 2.01 */ 44 static void set_sprs_book3s_201(uint64_t val) 45 { 46 mtspr(18, val); /* DSISR */ 47 mtspr(19, val); /* DAR */ 48 mtspr(152, val); /* CTRL */ 49 mtspr(256, val); /* VRSAVE */ 50 mtspr(786, val); /* MMCRA */ 51 mtspr(795, val); /* MMCR0 */ 52 mtspr(798, val); /* MMCR1 */ 53 } 54 55 /* SPRs from PowerISA 2.07 Book III-S */ 56 static void set_sprs_book3s_207(uint64_t val) 57 { 58 mtspr(3, val); /* DSCR */ 59 mtspr(13, val); /* AMR */ 60 mtspr(17, val); /* DSCR */ 61 mtspr(18, val); /* DSISR */ 62 mtspr(19, val); /* DAR */ 63 mtspr(29, val); /* AMR */ 64 mtspr(61, val); /* IAMR */ 65 // mtspr(152, val); /* CTRL */ /* TODO: Needs a fix in KVM */ 66 mtspr(153, val); /* FSCR */ 67 mtspr(157, val); /* UAMOR */ 68 mtspr(159, val); /* PSPB */ 69 mtspr(256, val); /* VRSAVE */ 70 // mtspr(272, val); /* SPRG0 */ /* Used by our exception handler */ 71 mtspr(769, val); /* MMCR2 */ 72 mtspr(770, val); /* MMCRA */ 73 mtspr(771, val); /* PMC1 */ 74 mtspr(772, val); /* PMC2 */ 75 mtspr(773, val); /* PMC3 */ 76 mtspr(774, val); /* PMC4 */ 77 mtspr(775, val); /* PMC5 */ 78 mtspr(776, val); /* PMC6 */ 79 mtspr(779, (val & 0xfffffffffbab3fffULL) | 0xfa0b2070); /* MMCR0 */ 80 mtspr(784, val); /* SIER */ 81 mtspr(785, val); /* MMCR2 */ 82 mtspr(786, val); /* MMCRA */ 83 mtspr(787, val); /* PMC1 */ 84 mtspr(788, val); /* PMC2 */ 85 mtspr(789, val); /* PMC3 */ 86 mtspr(790, val); /* PMC4 */ 87 mtspr(791, val); /* PMC5 */ 88 mtspr(792, val); /* PMC6 */ 89 mtspr(795, (val & 0xfffffffffbab3fffULL) | 0xfa0b2070); /* MMCR0 */ 90 mtspr(796, val); /* SIAR */ 91 mtspr(797, val); /* SDAR */ 92 mtspr(798, val); /* MMCR1 */ 93 mtspr(800, val); /* BESCRS */ 94 mtspr(801, val); /* BESCCRSU */ 95 mtspr(802, val); /* BESCRR */ 96 mtspr(803, val); /* BESCRRU */ 97 mtspr(804, val); /* EBBHR */ 98 mtspr(805, val); /* EBBRR */ 99 mtspr(806, val); /* BESCR */ 100 mtspr(815, val); /* TAR */ 101 } 102 103 /* SPRs from PowerISA 3.00 Book III */ 104 static void set_sprs_book3s_300(uint64_t val) 105 { 106 set_sprs_book3s_207(val); 107 mtspr(48, val); /* PIDR */ 108 mtspr(144, val); /* TIDR */ 109 mtspr(823, val); /* PSSCR */ 110 } 111 112 /* SPRs from Power ISA Version 3.1B */ 113 static void set_sprs_book3s_31(uint64_t val) 114 { 115 set_sprs_book3s_207(val); 116 mtspr(48, val); /* PIDR */ 117 /* 3.1 removes TIDR */ 118 mtspr(823, val); /* PSSCR */ 119 } 120 121 static void set_sprs(uint64_t val) 122 { 123 uint32_t pvr = mfspr(287); /* Processor Version Register */ 124 125 set_sprs_common(val); 126 127 switch (pvr >> 16) { 128 case 0x39: /* PPC970 */ 129 case 0x3C: /* PPC970FX */ 130 case 0x44: /* PPC970MP */ 131 set_sprs_book3s_201(val); 132 break; 133 case 0x4b: /* POWER8E */ 134 case 0x4c: /* POWER8NVL */ 135 case 0x4d: /* POWER8 */ 136 set_sprs_book3s_207(val); 137 break; 138 case 0x4e: /* POWER9 */ 139 set_sprs_book3s_300(val); 140 break; 141 case 0x80: /* POWER10 */ 142 set_sprs_book3s_31(val); 143 break; 144 default: 145 puts("Warning: Unknown processor version!\n"); 146 } 147 } 148 149 static void get_sprs_common(uint64_t *v) 150 { 151 v[9] = mfspr(9); /* CTR */ 152 // v[273] = mfspr(273); /* SPRG1 */ /* Used by our exception handler */ 153 v[274] = mfspr(274); /* SPRG2 */ 154 v[275] = mfspr(275); /* SPRG3 */ 155 } 156 157 static void get_sprs_book3s_201(uint64_t *v) 158 { 159 v[18] = mfspr(18); /* DSISR */ 160 v[19] = mfspr(19); /* DAR */ 161 v[136] = mfspr(136); /* CTRL */ 162 v[256] = mfspr(256); /* VRSAVE */ 163 v[786] = mfspr(786); /* MMCRA */ 164 v[795] = mfspr(795); /* MMCR0 */ 165 v[798] = mfspr(798); /* MMCR1 */ 166 } 167 168 static void get_sprs_book3s_207(uint64_t *v) 169 { 170 v[3] = mfspr(3); /* DSCR */ 171 v[13] = mfspr(13); /* AMR */ 172 v[17] = mfspr(17); /* DSCR */ 173 v[18] = mfspr(18); /* DSISR */ 174 v[19] = mfspr(19); /* DAR */ 175 v[29] = mfspr(29); /* AMR */ 176 v[61] = mfspr(61); /* IAMR */ 177 // v[136] = mfspr(136); /* CTRL */ /* TODO: Needs a fix in KVM */ 178 v[153] = mfspr(153); /* FSCR */ 179 v[157] = mfspr(157); /* UAMOR */ 180 v[159] = mfspr(159); /* PSPB */ 181 v[256] = mfspr(256); /* VRSAVE */ 182 v[259] = mfspr(259); /* SPRG3 (read only) */ 183 // v[272] = mfspr(272); /* SPRG0 */ /* Used by our exception handler */ 184 v[769] = mfspr(769); /* MMCR2 */ 185 v[770] = mfspr(770); /* MMCRA */ 186 v[771] = mfspr(771); /* PMC1 */ 187 v[772] = mfspr(772); /* PMC2 */ 188 v[773] = mfspr(773); /* PMC3 */ 189 v[774] = mfspr(774); /* PMC4 */ 190 v[775] = mfspr(775); /* PMC5 */ 191 v[776] = mfspr(776); /* PMC6 */ 192 v[779] = mfspr(779); /* MMCR0 */ 193 v[780] = mfspr(780); /* SIAR (read only) */ 194 v[781] = mfspr(781); /* SDAR (read only) */ 195 v[782] = mfspr(782); /* MMCR1 (read only) */ 196 v[784] = mfspr(784); /* SIER */ 197 v[785] = mfspr(785); /* MMCR2 */ 198 v[786] = mfspr(786); /* MMCRA */ 199 v[787] = mfspr(787); /* PMC1 */ 200 v[788] = mfspr(788); /* PMC2 */ 201 v[789] = mfspr(789); /* PMC3 */ 202 v[790] = mfspr(790); /* PMC4 */ 203 v[791] = mfspr(791); /* PMC5 */ 204 v[792] = mfspr(792); /* PMC6 */ 205 v[795] = mfspr(795); /* MMCR0 */ 206 v[796] = mfspr(796); /* SIAR */ 207 v[797] = mfspr(797); /* SDAR */ 208 v[798] = mfspr(798); /* MMCR1 */ 209 v[800] = mfspr(800); /* BESCRS */ 210 v[801] = mfspr(801); /* BESCCRSU */ 211 v[802] = mfspr(802); /* BESCRR */ 212 v[803] = mfspr(803); /* BESCRRU */ 213 v[804] = mfspr(804); /* EBBHR */ 214 v[805] = mfspr(805); /* EBBRR */ 215 v[806] = mfspr(806); /* BESCR */ 216 v[815] = mfspr(815); /* TAR */ 217 } 218 219 static void get_sprs_book3s_300(uint64_t *v) 220 { 221 get_sprs_book3s_207(v); 222 v[48] = mfspr(48); /* PIDR */ 223 v[144] = mfspr(144); /* TIDR */ 224 v[823] = mfspr(823); /* PSSCR */ 225 } 226 227 static void get_sprs_book3s_31(uint64_t *v) 228 { 229 get_sprs_book3s_207(v); 230 v[48] = mfspr(48); /* PIDR */ 231 v[823] = mfspr(823); /* PSSCR */ 232 } 233 234 static void get_sprs(uint64_t *v) 235 { 236 uint32_t pvr = mfspr(287); /* Processor Version Register */ 237 238 get_sprs_common(v); 239 240 switch (pvr >> 16) { 241 case 0x39: /* PPC970 */ 242 case 0x3C: /* PPC970FX */ 243 case 0x44: /* PPC970MP */ 244 get_sprs_book3s_201(v); 245 break; 246 case 0x4b: /* POWER8E */ 247 case 0x4c: /* POWER8NVL */ 248 case 0x4d: /* POWER8 */ 249 get_sprs_book3s_207(v); 250 break; 251 case 0x4e: /* POWER9 */ 252 get_sprs_book3s_300(v); 253 break; 254 case 0x80: /* POWER10 */ 255 get_sprs_book3s_31(v); 256 break; 257 } 258 } 259 260 int main(int argc, char **argv) 261 { 262 int i; 263 bool pause = false; 264 uint64_t pat = 0xcafefacec0debabeULL; 265 const uint64_t patterns[] = { 266 0xcafefacec0debabeULL, ~0xcafefacec0debabeULL, 267 0xAAAA5555AAAA5555ULL, 0x5555AAAA5555AAAAULL, 268 0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL, 269 -1ULL, 270 }; 271 272 for (i = 1; i < argc; i++) { 273 if (!strcmp(argv[i], "-w")) { 274 pause = true; 275 } else if (!strcmp(argv[i], "-p")) { 276 i += 1; 277 if (i >= argc || *argv[i] < '0' 278 || *argv[i] >= '0' + ARRAY_SIZE(patterns)) 279 report_abort("Error: bad value for -p"); 280 pat ^= patterns[*argv[i] - '0']; 281 } else if (!strcmp(argv[i], "-t")) { 282 /* Randomize with timebase register */ 283 asm volatile("mftb %0" : "=r"(i)); 284 pat ^= i; 285 asm volatile("mftb %0" : "=r"(i)); 286 pat ^= ~(uint64_t)i << 32; 287 } else { 288 report_abort("Warning: Unsupported argument: %s", 289 argv[i]); 290 } 291 } 292 293 printf("Settings SPRs to %#lx...\n", pat); 294 set_sprs(pat); 295 296 memset(before, 0, sizeof(before)); 297 memset(after, 0, sizeof(after)); 298 299 get_sprs(before); 300 301 if (pause) { 302 migrate_once(); 303 } else { 304 msleep(2000); 305 } 306 307 get_sprs(after); 308 309 puts("Checking SPRs...\n"); 310 for (i = 0; i < 1024; i++) { 311 if (before[i] != 0 || after[i] != 0) 312 report(before[i] == after[i], 313 "SPR %d:\t%#018lx <==> %#018lx", i, before[i], 314 after[i]); 315 } 316 317 return report_summary(); 318 } 319