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> 269c5e1913SNicholas 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 33*8f6290f0SNicholas Piggin /* "Indirect" mfspr/mtspr which accept a non-constant spr number */ 34*8f6290f0SNicholas Piggin static uint64_t __mfspr(unsigned spr) 35ee30cf14SThomas Huth { 36*8f6290f0SNicholas Piggin uint64_t tmp; 37*8f6290f0SNicholas Piggin uint64_t ret; 38*8f6290f0SNicholas Piggin 39*8f6290f0SNicholas Piggin asm volatile( 40*8f6290f0SNicholas Piggin " bcl 20, 31, 1f \n" 41*8f6290f0SNicholas Piggin "1: mflr %0 \n" 42*8f6290f0SNicholas Piggin " addi %0, %0, (2f-1b) \n" 43*8f6290f0SNicholas Piggin " add %0, %0, %2 \n" 44*8f6290f0SNicholas Piggin " mtctr %0 \n" 45*8f6290f0SNicholas Piggin " bctr \n" 46*8f6290f0SNicholas Piggin "2: \n" 47*8f6290f0SNicholas Piggin ".LSPR=0 \n" 48*8f6290f0SNicholas Piggin ".rept 1024 \n" 49*8f6290f0SNicholas Piggin " mfspr %1, .LSPR \n" 50*8f6290f0SNicholas Piggin " b 3f \n" 51*8f6290f0SNicholas Piggin " .LSPR=.LSPR+1 \n" 52*8f6290f0SNicholas Piggin ".endr \n" 53*8f6290f0SNicholas Piggin "3: \n" 54*8f6290f0SNicholas Piggin : "=&r"(tmp), 55*8f6290f0SNicholas Piggin "=r"(ret) 56*8f6290f0SNicholas Piggin : "r"(spr*8) /* 8 bytes per 'mfspr ; b' block */ 57*8f6290f0SNicholas Piggin : "lr", "ctr"); 58*8f6290f0SNicholas Piggin 59*8f6290f0SNicholas Piggin return ret; 60ee30cf14SThomas Huth } 61ee30cf14SThomas Huth 62*8f6290f0SNicholas Piggin static void __mtspr(unsigned spr, uint64_t val) 63*8f6290f0SNicholas Piggin { 64*8f6290f0SNicholas Piggin uint64_t tmp; 65*8f6290f0SNicholas Piggin 66*8f6290f0SNicholas Piggin asm volatile( 67*8f6290f0SNicholas Piggin " bcl 20, 31, 1f \n" 68*8f6290f0SNicholas Piggin "1: mflr %0 \n" 69*8f6290f0SNicholas Piggin " addi %0, %0, (2f-1b) \n" 70*8f6290f0SNicholas Piggin " add %0, %0, %2 \n" 71*8f6290f0SNicholas Piggin " mtctr %0 \n" 72*8f6290f0SNicholas Piggin " bctr \n" 73*8f6290f0SNicholas Piggin "2: \n" 74*8f6290f0SNicholas Piggin ".LSPR=0 \n" 75*8f6290f0SNicholas Piggin ".rept 1024 \n" 76*8f6290f0SNicholas Piggin " mtspr .LSPR, %1 \n" 77*8f6290f0SNicholas Piggin " b 3f \n" 78*8f6290f0SNicholas Piggin " .LSPR=.LSPR+1 \n" 79*8f6290f0SNicholas Piggin ".endr \n" 80*8f6290f0SNicholas Piggin "3: \n" 81*8f6290f0SNicholas Piggin : "=&r"(tmp) 82*8f6290f0SNicholas Piggin : "r"(val), 83*8f6290f0SNicholas Piggin "r"(spr*8) /* 8 bytes per 'mfspr ; b' block */ 84*8f6290f0SNicholas Piggin : "lr", "ctr", "xer"); 85*8f6290f0SNicholas Piggin } 86*8f6290f0SNicholas Piggin 87*8f6290f0SNicholas Piggin static uint64_t before[1024], after[1024]; 88*8f6290f0SNicholas Piggin 89*8f6290f0SNicholas Piggin #define SPR_PR_READ 0x0001 90*8f6290f0SNicholas Piggin #define SPR_PR_WRITE 0x0002 91*8f6290f0SNicholas Piggin #define SPR_OS_READ 0x0010 92*8f6290f0SNicholas Piggin #define SPR_OS_WRITE 0x0020 93*8f6290f0SNicholas Piggin #define SPR_HV_READ 0x0100 94*8f6290f0SNicholas Piggin #define SPR_HV_WRITE 0x0200 95*8f6290f0SNicholas Piggin 96*8f6290f0SNicholas Piggin #define RW 0x333 97*8f6290f0SNicholas Piggin #define RO 0x111 98*8f6290f0SNicholas Piggin #define WO 0x222 99*8f6290f0SNicholas Piggin #define OS_RW 0x330 100*8f6290f0SNicholas Piggin #define OS_RO 0x110 101*8f6290f0SNicholas Piggin #define OS_WO 0x220 102*8f6290f0SNicholas Piggin #define HV_RW 0x300 103*8f6290f0SNicholas Piggin #define HV_RO 0x100 104*8f6290f0SNicholas Piggin #define HV_WO 0x200 105*8f6290f0SNicholas Piggin 106*8f6290f0SNicholas Piggin #define SPR_ASYNC 0x1000 /* May be updated asynchronously */ 107*8f6290f0SNicholas Piggin #define SPR_INT 0x2000 /* May be updated by synchronous interrupt */ 108*8f6290f0SNicholas Piggin #define SPR_HARNESS 0x4000 /* Test harness uses the register */ 109*8f6290f0SNicholas Piggin 110*8f6290f0SNicholas Piggin struct spr { 111*8f6290f0SNicholas Piggin const char *name; 112*8f6290f0SNicholas Piggin uint8_t width; 113*8f6290f0SNicholas Piggin uint16_t access; 114*8f6290f0SNicholas Piggin uint16_t type; 115*8f6290f0SNicholas Piggin }; 116*8f6290f0SNicholas Piggin 117*8f6290f0SNicholas Piggin /* SPRs common denominator back to PowerPC Operating Environment Architecture */ 118*8f6290f0SNicholas Piggin static const struct spr sprs_common[1024] = { 119*8f6290f0SNicholas Piggin [1] = { "XER", 64, RW, SPR_HARNESS, }, /* Used by compiler */ 120*8f6290f0SNicholas Piggin [8] = { "LR", 64, RW, SPR_HARNESS, }, /* Compiler, mfspr/mtspr */ 121*8f6290f0SNicholas Piggin [9] = { "CTR", 64, RW, SPR_HARNESS, }, /* Compiler, mfspr/mtspr */ 122*8f6290f0SNicholas Piggin [18] = { "DSISR", 32, OS_RW, SPR_INT, }, 123*8f6290f0SNicholas Piggin [19] = { "DAR", 64, OS_RW, SPR_INT, }, 124*8f6290f0SNicholas Piggin [26] = { "SRR0", 64, OS_RW, SPR_INT, }, 125*8f6290f0SNicholas Piggin [27] = { "SRR1", 64, OS_RW, SPR_INT, }, 126*8f6290f0SNicholas Piggin [268] = { "TB", 64, RO , SPR_ASYNC, }, 127*8f6290f0SNicholas Piggin [269] = { "TBU", 32, RO, SPR_ASYNC, }, 128*8f6290f0SNicholas Piggin [272] = { "SPRG0", 64, OS_RW, SPR_HARNESS, }, /* Interrupt stacr */ 129*8f6290f0SNicholas Piggin [273] = { "SPRG1", 64, OS_RW, SPR_HARNESS, }, /* Interrupt Scratch */ 130*8f6290f0SNicholas Piggin [274] = { "SPRG2", 64, OS_RW, }, 131*8f6290f0SNicholas Piggin [275] = { "SPRG3", 64, OS_RW, }, 132*8f6290f0SNicholas Piggin [287] = { "PVR", 32, OS_RO, }, 133*8f6290f0SNicholas Piggin }; 134*8f6290f0SNicholas Piggin 135ee30cf14SThomas Huth /* SPRs from PowerPC Operating Environment Architecture, Book III, Vers. 2.01 */ 136*8f6290f0SNicholas Piggin static const struct spr sprs_201[1024] = { 137*8f6290f0SNicholas Piggin [22] = { "DEC", 32, OS_RW, SPR_ASYNC, }, 138*8f6290f0SNicholas Piggin [25] = { "SDR1", 64, HV_RW | OS_RO, }, 139*8f6290f0SNicholas Piggin [29] = { "ACCR", 64, OS_RW, }, 140*8f6290f0SNicholas Piggin [136] = { "CTRL", 32, RO, }, 141*8f6290f0SNicholas Piggin [152] = { "CTRL", 32, OS_WO, }, 142*8f6290f0SNicholas Piggin [259] = { "SPRG3", 64, RO, }, 143*8f6290f0SNicholas Piggin /* ASR, EAR omitted */ 144*8f6290f0SNicholas Piggin [284] = { "TBL", 32, HV_WO, }, 145*8f6290f0SNicholas Piggin [285] = { "TBU", 32, HV_WO, }, 146*8f6290f0SNicholas Piggin [310] = { "HDEC", 32, HV_RW, SPR_ASYNC, }, 147*8f6290f0SNicholas Piggin [1013]= { "DABR", 64, HV_RW | OS_RO, }, 148*8f6290f0SNicholas Piggin [1023]= { "PIR", 32, OS_RO, SPR_ASYNC, }, /* Can't be virtualised, appears to be async */ 149*8f6290f0SNicholas Piggin }; 150*8f6290f0SNicholas Piggin 151*8f6290f0SNicholas Piggin static const struct spr sprs_970_pmu[1024] = { 152*8f6290f0SNicholas Piggin /* POWER4+ PMU, should confirm with PPC970 */ 153*8f6290f0SNicholas Piggin [770] = { "MMCRA", 64, RO, }, 154*8f6290f0SNicholas Piggin [771] = { "PMC1", 32, RO, }, 155*8f6290f0SNicholas Piggin [772] = { "PMC2", 32, RO, }, 156*8f6290f0SNicholas Piggin [773] = { "PMC3", 32, RO, }, 157*8f6290f0SNicholas Piggin [774] = { "PMC4", 32, RO, }, 158*8f6290f0SNicholas Piggin [775] = { "PMC5", 32, RO, }, 159*8f6290f0SNicholas Piggin [776] = { "PMC6", 32, RO, }, 160*8f6290f0SNicholas Piggin [777] = { "PMC7", 32, RO, }, 161*8f6290f0SNicholas Piggin [778] = { "PMC8", 32, RO, }, 162*8f6290f0SNicholas Piggin [779] = { "MMCR0", 64, RO, }, 163*8f6290f0SNicholas Piggin [780] = { "SIAR", 64, RO, }, 164*8f6290f0SNicholas Piggin [781] = { "SDAR", 64, RO, }, 165*8f6290f0SNicholas Piggin [782] = { "MMCR1", 64, RO, }, 166*8f6290f0SNicholas Piggin [786] = { "MMCRA", 64, OS_RW, }, 167*8f6290f0SNicholas Piggin [787] = { "PMC1", 32, OS_RW, }, 168*8f6290f0SNicholas Piggin [788] = { "PMC2", 32, OS_RW, }, 169*8f6290f0SNicholas Piggin [789] = { "PMC3", 32, OS_RW, }, 170*8f6290f0SNicholas Piggin [790] = { "PMC4", 32, OS_RW, }, 171*8f6290f0SNicholas Piggin [791] = { "PMC5", 32, OS_RW, }, 172*8f6290f0SNicholas Piggin [792] = { "PMC6", 32, OS_RW, }, 173*8f6290f0SNicholas Piggin [793] = { "PMC7", 32, OS_RW, }, 174*8f6290f0SNicholas Piggin [794] = { "PMC8", 32, OS_RW, }, 175*8f6290f0SNicholas Piggin [795] = { "MMCR0", 64, OS_RW, }, 176*8f6290f0SNicholas Piggin [796] = { "SIAR", 64, OS_RW, }, 177*8f6290f0SNicholas Piggin [797] = { "SDAR", 64, OS_RW, }, 178*8f6290f0SNicholas Piggin [798] = { "MMCR1", 64, OS_RW, }, 179*8f6290f0SNicholas Piggin }; 180*8f6290f0SNicholas Piggin 181*8f6290f0SNicholas Piggin /* These are common SPRs from 2.07S onward (POWER CPUs that support KVM HV) */ 182*8f6290f0SNicholas Piggin static const struct spr sprs_power_common[1024] = { 183*8f6290f0SNicholas Piggin [3] = { "DSCR", 64, RW, }, 184*8f6290f0SNicholas Piggin [13] = { "AMR", 64, RW, }, 185*8f6290f0SNicholas Piggin [17] = { "DSCR", 64, OS_RW, }, 186*8f6290f0SNicholas Piggin [28] = { "CFAR", 64, OS_RW, SPR_ASYNC, }, /* Effectively async */ 187*8f6290f0SNicholas Piggin [29] = { "AMR", 64, OS_RW, }, 188*8f6290f0SNicholas Piggin [61] = { "IAMR", 64, OS_RW, }, 189*8f6290f0SNicholas Piggin [136] = { "CTRL", 32, RO, }, 190*8f6290f0SNicholas Piggin [152] = { "CTRL", 32, OS_WO, }, 191*8f6290f0SNicholas Piggin [153] = { "FSCR", 64, OS_RW, }, 192*8f6290f0SNicholas Piggin [157] = { "UAMOR", 64, OS_RW, }, 193*8f6290f0SNicholas Piggin [159] = { "PSPB", 32, OS_RW, }, 194*8f6290f0SNicholas Piggin [176] = { "DPDES", 64, HV_RW | OS_RO, }, 195*8f6290f0SNicholas Piggin [180] = { "DAWR0", 64, HV_RW, }, 196*8f6290f0SNicholas Piggin [186] = { "RPR", 64, HV_RW, }, 197*8f6290f0SNicholas Piggin [187] = { "CIABR", 64, HV_RW, }, 198*8f6290f0SNicholas Piggin [188] = { "DAWRX0", 32, HV_RW, }, 199*8f6290f0SNicholas Piggin [190] = { "HFSCR", 64, HV_RW, }, 200*8f6290f0SNicholas Piggin [256] = { "VRSAVE", 32, RW, }, 201*8f6290f0SNicholas Piggin [259] = { "SPRG3", 64, RO, }, 202*8f6290f0SNicholas Piggin [284] = { "TBL", 32, HV_WO, }, 203*8f6290f0SNicholas Piggin [285] = { "TBU", 32, HV_WO, }, 204*8f6290f0SNicholas Piggin [286] = { "TBU40", 64, HV_WO, }, 205*8f6290f0SNicholas Piggin [304] = { "HSPRG0", 64, HV_RW, }, 206*8f6290f0SNicholas Piggin [305] = { "HSPRG1", 64, HV_RW, }, 207*8f6290f0SNicholas Piggin [306] = { "HDSISR", 32, HV_RW, SPR_INT, }, 208*8f6290f0SNicholas Piggin [307] = { "HDAR", 64, HV_RW, SPR_INT, }, 209*8f6290f0SNicholas Piggin [308] = { "SPURR", 64, HV_RW | OS_RO, SPR_ASYNC, }, 210*8f6290f0SNicholas Piggin [309] = { "PURR", 64, HV_RW | OS_RO, SPR_ASYNC, }, 211*8f6290f0SNicholas Piggin [313] = { "HRMOR", 64, HV_RW, }, 212*8f6290f0SNicholas Piggin [314] = { "HSRR0", 64, HV_RW, SPR_INT, }, 213*8f6290f0SNicholas Piggin [315] = { "HSRR1", 64, HV_RW, SPR_INT, }, 214*8f6290f0SNicholas Piggin [318] = { "LPCR", 64, HV_RW, }, 215*8f6290f0SNicholas Piggin [319] = { "LPIDR", 32, HV_RW, }, 216*8f6290f0SNicholas Piggin [336] = { "HMER", 64, HV_RW, }, 217*8f6290f0SNicholas Piggin [337] = { "HMEER", 64, HV_RW, }, 218*8f6290f0SNicholas Piggin [338] = { "PCR", 64, HV_RW, }, 219*8f6290f0SNicholas Piggin [349] = { "AMOR", 64, HV_RW, }, 220*8f6290f0SNicholas Piggin [446] = { "TIR", 64, OS_RO, }, 221*8f6290f0SNicholas Piggin [800] = { "BESCRS", 64, RW, }, 222*8f6290f0SNicholas Piggin [801] = { "BESCRSU", 32, RW, }, 223*8f6290f0SNicholas Piggin [802] = { "BESCRR", 64, RW, }, 224*8f6290f0SNicholas Piggin [803] = { "BESCRRU", 32, RW, }, 225*8f6290f0SNicholas Piggin [804] = { "EBBHR", 64, RW, }, 226*8f6290f0SNicholas Piggin [805] = { "EBBRR", 64, RW, }, 227*8f6290f0SNicholas Piggin [806] = { "BESCR", 64, RW, }, 228*8f6290f0SNicholas Piggin [815] = { "TAR", 64, RW, }, 229*8f6290f0SNicholas Piggin [848] = { "IC", 64, HV_RW | OS_RO, SPR_ASYNC, }, 230*8f6290f0SNicholas Piggin [849] = { "VTB", 64, HV_RW | OS_RO, SPR_ASYNC, }, 231*8f6290f0SNicholas Piggin [896] = { "PPR", 64, RW, }, 232*8f6290f0SNicholas Piggin [898] = { "PPR32", 32, RW, }, 233*8f6290f0SNicholas Piggin [1023]= { "PIR", 32, OS_RO, SPR_ASYNC, }, /* Can't be virtualised, appears to be async */ 234*8f6290f0SNicholas Piggin }; 235*8f6290f0SNicholas Piggin 236*8f6290f0SNicholas Piggin static const struct spr sprs_tm[1024] = { 237*8f6290f0SNicholas Piggin #if 0 238*8f6290f0SNicholas Piggin /* XXX: leave these out until enabling TM facility (and more testing) */ 239*8f6290f0SNicholas Piggin [128] = { "TFHAR", 64, RW, }, 240*8f6290f0SNicholas Piggin [129] = { "TFIAR", 64, RW, }, 241*8f6290f0SNicholas Piggin [130] = { "TEXASR", 64, RW, }, 242*8f6290f0SNicholas Piggin [131] = { "TEXASRU", 32, RW, }, 243*8f6290f0SNicholas Piggin #endif 244*8f6290f0SNicholas Piggin }; 245ee30cf14SThomas Huth 246ee30cf14SThomas Huth /* SPRs from PowerISA 2.07 Book III-S */ 247*8f6290f0SNicholas Piggin static const struct spr sprs_207[1024] = { 248*8f6290f0SNicholas Piggin [22] = { "DEC", 32, OS_RW, SPR_ASYNC, }, 249*8f6290f0SNicholas Piggin [25] = { "SDR1", 64, HV_RW, }, 250*8f6290f0SNicholas Piggin [177] = { "DHDES", 64, HV_RW, }, 251*8f6290f0SNicholas Piggin [283] = { "CIR", 32, OS_RO, }, 252*8f6290f0SNicholas Piggin [310] = { "HDEC", 32, HV_RW, SPR_ASYNC, }, 253*8f6290f0SNicholas Piggin [312] = { "RMOR", 64, HV_RW, }, 254*8f6290f0SNicholas Piggin [339] = { "HEIR", 32, HV_RW, SPR_INT, }, 255*8f6290f0SNicholas Piggin }; 256ee30cf14SThomas Huth 25725a302cbSThomas Huth /* SPRs from PowerISA 3.00 Book III */ 258*8f6290f0SNicholas Piggin static const struct spr sprs_300[1024] = { 259*8f6290f0SNicholas Piggin [22] = { "DEC", 64, OS_RW, SPR_ASYNC, }, 260*8f6290f0SNicholas Piggin [48] = { "PIDR", 32, OS_RW, }, 261*8f6290f0SNicholas Piggin [144] = { "TIDR", 64, OS_RW, }, 262*8f6290f0SNicholas Piggin [283] = { "CIR", 32, OS_RO, }, 263*8f6290f0SNicholas Piggin [310] = { "HDEC", 64, HV_RW, SPR_ASYNC, }, 264*8f6290f0SNicholas Piggin [339] = { "HEIR", 32, HV_RW, SPR_INT, }, 265*8f6290f0SNicholas Piggin [464] = { "PTCR", 64, HV_RW, }, 266*8f6290f0SNicholas Piggin [816] = { "ASDR", 64, HV_RW, SPR_INT, }, 267*8f6290f0SNicholas Piggin [823] = { "PSSCR", 64, OS_RW, }, 268*8f6290f0SNicholas Piggin [855] = { "PSSCR", 64, HV_RW, }, 269*8f6290f0SNicholas Piggin }; 27025a302cbSThomas Huth 271*8f6290f0SNicholas Piggin /* SPRs from PowerISA 3.1B Book III */ 272*8f6290f0SNicholas Piggin static const struct spr sprs_31[1024] = { 273*8f6290f0SNicholas Piggin [22] = { "DEC", 64, OS_RW, SPR_ASYNC, }, 274*8f6290f0SNicholas Piggin [48] = { "PIDR", 32, OS_RW, }, 275*8f6290f0SNicholas Piggin [181] = { "DAWR1", 64, HV_RW, }, 276*8f6290f0SNicholas Piggin [189] = { "DAWRX1", 32, HV_RW, }, 277*8f6290f0SNicholas Piggin [310] = { "HDEC", 64, HV_RW, SPR_ASYNC, }, 278*8f6290f0SNicholas Piggin [339] = { "HEIR", 64, HV_RW, SPR_INT, }, 279*8f6290f0SNicholas Piggin [455] = { "HDEXCR", 32, RO, }, 280*8f6290f0SNicholas Piggin [464] = { "PTCR", 64, HV_RW, }, 281*8f6290f0SNicholas Piggin [468] = { "HASHKEYR", 64, OS_RW, }, 282*8f6290f0SNicholas Piggin [469] = { "HASHPKEYR", 64, HV_RW, }, 283*8f6290f0SNicholas Piggin [471] = { "HDEXCR", 64, HV_RW, }, 284*8f6290f0SNicholas Piggin [812] = { "DEXCR", 32, RO, }, 285*8f6290f0SNicholas Piggin [816] = { "ASDR", 64, HV_RW, SPR_INT, }, 286*8f6290f0SNicholas Piggin [823] = { "PSSCR", 64, OS_RW, }, 287*8f6290f0SNicholas Piggin [828] = { "DEXCR", 64, OS_RW, }, 288*8f6290f0SNicholas Piggin [855] = { "PSSCR", 64, HV_RW, }, 289*8f6290f0SNicholas Piggin }; 290faaddcb0SNicholas Piggin 291*8f6290f0SNicholas Piggin /* SPRs POWER9, POWER10 User Manual */ 292*8f6290f0SNicholas Piggin static const struct spr sprs_power9_10[1024] = { 293*8f6290f0SNicholas Piggin [276] = { "SPRC", 64, HV_RW, }, 294*8f6290f0SNicholas Piggin [277] = { "SPRD", 64, HV_RW, }, 295*8f6290f0SNicholas Piggin [317] = { "TFMR", 64, HV_RW, }, 296*8f6290f0SNicholas Piggin [799] = { "IMC", 64, HV_RW, }, 297*8f6290f0SNicholas Piggin [850] = { "LDBAR", 64, HV_RO, }, 298*8f6290f0SNicholas Piggin [851] = { "MMCRC", 32, HV_RW, }, 299*8f6290f0SNicholas Piggin [853] = { "PMSR", 32, HV_RO, }, 300*8f6290f0SNicholas Piggin [861] = { "L2QOSR", 64, HV_WO, }, 301*8f6290f0SNicholas Piggin [881] = { "TRIG1", 64, OS_WO, }, 302*8f6290f0SNicholas Piggin [882] = { "TRIG2", 64, OS_WO, }, 303*8f6290f0SNicholas Piggin [884] = { "PMCR", 64, HV_RW, }, 304*8f6290f0SNicholas Piggin [885] = { "RWMR", 64, HV_RW, }, 305*8f6290f0SNicholas Piggin [895] = { "WORT", 64, OS_RW, }, /* UM says 18-bits! */ 306*8f6290f0SNicholas Piggin [921] = { "TSCR", 32, HV_RW, }, 307*8f6290f0SNicholas Piggin [922] = { "TTR", 64, HV_RW, }, 308*8f6290f0SNicholas Piggin [1006]= { "TRACE", 64, WO, }, 309*8f6290f0SNicholas Piggin [1008]= { "HID", 64, HV_RW, }, 310*8f6290f0SNicholas Piggin }; 311*8f6290f0SNicholas Piggin 312*8f6290f0SNicholas Piggin /* This covers POWER8 and POWER9 PMUs */ 313*8f6290f0SNicholas Piggin static const struct spr sprs_power_common_pmu[1024] = { 314*8f6290f0SNicholas Piggin [768] = { "SIER", 64, RO, }, 315*8f6290f0SNicholas Piggin [769] = { "MMCR2", 64, RW, }, 316*8f6290f0SNicholas Piggin [770] = { "MMCRA", 64, RW, }, 317*8f6290f0SNicholas Piggin [771] = { "PMC1", 32, RW, }, 318*8f6290f0SNicholas Piggin [772] = { "PMC2", 32, RW, }, 319*8f6290f0SNicholas Piggin [773] = { "PMC3", 32, RW, }, 320*8f6290f0SNicholas Piggin [774] = { "PMC4", 32, RW, }, 321*8f6290f0SNicholas Piggin [775] = { "PMC5", 32, RW, }, 322*8f6290f0SNicholas Piggin [776] = { "PMC6", 32, RW, }, 323*8f6290f0SNicholas Piggin [779] = { "MMCR0", 64, RW, }, 324*8f6290f0SNicholas Piggin [780] = { "SIAR", 64, RO, }, 325*8f6290f0SNicholas Piggin [781] = { "SDAR", 64, RO, }, 326*8f6290f0SNicholas Piggin [782] = { "MMCR1", 64, RO, }, 327*8f6290f0SNicholas Piggin [784] = { "SIER", 64, OS_RW, }, 328*8f6290f0SNicholas Piggin [785] = { "MMCR2", 64, OS_RW, }, 329*8f6290f0SNicholas Piggin [786] = { "MMCRA", 64, OS_RW, }, 330*8f6290f0SNicholas Piggin [787] = { "PMC1", 32, OS_RW, }, 331*8f6290f0SNicholas Piggin [788] = { "PMC2", 32, OS_RW, }, 332*8f6290f0SNicholas Piggin [789] = { "PMC3", 32, OS_RW, }, 333*8f6290f0SNicholas Piggin [790] = { "PMC4", 32, OS_RW, }, 334*8f6290f0SNicholas Piggin [791] = { "PMC5", 32, OS_RW, }, 335*8f6290f0SNicholas Piggin [792] = { "PMC6", 32, OS_RW, }, 336*8f6290f0SNicholas Piggin [795] = { "MMCR0", 64, OS_RW, }, 337*8f6290f0SNicholas Piggin [796] = { "SIAR", 64, OS_RW, }, 338*8f6290f0SNicholas Piggin [797] = { "SDAR", 64, OS_RW, }, 339*8f6290f0SNicholas Piggin [798] = { "MMCR1", 64, OS_RW, }, 340*8f6290f0SNicholas Piggin }; 341*8f6290f0SNicholas Piggin 342*8f6290f0SNicholas Piggin static const struct spr sprs_power10_pmu[1024] = { 343*8f6290f0SNicholas Piggin [736] = { "SIER2", 64, RO, }, 344*8f6290f0SNicholas Piggin [737] = { "SIER3", 64, RO, }, 345*8f6290f0SNicholas Piggin [738] = { "MMCR3", 64, RO, }, 346*8f6290f0SNicholas Piggin [752] = { "SIER2", 64, OS_RW, }, 347*8f6290f0SNicholas Piggin [753] = { "SIER3", 64, OS_RW, }, 348*8f6290f0SNicholas Piggin [754] = { "MMCR3", 64, OS_RW, }, 349*8f6290f0SNicholas Piggin }; 350*8f6290f0SNicholas Piggin 351*8f6290f0SNicholas Piggin static struct spr sprs[1024]; 352*8f6290f0SNicholas Piggin 353*8f6290f0SNicholas Piggin static void setup_sprs(void) 354ee30cf14SThomas Huth { 355*8f6290f0SNicholas Piggin int i; 356*8f6290f0SNicholas Piggin 357*8f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 358*8f6290f0SNicholas Piggin if (sprs_common[i].name) { 359*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_common[i], sizeof(struct spr)); 360*8f6290f0SNicholas Piggin } 361*8f6290f0SNicholas Piggin } 362ee30cf14SThomas Huth 3639c5e1913SNicholas Piggin switch (mfspr(SPR_PVR) & PVR_VERSION_MASK) { 3649c5e1913SNicholas Piggin case PVR_VER_970: 3659c5e1913SNicholas Piggin case PVR_VER_970FX: 3669c5e1913SNicholas Piggin case PVR_VER_970MP: 367*8f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 368*8f6290f0SNicholas Piggin if (sprs_201[i].name) { 369*8f6290f0SNicholas Piggin assert(!sprs[i].name); 370*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_201[i], sizeof(struct spr)); 371*8f6290f0SNicholas Piggin } 372*8f6290f0SNicholas Piggin if (sprs_970_pmu[i].name) { 373*8f6290f0SNicholas Piggin assert(!sprs[i].name); 374*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 375*8f6290f0SNicholas Piggin } 376*8f6290f0SNicholas Piggin } 377ee30cf14SThomas Huth break; 378*8f6290f0SNicholas Piggin 3799c5e1913SNicholas Piggin case PVR_VER_POWER8E: 3809c5e1913SNicholas Piggin case PVR_VER_POWER8NVL: 3819c5e1913SNicholas Piggin case PVR_VER_POWER8: 382*8f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 383*8f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 384*8f6290f0SNicholas Piggin assert(!sprs[i].name); 385*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 386*8f6290f0SNicholas Piggin } 387*8f6290f0SNicholas Piggin if (sprs_207[i].name) { 388*8f6290f0SNicholas Piggin assert(!sprs[i].name); 389*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_207[i], sizeof(struct spr)); 390*8f6290f0SNicholas Piggin } 391*8f6290f0SNicholas Piggin if (sprs_tm[i].name) { 392*8f6290f0SNicholas Piggin assert(!sprs[i].name); 393*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr)); 394*8f6290f0SNicholas Piggin } 395*8f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 396*8f6290f0SNicholas Piggin assert(!sprs[i].name); 397*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 398*8f6290f0SNicholas Piggin } 399*8f6290f0SNicholas Piggin } 400ee30cf14SThomas Huth break; 401*8f6290f0SNicholas Piggin 4029c5e1913SNicholas Piggin case PVR_VER_POWER9: 403*8f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 404*8f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 405*8f6290f0SNicholas Piggin assert(!sprs[i].name); 406*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 407*8f6290f0SNicholas Piggin } 408*8f6290f0SNicholas Piggin if (sprs_300[i].name) { 409*8f6290f0SNicholas Piggin assert(!sprs[i].name); 410*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_300[i], sizeof(struct spr)); 411*8f6290f0SNicholas Piggin } 412*8f6290f0SNicholas Piggin if (sprs_tm[i].name) { 413*8f6290f0SNicholas Piggin assert(!sprs[i].name); 414*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr)); 415*8f6290f0SNicholas Piggin } 416*8f6290f0SNicholas Piggin if (sprs_power9_10[i].name) { 417*8f6290f0SNicholas Piggin assert(!sprs[i].name); 418*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr)); 419*8f6290f0SNicholas Piggin } 420*8f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 421*8f6290f0SNicholas Piggin assert(!sprs[i].name); 422*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 423*8f6290f0SNicholas Piggin } 424*8f6290f0SNicholas Piggin } 42525a302cbSThomas Huth break; 426*8f6290f0SNicholas Piggin 4279c5e1913SNicholas Piggin case PVR_VER_POWER10: 428*8f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 429*8f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 430*8f6290f0SNicholas Piggin assert(!sprs[i].name); 431*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 432*8f6290f0SNicholas Piggin } 433*8f6290f0SNicholas Piggin if (sprs_31[i].name) { 434*8f6290f0SNicholas Piggin assert(!sprs[i].name); 435*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_31[i], sizeof(struct spr)); 436*8f6290f0SNicholas Piggin } 437*8f6290f0SNicholas Piggin if (sprs_power9_10[i].name) { 438*8f6290f0SNicholas Piggin assert(!sprs[i].name); 439*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr)); 440*8f6290f0SNicholas Piggin } 441*8f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 442*8f6290f0SNicholas Piggin assert(!sprs[i].name); 443*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 444*8f6290f0SNicholas Piggin } 445*8f6290f0SNicholas Piggin if (sprs_power10_pmu[i].name) { 446*8f6290f0SNicholas Piggin assert(!sprs[i].name); 447*8f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power10_pmu[i], sizeof(struct spr)); 448*8f6290f0SNicholas Piggin } 449*8f6290f0SNicholas Piggin } 450faaddcb0SNicholas Piggin break; 451*8f6290f0SNicholas Piggin 452ee30cf14SThomas Huth default: 453*8f6290f0SNicholas Piggin memcpy(sprs, sprs_common, sizeof(sprs)); 454*8f6290f0SNicholas Piggin puts("Warning: Unknown processor version, falling back to common SPRs!\n"); 455*8f6290f0SNicholas Piggin break; 456ee30cf14SThomas Huth } 457ee30cf14SThomas Huth } 458ee30cf14SThomas Huth 459ee30cf14SThomas Huth static void get_sprs(uint64_t *v) 460ee30cf14SThomas Huth { 461*8f6290f0SNicholas Piggin int i; 462ee30cf14SThomas Huth 463*8f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 464*8f6290f0SNicholas Piggin if (!(sprs[i].access & SPR_OS_READ)) 465*8f6290f0SNicholas Piggin continue; 466*8f6290f0SNicholas Piggin v[i] = __mfspr(i); 467*8f6290f0SNicholas Piggin } 468*8f6290f0SNicholas Piggin } 469ee30cf14SThomas Huth 470*8f6290f0SNicholas Piggin static void set_sprs(uint64_t val) 471*8f6290f0SNicholas Piggin { 472*8f6290f0SNicholas Piggin int i; 473*8f6290f0SNicholas Piggin 474*8f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 475*8f6290f0SNicholas Piggin if (!(sprs[i].access & SPR_OS_WRITE)) 476*8f6290f0SNicholas Piggin continue; 477*8f6290f0SNicholas Piggin if (sprs[i].type & SPR_HARNESS) 478*8f6290f0SNicholas Piggin continue; 479*8f6290f0SNicholas Piggin if (!strcmp(sprs[i].name, "MMCR0")) { 480*8f6290f0SNicholas Piggin /* XXX: could use a comment or better abstraction! */ 481*8f6290f0SNicholas Piggin __mtspr(i, (val & 0xfffffffffbab3fffULL) | 0xfa0b2070); 482*8f6290f0SNicholas Piggin } else { 483*8f6290f0SNicholas Piggin __mtspr(i, val); 484*8f6290f0SNicholas Piggin } 485ee30cf14SThomas Huth } 486ee30cf14SThomas Huth } 487ee30cf14SThomas Huth 488ee30cf14SThomas Huth int main(int argc, char **argv) 489ee30cf14SThomas Huth { 490ee30cf14SThomas Huth int i; 491ee30cf14SThomas Huth bool pause = false; 492ee30cf14SThomas Huth uint64_t pat = 0xcafefacec0debabeULL; 493ee30cf14SThomas Huth const uint64_t patterns[] = { 494ee30cf14SThomas Huth 0xcafefacec0debabeULL, ~0xcafefacec0debabeULL, 495ee30cf14SThomas Huth 0xAAAA5555AAAA5555ULL, 0x5555AAAA5555AAAAULL, 496ee30cf14SThomas Huth 0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL, 497ee30cf14SThomas Huth -1ULL, 498ee30cf14SThomas Huth }; 499ee30cf14SThomas Huth 500ee30cf14SThomas Huth for (i = 1; i < argc; i++) { 501ee30cf14SThomas Huth if (!strcmp(argv[i], "-w")) { 502ee30cf14SThomas Huth pause = true; 503ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-p")) { 504ee30cf14SThomas Huth i += 1; 505ee30cf14SThomas Huth if (i >= argc || *argv[i] < '0' 506ee30cf14SThomas Huth || *argv[i] >= '0' + ARRAY_SIZE(patterns)) 507ee30cf14SThomas Huth report_abort("Error: bad value for -p"); 508ee30cf14SThomas Huth pat ^= patterns[*argv[i] - '0']; 509ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-t")) { 510ee30cf14SThomas Huth /* Randomize with timebase register */ 511ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 512ee30cf14SThomas Huth pat ^= i; 513ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 514ee30cf14SThomas Huth pat ^= ~(uint64_t)i << 32; 515ee30cf14SThomas Huth } else { 516ee30cf14SThomas Huth report_abort("Warning: Unsupported argument: %s", 517ee30cf14SThomas Huth argv[i]); 518ee30cf14SThomas Huth } 519ee30cf14SThomas Huth } 520ee30cf14SThomas Huth 521*8f6290f0SNicholas Piggin setup_sprs(); 522*8f6290f0SNicholas Piggin 523*8f6290f0SNicholas Piggin printf("Setting SPRs to 0x%lx...\n", pat); 524ee30cf14SThomas Huth set_sprs(pat); 525ee30cf14SThomas Huth 526ee30cf14SThomas Huth memset(before, 0, sizeof(before)); 527ee30cf14SThomas Huth memset(after, 0, sizeof(after)); 528ee30cf14SThomas Huth 529ee30cf14SThomas Huth get_sprs(before); 530ee30cf14SThomas Huth 531ee30cf14SThomas Huth if (pause) { 53277a59d17SNico Boehr migrate_once(); 533*8f6290f0SNicholas Piggin /* Reload regs changed by getchar/putchar hcalls */ 534*8f6290f0SNicholas Piggin before[SPR_SRR0] = mfspr(SPR_SRR0); 535*8f6290f0SNicholas Piggin before[SPR_SRR1] = mfspr(SPR_SRR1); 536*8f6290f0SNicholas Piggin 537*8f6290f0SNicholas Piggin /* WORT seems to go to 0 after KVM switch, perhaps CPU idle */ 538*8f6290f0SNicholas Piggin if (sprs[895].name) 539*8f6290f0SNicholas Piggin before[895] = mfspr(895); 540ee30cf14SThomas Huth } else { 541ba33a96fSNicholas Piggin msleep(2000); 542*8f6290f0SNicholas Piggin 543*8f6290f0SNicholas Piggin /* Reload regs changed by dec interrupt */ 544*8f6290f0SNicholas Piggin before[SPR_SRR0] = mfspr(SPR_SRR0); 545*8f6290f0SNicholas Piggin before[SPR_SRR1] = mfspr(SPR_SRR1); 546*8f6290f0SNicholas Piggin before[SPR_SPRG1] = mfspr(SPR_SPRG1); 547*8f6290f0SNicholas Piggin 548*8f6290f0SNicholas Piggin /* WORT seems to go to 0 after KVM switch, perhaps CPU idle */ 549*8f6290f0SNicholas Piggin if (sprs[895].name) 550*8f6290f0SNicholas Piggin before[895] = mfspr(895); 551ee30cf14SThomas Huth } 552ee30cf14SThomas Huth 553ee30cf14SThomas Huth get_sprs(after); 554ee30cf14SThomas Huth 555ee30cf14SThomas Huth puts("Checking SPRs...\n"); 556ee30cf14SThomas Huth for (i = 0; i < 1024; i++) { 557*8f6290f0SNicholas Piggin bool pass = true; 558*8f6290f0SNicholas Piggin 559*8f6290f0SNicholas Piggin if (!(sprs[i].access & SPR_OS_READ)) 560*8f6290f0SNicholas Piggin continue; 561*8f6290f0SNicholas Piggin 562*8f6290f0SNicholas Piggin if (sprs[i].width == 32) { 563*8f6290f0SNicholas Piggin if (before[i] >> 32) 564*8f6290f0SNicholas Piggin pass = false; 565*8f6290f0SNicholas Piggin } 566*8f6290f0SNicholas Piggin if (!(sprs[i].type & (SPR_HARNESS|SPR_ASYNC)) && (before[i] != after[i])) 567*8f6290f0SNicholas Piggin pass = false; 568*8f6290f0SNicholas Piggin 569*8f6290f0SNicholas Piggin if (sprs[i].width == 32 && !(before[i] >> 32) && !(after[i] >> 32)) { 570*8f6290f0SNicholas Piggin /* known failure KVM migration of CTRL */ 571*8f6290f0SNicholas Piggin report_kfail(true && i == 136, 572*8f6290f0SNicholas Piggin "%-10s(%4d):\t 0x%08lx <==> 0x%08lx", 573*8f6290f0SNicholas Piggin sprs[i].name, i, 574*8f6290f0SNicholas Piggin before[i], after[i]); 575*8f6290f0SNicholas Piggin } else { 576*8f6290f0SNicholas Piggin report(pass, "%-10s(%4d):\t0x%016lx <==> 0x%016lx", 577*8f6290f0SNicholas Piggin sprs[i].name, i, 578*8f6290f0SNicholas Piggin before[i], after[i]); 579*8f6290f0SNicholas Piggin } 580ee30cf14SThomas Huth } 581ee30cf14SThomas Huth 582ee30cf14SThomas Huth return report_summary(); 583ee30cf14SThomas Huth } 584