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 338f6290f0SNicholas Piggin /* "Indirect" mfspr/mtspr which accept a non-constant spr number */ 348f6290f0SNicholas Piggin static uint64_t __mfspr(unsigned spr) 35ee30cf14SThomas Huth { 368f6290f0SNicholas Piggin uint64_t tmp; 378f6290f0SNicholas Piggin uint64_t ret; 388f6290f0SNicholas Piggin 398f6290f0SNicholas Piggin asm volatile( 408f6290f0SNicholas Piggin " bcl 20, 31, 1f \n" 418f6290f0SNicholas Piggin "1: mflr %0 \n" 428f6290f0SNicholas Piggin " addi %0, %0, (2f-1b) \n" 438f6290f0SNicholas Piggin " add %0, %0, %2 \n" 448f6290f0SNicholas Piggin " mtctr %0 \n" 458f6290f0SNicholas Piggin " bctr \n" 468f6290f0SNicholas Piggin "2: \n" 478f6290f0SNicholas Piggin ".LSPR=0 \n" 488f6290f0SNicholas Piggin ".rept 1024 \n" 498f6290f0SNicholas Piggin " mfspr %1, .LSPR \n" 508f6290f0SNicholas Piggin " b 3f \n" 518f6290f0SNicholas Piggin " .LSPR=.LSPR+1 \n" 528f6290f0SNicholas Piggin ".endr \n" 538f6290f0SNicholas Piggin "3: \n" 548f6290f0SNicholas Piggin : "=&r"(tmp), 558f6290f0SNicholas Piggin "=r"(ret) 568f6290f0SNicholas Piggin : "r"(spr*8) /* 8 bytes per 'mfspr ; b' block */ 578f6290f0SNicholas Piggin : "lr", "ctr"); 588f6290f0SNicholas Piggin 598f6290f0SNicholas Piggin return ret; 60ee30cf14SThomas Huth } 61ee30cf14SThomas Huth 628f6290f0SNicholas Piggin static void __mtspr(unsigned spr, uint64_t val) 638f6290f0SNicholas Piggin { 648f6290f0SNicholas Piggin uint64_t tmp; 658f6290f0SNicholas Piggin 668f6290f0SNicholas Piggin asm volatile( 678f6290f0SNicholas Piggin " bcl 20, 31, 1f \n" 688f6290f0SNicholas Piggin "1: mflr %0 \n" 698f6290f0SNicholas Piggin " addi %0, %0, (2f-1b) \n" 708f6290f0SNicholas Piggin " add %0, %0, %2 \n" 718f6290f0SNicholas Piggin " mtctr %0 \n" 728f6290f0SNicholas Piggin " bctr \n" 738f6290f0SNicholas Piggin "2: \n" 748f6290f0SNicholas Piggin ".LSPR=0 \n" 758f6290f0SNicholas Piggin ".rept 1024 \n" 768f6290f0SNicholas Piggin " mtspr .LSPR, %1 \n" 778f6290f0SNicholas Piggin " b 3f \n" 788f6290f0SNicholas Piggin " .LSPR=.LSPR+1 \n" 798f6290f0SNicholas Piggin ".endr \n" 808f6290f0SNicholas Piggin "3: \n" 818f6290f0SNicholas Piggin : "=&r"(tmp) 828f6290f0SNicholas Piggin : "r"(val), 838f6290f0SNicholas Piggin "r"(spr*8) /* 8 bytes per 'mfspr ; b' block */ 848f6290f0SNicholas Piggin : "lr", "ctr", "xer"); 858f6290f0SNicholas Piggin } 868f6290f0SNicholas Piggin 878f6290f0SNicholas Piggin static uint64_t before[1024], after[1024]; 888f6290f0SNicholas Piggin 898f6290f0SNicholas Piggin #define SPR_PR_READ 0x0001 908f6290f0SNicholas Piggin #define SPR_PR_WRITE 0x0002 918f6290f0SNicholas Piggin #define SPR_OS_READ 0x0010 928f6290f0SNicholas Piggin #define SPR_OS_WRITE 0x0020 938f6290f0SNicholas Piggin #define SPR_HV_READ 0x0100 948f6290f0SNicholas Piggin #define SPR_HV_WRITE 0x0200 958f6290f0SNicholas Piggin 968f6290f0SNicholas Piggin #define RW 0x333 978f6290f0SNicholas Piggin #define RO 0x111 988f6290f0SNicholas Piggin #define WO 0x222 998f6290f0SNicholas Piggin #define OS_RW 0x330 1008f6290f0SNicholas Piggin #define OS_RO 0x110 1018f6290f0SNicholas Piggin #define OS_WO 0x220 1028f6290f0SNicholas Piggin #define HV_RW 0x300 1038f6290f0SNicholas Piggin #define HV_RO 0x100 1048f6290f0SNicholas Piggin #define HV_WO 0x200 1058f6290f0SNicholas Piggin 1068f6290f0SNicholas Piggin #define SPR_ASYNC 0x1000 /* May be updated asynchronously */ 1078f6290f0SNicholas Piggin #define SPR_INT 0x2000 /* May be updated by synchronous interrupt */ 1088f6290f0SNicholas Piggin #define SPR_HARNESS 0x4000 /* Test harness uses the register */ 1098f6290f0SNicholas Piggin 1108f6290f0SNicholas Piggin struct spr { 1118f6290f0SNicholas Piggin const char *name; 1128f6290f0SNicholas Piggin uint8_t width; 1138f6290f0SNicholas Piggin uint16_t access; 1148f6290f0SNicholas Piggin uint16_t type; 1158f6290f0SNicholas Piggin }; 1168f6290f0SNicholas Piggin 1178f6290f0SNicholas Piggin /* SPRs common denominator back to PowerPC Operating Environment Architecture */ 1188f6290f0SNicholas Piggin static const struct spr sprs_common[1024] = { 1198f6290f0SNicholas Piggin [1] = { "XER", 64, RW, SPR_HARNESS, }, /* Used by compiler */ 1208f6290f0SNicholas Piggin [8] = { "LR", 64, RW, SPR_HARNESS, }, /* Compiler, mfspr/mtspr */ 1218f6290f0SNicholas Piggin [9] = { "CTR", 64, RW, SPR_HARNESS, }, /* Compiler, mfspr/mtspr */ 1228f6290f0SNicholas Piggin [18] = { "DSISR", 32, OS_RW, SPR_INT, }, 1238f6290f0SNicholas Piggin [19] = { "DAR", 64, OS_RW, SPR_INT, }, 1248f6290f0SNicholas Piggin [26] = { "SRR0", 64, OS_RW, SPR_INT, }, 1258f6290f0SNicholas Piggin [27] = { "SRR1", 64, OS_RW, SPR_INT, }, 1268f6290f0SNicholas Piggin [268] = { "TB", 64, RO , SPR_ASYNC, }, 1278f6290f0SNicholas Piggin [269] = { "TBU", 32, RO, SPR_ASYNC, }, 1288f6290f0SNicholas Piggin [272] = { "SPRG0", 64, OS_RW, SPR_HARNESS, }, /* Interrupt stacr */ 1298f6290f0SNicholas Piggin [273] = { "SPRG1", 64, OS_RW, SPR_HARNESS, }, /* Interrupt Scratch */ 1308f6290f0SNicholas Piggin [274] = { "SPRG2", 64, OS_RW, }, 1318f6290f0SNicholas Piggin [275] = { "SPRG3", 64, OS_RW, }, 1328f6290f0SNicholas Piggin [287] = { "PVR", 32, OS_RO, }, 1338f6290f0SNicholas Piggin }; 1348f6290f0SNicholas Piggin 135ee30cf14SThomas Huth /* SPRs from PowerPC Operating Environment Architecture, Book III, Vers. 2.01 */ 1368f6290f0SNicholas Piggin static const struct spr sprs_201[1024] = { 1378f6290f0SNicholas Piggin [22] = { "DEC", 32, OS_RW, SPR_ASYNC, }, 1388f6290f0SNicholas Piggin [25] = { "SDR1", 64, HV_RW | OS_RO, }, 1398f6290f0SNicholas Piggin [29] = { "ACCR", 64, OS_RW, }, 1408f6290f0SNicholas Piggin [136] = { "CTRL", 32, RO, }, 1418f6290f0SNicholas Piggin [152] = { "CTRL", 32, OS_WO, }, 1428f6290f0SNicholas Piggin [259] = { "SPRG3", 64, RO, }, 1438f6290f0SNicholas Piggin /* ASR, EAR omitted */ 1448f6290f0SNicholas Piggin [284] = { "TBL", 32, HV_WO, }, 1458f6290f0SNicholas Piggin [285] = { "TBU", 32, HV_WO, }, 1468f6290f0SNicholas Piggin [310] = { "HDEC", 32, HV_RW, SPR_ASYNC, }, 1478f6290f0SNicholas Piggin [1013]= { "DABR", 64, HV_RW | OS_RO, }, 1488f6290f0SNicholas Piggin [1023]= { "PIR", 32, OS_RO, SPR_ASYNC, }, /* Can't be virtualised, appears to be async */ 1498f6290f0SNicholas Piggin }; 1508f6290f0SNicholas Piggin 1518f6290f0SNicholas Piggin static const struct spr sprs_970_pmu[1024] = { 1528f6290f0SNicholas Piggin /* POWER4+ PMU, should confirm with PPC970 */ 1538f6290f0SNicholas Piggin [770] = { "MMCRA", 64, RO, }, 1548f6290f0SNicholas Piggin [771] = { "PMC1", 32, RO, }, 1558f6290f0SNicholas Piggin [772] = { "PMC2", 32, RO, }, 1568f6290f0SNicholas Piggin [773] = { "PMC3", 32, RO, }, 1578f6290f0SNicholas Piggin [774] = { "PMC4", 32, RO, }, 1588f6290f0SNicholas Piggin [775] = { "PMC5", 32, RO, }, 1598f6290f0SNicholas Piggin [776] = { "PMC6", 32, RO, }, 1608f6290f0SNicholas Piggin [777] = { "PMC7", 32, RO, }, 1618f6290f0SNicholas Piggin [778] = { "PMC8", 32, RO, }, 1628f6290f0SNicholas Piggin [779] = { "MMCR0", 64, RO, }, 1638f6290f0SNicholas Piggin [780] = { "SIAR", 64, RO, }, 1648f6290f0SNicholas Piggin [781] = { "SDAR", 64, RO, }, 1658f6290f0SNicholas Piggin [782] = { "MMCR1", 64, RO, }, 1668f6290f0SNicholas Piggin [786] = { "MMCRA", 64, OS_RW, }, 1678f6290f0SNicholas Piggin [787] = { "PMC1", 32, OS_RW, }, 1688f6290f0SNicholas Piggin [788] = { "PMC2", 32, OS_RW, }, 1698f6290f0SNicholas Piggin [789] = { "PMC3", 32, OS_RW, }, 1708f6290f0SNicholas Piggin [790] = { "PMC4", 32, OS_RW, }, 1718f6290f0SNicholas Piggin [791] = { "PMC5", 32, OS_RW, }, 1728f6290f0SNicholas Piggin [792] = { "PMC6", 32, OS_RW, }, 1738f6290f0SNicholas Piggin [793] = { "PMC7", 32, OS_RW, }, 1748f6290f0SNicholas Piggin [794] = { "PMC8", 32, OS_RW, }, 1758f6290f0SNicholas Piggin [795] = { "MMCR0", 64, OS_RW, }, 1768f6290f0SNicholas Piggin [796] = { "SIAR", 64, OS_RW, }, 1778f6290f0SNicholas Piggin [797] = { "SDAR", 64, OS_RW, }, 1788f6290f0SNicholas Piggin [798] = { "MMCR1", 64, OS_RW, }, 1798f6290f0SNicholas Piggin }; 1808f6290f0SNicholas Piggin 1818f6290f0SNicholas Piggin /* These are common SPRs from 2.07S onward (POWER CPUs that support KVM HV) */ 1828f6290f0SNicholas Piggin static const struct spr sprs_power_common[1024] = { 1838f6290f0SNicholas Piggin [3] = { "DSCR", 64, RW, }, 1848f6290f0SNicholas Piggin [13] = { "AMR", 64, RW, }, 1858f6290f0SNicholas Piggin [17] = { "DSCR", 64, OS_RW, }, 1868f6290f0SNicholas Piggin [28] = { "CFAR", 64, OS_RW, SPR_ASYNC, }, /* Effectively async */ 1878f6290f0SNicholas Piggin [29] = { "AMR", 64, OS_RW, }, 1888f6290f0SNicholas Piggin [61] = { "IAMR", 64, OS_RW, }, 1898f6290f0SNicholas Piggin [136] = { "CTRL", 32, RO, }, 1908f6290f0SNicholas Piggin [152] = { "CTRL", 32, OS_WO, }, 1918f6290f0SNicholas Piggin [153] = { "FSCR", 64, OS_RW, }, 1928f6290f0SNicholas Piggin [157] = { "UAMOR", 64, OS_RW, }, 1938f6290f0SNicholas Piggin [159] = { "PSPB", 32, OS_RW, }, 1948f6290f0SNicholas Piggin [176] = { "DPDES", 64, HV_RW | OS_RO, }, 1958f6290f0SNicholas Piggin [180] = { "DAWR0", 64, HV_RW, }, 1968f6290f0SNicholas Piggin [186] = { "RPR", 64, HV_RW, }, 1978f6290f0SNicholas Piggin [187] = { "CIABR", 64, HV_RW, }, 1988f6290f0SNicholas Piggin [188] = { "DAWRX0", 32, HV_RW, }, 1998f6290f0SNicholas Piggin [190] = { "HFSCR", 64, HV_RW, }, 2008f6290f0SNicholas Piggin [256] = { "VRSAVE", 32, RW, }, 2018f6290f0SNicholas Piggin [259] = { "SPRG3", 64, RO, }, 202584c6ad4SNicholas Piggin [284] = { "TBL", 32, HV_WO, }, /* Things can go a bit wonky with */ 203584c6ad4SNicholas Piggin [285] = { "TBU", 32, HV_WO, }, /* Timebase changing. Should save */ 204584c6ad4SNicholas Piggin [286] = { "TBU40", 64, HV_WO, }, /* and restore it. */ 2058f6290f0SNicholas Piggin [304] = { "HSPRG0", 64, HV_RW, }, 2068f6290f0SNicholas Piggin [305] = { "HSPRG1", 64, HV_RW, }, 2078f6290f0SNicholas Piggin [306] = { "HDSISR", 32, HV_RW, SPR_INT, }, 2088f6290f0SNicholas Piggin [307] = { "HDAR", 64, HV_RW, SPR_INT, }, 2098f6290f0SNicholas Piggin [308] = { "SPURR", 64, HV_RW | OS_RO, SPR_ASYNC, }, 2108f6290f0SNicholas Piggin [309] = { "PURR", 64, HV_RW | OS_RO, SPR_ASYNC, }, 211584c6ad4SNicholas Piggin [313] = { "HRMOR", 64, HV_RW, SPR_HARNESS, }, /* Harness can't cope with HRMOR changing */ 2128f6290f0SNicholas Piggin [314] = { "HSRR0", 64, HV_RW, SPR_INT, }, 2138f6290f0SNicholas Piggin [315] = { "HSRR1", 64, HV_RW, SPR_INT, }, 2148f6290f0SNicholas Piggin [318] = { "LPCR", 64, HV_RW, }, 2158f6290f0SNicholas Piggin [319] = { "LPIDR", 32, HV_RW, }, 2168f6290f0SNicholas Piggin [336] = { "HMER", 64, HV_RW, }, 2178f6290f0SNicholas Piggin [337] = { "HMEER", 64, HV_RW, }, 2188f6290f0SNicholas Piggin [338] = { "PCR", 64, HV_RW, }, 2198f6290f0SNicholas Piggin [349] = { "AMOR", 64, HV_RW, }, 2208f6290f0SNicholas Piggin [446] = { "TIR", 64, OS_RO, }, 2218f6290f0SNicholas Piggin [800] = { "BESCRS", 64, RW, }, 2228f6290f0SNicholas Piggin [801] = { "BESCRSU", 32, RW, }, 2238f6290f0SNicholas Piggin [802] = { "BESCRR", 64, RW, }, 2248f6290f0SNicholas Piggin [803] = { "BESCRRU", 32, RW, }, 2258f6290f0SNicholas Piggin [804] = { "EBBHR", 64, RW, }, 2268f6290f0SNicholas Piggin [805] = { "EBBRR", 64, RW, }, 2278f6290f0SNicholas Piggin [806] = { "BESCR", 64, RW, }, 2288f6290f0SNicholas Piggin [815] = { "TAR", 64, RW, }, 2298f6290f0SNicholas Piggin [848] = { "IC", 64, HV_RW | OS_RO, SPR_ASYNC, }, 2308f6290f0SNicholas Piggin [849] = { "VTB", 64, HV_RW | OS_RO, SPR_ASYNC, }, 231*cc2ece41SNicholas Piggin [896] = { "PPR", 64, RW, SPR_ASYNC, }, /* PPR(32) is changed by cpu_relax(), appears to be async */ 232*cc2ece41SNicholas Piggin [898] = { "PPR32", 32, RW, SPR_ASYNC, }, 2338f6290f0SNicholas Piggin [1023]= { "PIR", 32, OS_RO, SPR_ASYNC, }, /* Can't be virtualised, appears to be async */ 2348f6290f0SNicholas Piggin }; 2358f6290f0SNicholas Piggin 2368f6290f0SNicholas Piggin static const struct spr sprs_tm[1024] = { 2378f6290f0SNicholas Piggin #if 0 2388f6290f0SNicholas Piggin /* XXX: leave these out until enabling TM facility (and more testing) */ 2398f6290f0SNicholas Piggin [128] = { "TFHAR", 64, RW, }, 2408f6290f0SNicholas Piggin [129] = { "TFIAR", 64, RW, }, 2418f6290f0SNicholas Piggin [130] = { "TEXASR", 64, RW, }, 2428f6290f0SNicholas Piggin [131] = { "TEXASRU", 32, RW, }, 2438f6290f0SNicholas Piggin #endif 2448f6290f0SNicholas Piggin }; 245ee30cf14SThomas Huth 246ee30cf14SThomas Huth /* SPRs from PowerISA 2.07 Book III-S */ 2478f6290f0SNicholas Piggin static const struct spr sprs_207[1024] = { 2488f6290f0SNicholas Piggin [22] = { "DEC", 32, OS_RW, SPR_ASYNC, }, 2498f6290f0SNicholas Piggin [25] = { "SDR1", 64, HV_RW, }, 2508f6290f0SNicholas Piggin [177] = { "DHDES", 64, HV_RW, }, 2518f6290f0SNicholas Piggin [283] = { "CIR", 32, OS_RO, }, 2528f6290f0SNicholas Piggin [310] = { "HDEC", 32, HV_RW, SPR_ASYNC, }, 2538f6290f0SNicholas Piggin [312] = { "RMOR", 64, HV_RW, }, 2548f6290f0SNicholas Piggin [339] = { "HEIR", 32, HV_RW, SPR_INT, }, 2558f6290f0SNicholas Piggin }; 256ee30cf14SThomas Huth 25725a302cbSThomas Huth /* SPRs from PowerISA 3.00 Book III */ 2588f6290f0SNicholas Piggin static const struct spr sprs_300[1024] = { 2598f6290f0SNicholas Piggin [22] = { "DEC", 64, OS_RW, SPR_ASYNC, }, 2608f6290f0SNicholas Piggin [48] = { "PIDR", 32, OS_RW, }, 2618f6290f0SNicholas Piggin [144] = { "TIDR", 64, OS_RW, }, 2628f6290f0SNicholas Piggin [283] = { "CIR", 32, OS_RO, }, 2638f6290f0SNicholas Piggin [310] = { "HDEC", 64, HV_RW, SPR_ASYNC, }, 2648f6290f0SNicholas Piggin [339] = { "HEIR", 32, HV_RW, SPR_INT, }, 2658f6290f0SNicholas Piggin [464] = { "PTCR", 64, HV_RW, }, 2668f6290f0SNicholas Piggin [816] = { "ASDR", 64, HV_RW, SPR_INT, }, 2678f6290f0SNicholas Piggin [823] = { "PSSCR", 64, OS_RW, }, 2688f6290f0SNicholas Piggin [855] = { "PSSCR", 64, HV_RW, }, 2698f6290f0SNicholas Piggin }; 27025a302cbSThomas Huth 2718f6290f0SNicholas Piggin /* SPRs from PowerISA 3.1B Book III */ 2728f6290f0SNicholas Piggin static const struct spr sprs_31[1024] = { 2738f6290f0SNicholas Piggin [22] = { "DEC", 64, OS_RW, SPR_ASYNC, }, 2748f6290f0SNicholas Piggin [48] = { "PIDR", 32, OS_RW, }, 2758f6290f0SNicholas Piggin [181] = { "DAWR1", 64, HV_RW, }, 2768f6290f0SNicholas Piggin [189] = { "DAWRX1", 32, HV_RW, }, 2778f6290f0SNicholas Piggin [310] = { "HDEC", 64, HV_RW, SPR_ASYNC, }, 2788f6290f0SNicholas Piggin [339] = { "HEIR", 64, HV_RW, SPR_INT, }, 2798f6290f0SNicholas Piggin [455] = { "HDEXCR", 32, RO, }, 2808f6290f0SNicholas Piggin [464] = { "PTCR", 64, HV_RW, }, 2818f6290f0SNicholas Piggin [468] = { "HASHKEYR", 64, OS_RW, }, 2828f6290f0SNicholas Piggin [469] = { "HASHPKEYR", 64, HV_RW, }, 2838f6290f0SNicholas Piggin [471] = { "HDEXCR", 64, HV_RW, }, 2848f6290f0SNicholas Piggin [812] = { "DEXCR", 32, RO, }, 2858f6290f0SNicholas Piggin [816] = { "ASDR", 64, HV_RW, SPR_INT, }, 2868f6290f0SNicholas Piggin [823] = { "PSSCR", 64, OS_RW, }, 2878f6290f0SNicholas Piggin [828] = { "DEXCR", 64, OS_RW, }, 2888f6290f0SNicholas Piggin [855] = { "PSSCR", 64, HV_RW, }, 2898f6290f0SNicholas Piggin }; 290faaddcb0SNicholas Piggin 2918f6290f0SNicholas Piggin /* SPRs POWER9, POWER10 User Manual */ 2928f6290f0SNicholas Piggin static const struct spr sprs_power9_10[1024] = { 2938f6290f0SNicholas Piggin [276] = { "SPRC", 64, HV_RW, }, 2948f6290f0SNicholas Piggin [277] = { "SPRD", 64, HV_RW, }, 2958f6290f0SNicholas Piggin [317] = { "TFMR", 64, HV_RW, }, 2968f6290f0SNicholas Piggin [799] = { "IMC", 64, HV_RW, }, 2978f6290f0SNicholas Piggin [850] = { "LDBAR", 64, HV_RO, }, 2988f6290f0SNicholas Piggin [851] = { "MMCRC", 32, HV_RW, }, 2998f6290f0SNicholas Piggin [853] = { "PMSR", 32, HV_RO, }, 3008f6290f0SNicholas Piggin [861] = { "L2QOSR", 64, HV_WO, }, 3018f6290f0SNicholas Piggin [881] = { "TRIG1", 64, OS_WO, }, 3028f6290f0SNicholas Piggin [882] = { "TRIG2", 64, OS_WO, }, 3038f6290f0SNicholas Piggin [884] = { "PMCR", 64, HV_RW, }, 3048f6290f0SNicholas Piggin [885] = { "RWMR", 64, HV_RW, }, 3058f6290f0SNicholas Piggin [895] = { "WORT", 64, OS_RW, }, /* UM says 18-bits! */ 3068f6290f0SNicholas Piggin [921] = { "TSCR", 32, HV_RW, }, 3078f6290f0SNicholas Piggin [922] = { "TTR", 64, HV_RW, }, 3088f6290f0SNicholas Piggin [1006]= { "TRACE", 64, WO, }, 309584c6ad4SNicholas Piggin [1008]= { "HID", 64, HV_RW, SPR_HARNESS, }, /* HILE would be unhelpful to change */ 3108f6290f0SNicholas Piggin }; 3118f6290f0SNicholas Piggin 3128f6290f0SNicholas Piggin /* This covers POWER8 and POWER9 PMUs */ 3138f6290f0SNicholas Piggin static const struct spr sprs_power_common_pmu[1024] = { 3148f6290f0SNicholas Piggin [768] = { "SIER", 64, RO, }, 3158f6290f0SNicholas Piggin [769] = { "MMCR2", 64, RW, }, 3168f6290f0SNicholas Piggin [770] = { "MMCRA", 64, RW, }, 3178f6290f0SNicholas Piggin [771] = { "PMC1", 32, RW, }, 3188f6290f0SNicholas Piggin [772] = { "PMC2", 32, RW, }, 3198f6290f0SNicholas Piggin [773] = { "PMC3", 32, RW, }, 3208f6290f0SNicholas Piggin [774] = { "PMC4", 32, RW, }, 3218f6290f0SNicholas Piggin [775] = { "PMC5", 32, RW, }, 3228f6290f0SNicholas Piggin [776] = { "PMC6", 32, RW, }, 3238f6290f0SNicholas Piggin [779] = { "MMCR0", 64, RW, }, 3248f6290f0SNicholas Piggin [780] = { "SIAR", 64, RO, }, 3258f6290f0SNicholas Piggin [781] = { "SDAR", 64, RO, }, 3268f6290f0SNicholas Piggin [782] = { "MMCR1", 64, RO, }, 3278f6290f0SNicholas Piggin [784] = { "SIER", 64, OS_RW, }, 3288f6290f0SNicholas Piggin [785] = { "MMCR2", 64, OS_RW, }, 3298f6290f0SNicholas Piggin [786] = { "MMCRA", 64, OS_RW, }, 3308f6290f0SNicholas Piggin [787] = { "PMC1", 32, OS_RW, }, 3318f6290f0SNicholas Piggin [788] = { "PMC2", 32, OS_RW, }, 3328f6290f0SNicholas Piggin [789] = { "PMC3", 32, OS_RW, }, 3338f6290f0SNicholas Piggin [790] = { "PMC4", 32, OS_RW, }, 3348f6290f0SNicholas Piggin [791] = { "PMC5", 32, OS_RW, }, 3358f6290f0SNicholas Piggin [792] = { "PMC6", 32, OS_RW, }, 3368f6290f0SNicholas Piggin [795] = { "MMCR0", 64, OS_RW, }, 3378f6290f0SNicholas Piggin [796] = { "SIAR", 64, OS_RW, }, 3388f6290f0SNicholas Piggin [797] = { "SDAR", 64, OS_RW, }, 3398f6290f0SNicholas Piggin [798] = { "MMCR1", 64, OS_RW, }, 3408f6290f0SNicholas Piggin }; 3418f6290f0SNicholas Piggin 3428f6290f0SNicholas Piggin static const struct spr sprs_power10_pmu[1024] = { 3438f6290f0SNicholas Piggin [736] = { "SIER2", 64, RO, }, 3448f6290f0SNicholas Piggin [737] = { "SIER3", 64, RO, }, 3458f6290f0SNicholas Piggin [738] = { "MMCR3", 64, RO, }, 3468f6290f0SNicholas Piggin [752] = { "SIER2", 64, OS_RW, }, 3478f6290f0SNicholas Piggin [753] = { "SIER3", 64, OS_RW, }, 3488f6290f0SNicholas Piggin [754] = { "MMCR3", 64, OS_RW, }, 3498f6290f0SNicholas Piggin }; 3508f6290f0SNicholas Piggin 3518f6290f0SNicholas Piggin static struct spr sprs[1024]; 3528f6290f0SNicholas Piggin 353584c6ad4SNicholas Piggin static bool spr_read_perms(int spr) 354584c6ad4SNicholas Piggin { 355584c6ad4SNicholas Piggin if (cpu_has_hv) 356584c6ad4SNicholas Piggin return !!(sprs[spr].access & SPR_HV_READ); 357584c6ad4SNicholas Piggin else 358584c6ad4SNicholas Piggin return !!(sprs[spr].access & SPR_OS_READ); 359584c6ad4SNicholas Piggin } 360584c6ad4SNicholas Piggin 361584c6ad4SNicholas Piggin static bool spr_write_perms(int spr) 362584c6ad4SNicholas Piggin { 363584c6ad4SNicholas Piggin if (cpu_has_hv) 364584c6ad4SNicholas Piggin return !!(sprs[spr].access & SPR_HV_WRITE); 365584c6ad4SNicholas Piggin else 366584c6ad4SNicholas Piggin return !!(sprs[spr].access & SPR_OS_WRITE); 367584c6ad4SNicholas Piggin } 368584c6ad4SNicholas Piggin 3698f6290f0SNicholas Piggin static void setup_sprs(void) 370ee30cf14SThomas Huth { 3718f6290f0SNicholas Piggin int i; 3728f6290f0SNicholas Piggin 3738f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 3748f6290f0SNicholas Piggin if (sprs_common[i].name) { 3758f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_common[i], sizeof(struct spr)); 3768f6290f0SNicholas Piggin } 3778f6290f0SNicholas Piggin } 378ee30cf14SThomas Huth 3799c5e1913SNicholas Piggin switch (mfspr(SPR_PVR) & PVR_VERSION_MASK) { 3809c5e1913SNicholas Piggin case PVR_VER_970: 3819c5e1913SNicholas Piggin case PVR_VER_970FX: 3829c5e1913SNicholas Piggin case PVR_VER_970MP: 3838f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 3848f6290f0SNicholas Piggin if (sprs_201[i].name) { 3858f6290f0SNicholas Piggin assert(!sprs[i].name); 3868f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_201[i], sizeof(struct spr)); 3878f6290f0SNicholas Piggin } 3888f6290f0SNicholas Piggin if (sprs_970_pmu[i].name) { 3898f6290f0SNicholas Piggin assert(!sprs[i].name); 3908f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 3918f6290f0SNicholas Piggin } 3928f6290f0SNicholas Piggin } 393ee30cf14SThomas Huth break; 3948f6290f0SNicholas Piggin 3959c5e1913SNicholas Piggin case PVR_VER_POWER8E: 3969c5e1913SNicholas Piggin case PVR_VER_POWER8NVL: 3979c5e1913SNicholas Piggin case PVR_VER_POWER8: 3988f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 3998f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 4008f6290f0SNicholas Piggin assert(!sprs[i].name); 4018f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 4028f6290f0SNicholas Piggin } 4038f6290f0SNicholas Piggin if (sprs_207[i].name) { 4048f6290f0SNicholas Piggin assert(!sprs[i].name); 4058f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_207[i], sizeof(struct spr)); 4068f6290f0SNicholas Piggin } 4078f6290f0SNicholas Piggin if (sprs_tm[i].name) { 4088f6290f0SNicholas Piggin assert(!sprs[i].name); 4098f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr)); 4108f6290f0SNicholas Piggin } 4118f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 4128f6290f0SNicholas Piggin assert(!sprs[i].name); 4138f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 4148f6290f0SNicholas Piggin } 4158f6290f0SNicholas Piggin } 416ee30cf14SThomas Huth break; 4178f6290f0SNicholas Piggin 4189c5e1913SNicholas Piggin case PVR_VER_POWER9: 4198f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 4208f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 4218f6290f0SNicholas Piggin assert(!sprs[i].name); 4228f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 4238f6290f0SNicholas Piggin } 4248f6290f0SNicholas Piggin if (sprs_300[i].name) { 4258f6290f0SNicholas Piggin assert(!sprs[i].name); 4268f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_300[i], sizeof(struct spr)); 4278f6290f0SNicholas Piggin } 4288f6290f0SNicholas Piggin if (sprs_tm[i].name) { 4298f6290f0SNicholas Piggin assert(!sprs[i].name); 4308f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr)); 4318f6290f0SNicholas Piggin } 4328f6290f0SNicholas Piggin if (sprs_power9_10[i].name) { 4338f6290f0SNicholas Piggin assert(!sprs[i].name); 4348f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr)); 4358f6290f0SNicholas Piggin } 4368f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 4378f6290f0SNicholas Piggin assert(!sprs[i].name); 4388f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 4398f6290f0SNicholas Piggin } 4408f6290f0SNicholas Piggin } 44125a302cbSThomas Huth break; 4428f6290f0SNicholas Piggin 4439c5e1913SNicholas Piggin case PVR_VER_POWER10: 4448f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 4458f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 4468f6290f0SNicholas Piggin assert(!sprs[i].name); 4478f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 4488f6290f0SNicholas Piggin } 4498f6290f0SNicholas Piggin if (sprs_31[i].name) { 4508f6290f0SNicholas Piggin assert(!sprs[i].name); 4518f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_31[i], sizeof(struct spr)); 4528f6290f0SNicholas Piggin } 4538f6290f0SNicholas Piggin if (sprs_power9_10[i].name) { 4548f6290f0SNicholas Piggin assert(!sprs[i].name); 4558f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr)); 4568f6290f0SNicholas Piggin } 4578f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 4588f6290f0SNicholas Piggin assert(!sprs[i].name); 4598f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 4608f6290f0SNicholas Piggin } 4618f6290f0SNicholas Piggin if (sprs_power10_pmu[i].name) { 4628f6290f0SNicholas Piggin assert(!sprs[i].name); 4638f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power10_pmu[i], sizeof(struct spr)); 4648f6290f0SNicholas Piggin } 4658f6290f0SNicholas Piggin } 466faaddcb0SNicholas Piggin break; 4678f6290f0SNicholas Piggin 468ee30cf14SThomas Huth default: 4698f6290f0SNicholas Piggin memcpy(sprs, sprs_common, sizeof(sprs)); 4708f6290f0SNicholas Piggin puts("Warning: Unknown processor version, falling back to common SPRs!\n"); 4718f6290f0SNicholas Piggin break; 472ee30cf14SThomas Huth } 473ee30cf14SThomas Huth } 474ee30cf14SThomas Huth 475ee30cf14SThomas Huth static void get_sprs(uint64_t *v) 476ee30cf14SThomas Huth { 4778f6290f0SNicholas Piggin int i; 478ee30cf14SThomas Huth 4798f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 480584c6ad4SNicholas Piggin if (!spr_read_perms(i)) 4818f6290f0SNicholas Piggin continue; 4828f6290f0SNicholas Piggin v[i] = __mfspr(i); 4838f6290f0SNicholas Piggin } 4848f6290f0SNicholas Piggin } 485ee30cf14SThomas Huth 4868f6290f0SNicholas Piggin static void set_sprs(uint64_t val) 4878f6290f0SNicholas Piggin { 4888f6290f0SNicholas Piggin int i; 4898f6290f0SNicholas Piggin 4908f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 491584c6ad4SNicholas Piggin if (!spr_write_perms(i)) 4928f6290f0SNicholas Piggin continue; 493584c6ad4SNicholas Piggin 4948f6290f0SNicholas Piggin if (sprs[i].type & SPR_HARNESS) 4958f6290f0SNicholas Piggin continue; 4968f6290f0SNicholas Piggin __mtspr(i, val); 4978f6290f0SNicholas Piggin } 498ee30cf14SThomas Huth } 499ee30cf14SThomas Huth 500ee30cf14SThomas Huth int main(int argc, char **argv) 501ee30cf14SThomas Huth { 502ee30cf14SThomas Huth int i; 503ee30cf14SThomas Huth bool pause = false; 504ee30cf14SThomas Huth uint64_t pat = 0xcafefacec0debabeULL; 505ee30cf14SThomas Huth const uint64_t patterns[] = { 506ee30cf14SThomas Huth 0xcafefacec0debabeULL, ~0xcafefacec0debabeULL, 507ee30cf14SThomas Huth 0xAAAA5555AAAA5555ULL, 0x5555AAAA5555AAAAULL, 508ee30cf14SThomas Huth 0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL, 509ee30cf14SThomas Huth -1ULL, 510ee30cf14SThomas Huth }; 511ee30cf14SThomas Huth 512ee30cf14SThomas Huth for (i = 1; i < argc; i++) { 513ee30cf14SThomas Huth if (!strcmp(argv[i], "-w")) { 514ee30cf14SThomas Huth pause = true; 515ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-p")) { 516ee30cf14SThomas Huth i += 1; 517ee30cf14SThomas Huth if (i >= argc || *argv[i] < '0' 518ee30cf14SThomas Huth || *argv[i] >= '0' + ARRAY_SIZE(patterns)) 519ee30cf14SThomas Huth report_abort("Error: bad value for -p"); 520ee30cf14SThomas Huth pat ^= patterns[*argv[i] - '0']; 521ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-t")) { 522ee30cf14SThomas Huth /* Randomize with timebase register */ 523ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 524ee30cf14SThomas Huth pat ^= i; 525ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 526ee30cf14SThomas Huth pat ^= ~(uint64_t)i << 32; 527ee30cf14SThomas Huth } else { 528ee30cf14SThomas Huth report_abort("Warning: Unsupported argument: %s", 529ee30cf14SThomas Huth argv[i]); 530ee30cf14SThomas Huth } 531ee30cf14SThomas Huth } 532ee30cf14SThomas Huth 5338f6290f0SNicholas Piggin setup_sprs(); 5348f6290f0SNicholas Piggin 5358f6290f0SNicholas Piggin printf("Setting SPRs to 0x%lx...\n", pat); 536ee30cf14SThomas Huth set_sprs(pat); 537ee30cf14SThomas Huth 538ee30cf14SThomas Huth memset(before, 0, sizeof(before)); 539ee30cf14SThomas Huth memset(after, 0, sizeof(after)); 540ee30cf14SThomas Huth 541ee30cf14SThomas Huth get_sprs(before); 542ee30cf14SThomas Huth 543ee30cf14SThomas Huth if (pause) { 54477a59d17SNico Boehr migrate_once(); 5458f6290f0SNicholas Piggin /* Reload regs changed by getchar/putchar hcalls */ 5468f6290f0SNicholas Piggin before[SPR_SRR0] = mfspr(SPR_SRR0); 5478f6290f0SNicholas Piggin before[SPR_SRR1] = mfspr(SPR_SRR1); 5488f6290f0SNicholas Piggin 5498f6290f0SNicholas Piggin /* WORT seems to go to 0 after KVM switch, perhaps CPU idle */ 5508f6290f0SNicholas Piggin if (sprs[895].name) 5518f6290f0SNicholas Piggin before[895] = mfspr(895); 552ee30cf14SThomas Huth } else { 553d499b05fSNicholas Piggin /* 554d499b05fSNicholas Piggin * msleep will enable MSR[EE] and take a decrementer 555d499b05fSNicholas Piggin * interrupt. Must account for changed registers and 556d499b05fSNicholas Piggin * prevent taking unhandled interrupts. 557d499b05fSNicholas Piggin */ 558d499b05fSNicholas Piggin /* Prevent PMU interrupt */ 559d499b05fSNicholas Piggin mtspr(SPR_MMCR0, (mfspr(SPR_MMCR0) | MMCR0_FC) & 560d499b05fSNicholas Piggin ~(MMCR0_PMAO | MMCR0_PMAE)); 561d499b05fSNicholas Piggin before[SPR_MMCR0] = mfspr(SPR_MMCR0); 562d499b05fSNicholas Piggin before[779] = mfspr(SPR_MMCR0); 563ba33a96fSNicholas Piggin msleep(2000); 5648f6290f0SNicholas Piggin 5658f6290f0SNicholas Piggin /* Reload regs changed by dec interrupt */ 5668f6290f0SNicholas Piggin before[SPR_SRR0] = mfspr(SPR_SRR0); 5678f6290f0SNicholas Piggin before[SPR_SRR1] = mfspr(SPR_SRR1); 5688f6290f0SNicholas Piggin before[SPR_SPRG1] = mfspr(SPR_SPRG1); 5698f6290f0SNicholas Piggin 5708f6290f0SNicholas Piggin /* WORT seems to go to 0 after KVM switch, perhaps CPU idle */ 5718f6290f0SNicholas Piggin if (sprs[895].name) 5728f6290f0SNicholas Piggin before[895] = mfspr(895); 573ee30cf14SThomas Huth } 574ee30cf14SThomas Huth 575ee30cf14SThomas Huth get_sprs(after); 576ee30cf14SThomas Huth 577ee30cf14SThomas Huth puts("Checking SPRs...\n"); 578ee30cf14SThomas Huth for (i = 0; i < 1024; i++) { 5798f6290f0SNicholas Piggin bool pass = true; 5808f6290f0SNicholas Piggin 581584c6ad4SNicholas Piggin if (!spr_read_perms(i)) 5828f6290f0SNicholas Piggin continue; 5838f6290f0SNicholas Piggin 5848f6290f0SNicholas Piggin if (sprs[i].width == 32) { 5858f6290f0SNicholas Piggin if (before[i] >> 32) 5868f6290f0SNicholas Piggin pass = false; 5878f6290f0SNicholas Piggin } 5888f6290f0SNicholas Piggin if (!(sprs[i].type & (SPR_HARNESS|SPR_ASYNC)) && (before[i] != after[i])) 5898f6290f0SNicholas Piggin pass = false; 5908f6290f0SNicholas Piggin 5918f6290f0SNicholas Piggin if (sprs[i].width == 32 && !(before[i] >> 32) && !(after[i] >> 32)) { 5928f6290f0SNicholas Piggin /* known failure KVM migration of CTRL */ 593eb2d4443SNicholas Piggin report_kfail(i == 136, pass, 5948f6290f0SNicholas Piggin "%-10s(%4d):\t 0x%08lx <==> 0x%08lx", 5958f6290f0SNicholas Piggin sprs[i].name, i, 5968f6290f0SNicholas Piggin before[i], after[i]); 5978f6290f0SNicholas Piggin } else { 5988f6290f0SNicholas Piggin report(pass, "%-10s(%4d):\t0x%016lx <==> 0x%016lx", 5998f6290f0SNicholas Piggin sprs[i].name, i, 6008f6290f0SNicholas Piggin before[i], after[i]); 6018f6290f0SNicholas Piggin } 602ee30cf14SThomas Huth } 603ee30cf14SThomas Huth 604ee30cf14SThomas Huth return report_summary(); 605ee30cf14SThomas Huth } 606