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, }, 2028f6290f0SNicholas Piggin [284] = { "TBL", 32, HV_WO, }, 2038f6290f0SNicholas Piggin [285] = { "TBU", 32, HV_WO, }, 2048f6290f0SNicholas Piggin [286] = { "TBU40", 64, HV_WO, }, 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, }, 2118f6290f0SNicholas Piggin [313] = { "HRMOR", 64, HV_RW, }, 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, }, 2318f6290f0SNicholas Piggin [896] = { "PPR", 64, RW, }, 2328f6290f0SNicholas Piggin [898] = { "PPR32", 32, RW, }, 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, }, 3098f6290f0SNicholas Piggin [1008]= { "HID", 64, HV_RW, }, 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 3538f6290f0SNicholas Piggin static void setup_sprs(void) 354ee30cf14SThomas Huth { 3558f6290f0SNicholas Piggin int i; 3568f6290f0SNicholas Piggin 3578f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 3588f6290f0SNicholas Piggin if (sprs_common[i].name) { 3598f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_common[i], sizeof(struct spr)); 3608f6290f0SNicholas Piggin } 3618f6290f0SNicholas 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: 3678f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 3688f6290f0SNicholas Piggin if (sprs_201[i].name) { 3698f6290f0SNicholas Piggin assert(!sprs[i].name); 3708f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_201[i], sizeof(struct spr)); 3718f6290f0SNicholas Piggin } 3728f6290f0SNicholas Piggin if (sprs_970_pmu[i].name) { 3738f6290f0SNicholas Piggin assert(!sprs[i].name); 3748f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 3758f6290f0SNicholas Piggin } 3768f6290f0SNicholas Piggin } 377ee30cf14SThomas Huth break; 3788f6290f0SNicholas Piggin 3799c5e1913SNicholas Piggin case PVR_VER_POWER8E: 3809c5e1913SNicholas Piggin case PVR_VER_POWER8NVL: 3819c5e1913SNicholas Piggin case PVR_VER_POWER8: 3828f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 3838f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 3848f6290f0SNicholas Piggin assert(!sprs[i].name); 3858f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 3868f6290f0SNicholas Piggin } 3878f6290f0SNicholas Piggin if (sprs_207[i].name) { 3888f6290f0SNicholas Piggin assert(!sprs[i].name); 3898f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_207[i], sizeof(struct spr)); 3908f6290f0SNicholas Piggin } 3918f6290f0SNicholas Piggin if (sprs_tm[i].name) { 3928f6290f0SNicholas Piggin assert(!sprs[i].name); 3938f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr)); 3948f6290f0SNicholas Piggin } 3958f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 3968f6290f0SNicholas Piggin assert(!sprs[i].name); 3978f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 3988f6290f0SNicholas Piggin } 3998f6290f0SNicholas Piggin } 400ee30cf14SThomas Huth break; 4018f6290f0SNicholas Piggin 4029c5e1913SNicholas Piggin case PVR_VER_POWER9: 4038f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 4048f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 4058f6290f0SNicholas Piggin assert(!sprs[i].name); 4068f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 4078f6290f0SNicholas Piggin } 4088f6290f0SNicholas Piggin if (sprs_300[i].name) { 4098f6290f0SNicholas Piggin assert(!sprs[i].name); 4108f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_300[i], sizeof(struct spr)); 4118f6290f0SNicholas Piggin } 4128f6290f0SNicholas Piggin if (sprs_tm[i].name) { 4138f6290f0SNicholas Piggin assert(!sprs[i].name); 4148f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_tm[i], sizeof(struct spr)); 4158f6290f0SNicholas Piggin } 4168f6290f0SNicholas Piggin if (sprs_power9_10[i].name) { 4178f6290f0SNicholas Piggin assert(!sprs[i].name); 4188f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr)); 4198f6290f0SNicholas Piggin } 4208f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 4218f6290f0SNicholas Piggin assert(!sprs[i].name); 4228f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 4238f6290f0SNicholas Piggin } 4248f6290f0SNicholas Piggin } 42525a302cbSThomas Huth break; 4268f6290f0SNicholas Piggin 4279c5e1913SNicholas Piggin case PVR_VER_POWER10: 4288f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 4298f6290f0SNicholas Piggin if (sprs_power_common[i].name) { 4308f6290f0SNicholas Piggin assert(!sprs[i].name); 4318f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common[i], sizeof(struct spr)); 4328f6290f0SNicholas Piggin } 4338f6290f0SNicholas Piggin if (sprs_31[i].name) { 4348f6290f0SNicholas Piggin assert(!sprs[i].name); 4358f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_31[i], sizeof(struct spr)); 4368f6290f0SNicholas Piggin } 4378f6290f0SNicholas Piggin if (sprs_power9_10[i].name) { 4388f6290f0SNicholas Piggin assert(!sprs[i].name); 4398f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power9_10[i], sizeof(struct spr)); 4408f6290f0SNicholas Piggin } 4418f6290f0SNicholas Piggin if (sprs_power_common_pmu[i].name) { 4428f6290f0SNicholas Piggin assert(!sprs[i].name); 4438f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power_common_pmu[i], sizeof(struct spr)); 4448f6290f0SNicholas Piggin } 4458f6290f0SNicholas Piggin if (sprs_power10_pmu[i].name) { 4468f6290f0SNicholas Piggin assert(!sprs[i].name); 4478f6290f0SNicholas Piggin memcpy(&sprs[i], &sprs_power10_pmu[i], sizeof(struct spr)); 4488f6290f0SNicholas Piggin } 4498f6290f0SNicholas Piggin } 450faaddcb0SNicholas Piggin break; 4518f6290f0SNicholas Piggin 452ee30cf14SThomas Huth default: 4538f6290f0SNicholas Piggin memcpy(sprs, sprs_common, sizeof(sprs)); 4548f6290f0SNicholas Piggin puts("Warning: Unknown processor version, falling back to common SPRs!\n"); 4558f6290f0SNicholas Piggin break; 456ee30cf14SThomas Huth } 457ee30cf14SThomas Huth } 458ee30cf14SThomas Huth 459ee30cf14SThomas Huth static void get_sprs(uint64_t *v) 460ee30cf14SThomas Huth { 4618f6290f0SNicholas Piggin int i; 462ee30cf14SThomas Huth 4638f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 4648f6290f0SNicholas Piggin if (!(sprs[i].access & SPR_OS_READ)) 4658f6290f0SNicholas Piggin continue; 4668f6290f0SNicholas Piggin v[i] = __mfspr(i); 4678f6290f0SNicholas Piggin } 4688f6290f0SNicholas Piggin } 469ee30cf14SThomas Huth 4708f6290f0SNicholas Piggin static void set_sprs(uint64_t val) 4718f6290f0SNicholas Piggin { 4728f6290f0SNicholas Piggin int i; 4738f6290f0SNicholas Piggin 4748f6290f0SNicholas Piggin for (i = 0; i < 1024; i++) { 4758f6290f0SNicholas Piggin if (!(sprs[i].access & SPR_OS_WRITE)) 4768f6290f0SNicholas Piggin continue; 4778f6290f0SNicholas Piggin if (sprs[i].type & SPR_HARNESS) 4788f6290f0SNicholas Piggin continue; 4798f6290f0SNicholas Piggin __mtspr(i, val); 4808f6290f0SNicholas Piggin } 481ee30cf14SThomas Huth } 482ee30cf14SThomas Huth 483ee30cf14SThomas Huth int main(int argc, char **argv) 484ee30cf14SThomas Huth { 485ee30cf14SThomas Huth int i; 486ee30cf14SThomas Huth bool pause = false; 487ee30cf14SThomas Huth uint64_t pat = 0xcafefacec0debabeULL; 488ee30cf14SThomas Huth const uint64_t patterns[] = { 489ee30cf14SThomas Huth 0xcafefacec0debabeULL, ~0xcafefacec0debabeULL, 490ee30cf14SThomas Huth 0xAAAA5555AAAA5555ULL, 0x5555AAAA5555AAAAULL, 491ee30cf14SThomas Huth 0x1234567890ABCDEFULL, 0xFEDCBA0987654321ULL, 492ee30cf14SThomas Huth -1ULL, 493ee30cf14SThomas Huth }; 494ee30cf14SThomas Huth 495ee30cf14SThomas Huth for (i = 1; i < argc; i++) { 496ee30cf14SThomas Huth if (!strcmp(argv[i], "-w")) { 497ee30cf14SThomas Huth pause = true; 498ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-p")) { 499ee30cf14SThomas Huth i += 1; 500ee30cf14SThomas Huth if (i >= argc || *argv[i] < '0' 501ee30cf14SThomas Huth || *argv[i] >= '0' + ARRAY_SIZE(patterns)) 502ee30cf14SThomas Huth report_abort("Error: bad value for -p"); 503ee30cf14SThomas Huth pat ^= patterns[*argv[i] - '0']; 504ee30cf14SThomas Huth } else if (!strcmp(argv[i], "-t")) { 505ee30cf14SThomas Huth /* Randomize with timebase register */ 506ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 507ee30cf14SThomas Huth pat ^= i; 508ee30cf14SThomas Huth asm volatile("mftb %0" : "=r"(i)); 509ee30cf14SThomas Huth pat ^= ~(uint64_t)i << 32; 510ee30cf14SThomas Huth } else { 511ee30cf14SThomas Huth report_abort("Warning: Unsupported argument: %s", 512ee30cf14SThomas Huth argv[i]); 513ee30cf14SThomas Huth } 514ee30cf14SThomas Huth } 515ee30cf14SThomas Huth 5168f6290f0SNicholas Piggin setup_sprs(); 5178f6290f0SNicholas Piggin 5188f6290f0SNicholas Piggin printf("Setting SPRs to 0x%lx...\n", pat); 519ee30cf14SThomas Huth set_sprs(pat); 520ee30cf14SThomas Huth 521ee30cf14SThomas Huth memset(before, 0, sizeof(before)); 522ee30cf14SThomas Huth memset(after, 0, sizeof(after)); 523ee30cf14SThomas Huth 524ee30cf14SThomas Huth get_sprs(before); 525ee30cf14SThomas Huth 526ee30cf14SThomas Huth if (pause) { 52777a59d17SNico Boehr migrate_once(); 5288f6290f0SNicholas Piggin /* Reload regs changed by getchar/putchar hcalls */ 5298f6290f0SNicholas Piggin before[SPR_SRR0] = mfspr(SPR_SRR0); 5308f6290f0SNicholas Piggin before[SPR_SRR1] = mfspr(SPR_SRR1); 5318f6290f0SNicholas Piggin 5328f6290f0SNicholas Piggin /* WORT seems to go to 0 after KVM switch, perhaps CPU idle */ 5338f6290f0SNicholas Piggin if (sprs[895].name) 5348f6290f0SNicholas Piggin before[895] = mfspr(895); 535ee30cf14SThomas Huth } else { 536*d499b05fSNicholas Piggin /* 537*d499b05fSNicholas Piggin * msleep will enable MSR[EE] and take a decrementer 538*d499b05fSNicholas Piggin * interrupt. Must account for changed registers and 539*d499b05fSNicholas Piggin * prevent taking unhandled interrupts. 540*d499b05fSNicholas Piggin */ 541*d499b05fSNicholas Piggin /* Prevent PMU interrupt */ 542*d499b05fSNicholas Piggin mtspr(SPR_MMCR0, (mfspr(SPR_MMCR0) | MMCR0_FC) & 543*d499b05fSNicholas Piggin ~(MMCR0_PMAO | MMCR0_PMAE)); 544*d499b05fSNicholas Piggin before[SPR_MMCR0] = mfspr(SPR_MMCR0); 545*d499b05fSNicholas Piggin before[779] = mfspr(SPR_MMCR0); 546ba33a96fSNicholas Piggin msleep(2000); 5478f6290f0SNicholas Piggin 5488f6290f0SNicholas Piggin /* Reload regs changed by dec interrupt */ 5498f6290f0SNicholas Piggin before[SPR_SRR0] = mfspr(SPR_SRR0); 5508f6290f0SNicholas Piggin before[SPR_SRR1] = mfspr(SPR_SRR1); 5518f6290f0SNicholas Piggin before[SPR_SPRG1] = mfspr(SPR_SPRG1); 5528f6290f0SNicholas Piggin 5538f6290f0SNicholas Piggin /* WORT seems to go to 0 after KVM switch, perhaps CPU idle */ 5548f6290f0SNicholas Piggin if (sprs[895].name) 5558f6290f0SNicholas Piggin before[895] = mfspr(895); 556ee30cf14SThomas Huth } 557ee30cf14SThomas Huth 558ee30cf14SThomas Huth get_sprs(after); 559ee30cf14SThomas Huth 560ee30cf14SThomas Huth puts("Checking SPRs...\n"); 561ee30cf14SThomas Huth for (i = 0; i < 1024; i++) { 5628f6290f0SNicholas Piggin bool pass = true; 5638f6290f0SNicholas Piggin 5648f6290f0SNicholas Piggin if (!(sprs[i].access & SPR_OS_READ)) 5658f6290f0SNicholas Piggin continue; 5668f6290f0SNicholas Piggin 5678f6290f0SNicholas Piggin if (sprs[i].width == 32) { 5688f6290f0SNicholas Piggin if (before[i] >> 32) 5698f6290f0SNicholas Piggin pass = false; 5708f6290f0SNicholas Piggin } 5718f6290f0SNicholas Piggin if (!(sprs[i].type & (SPR_HARNESS|SPR_ASYNC)) && (before[i] != after[i])) 5728f6290f0SNicholas Piggin pass = false; 5738f6290f0SNicholas Piggin 5748f6290f0SNicholas Piggin if (sprs[i].width == 32 && !(before[i] >> 32) && !(after[i] >> 32)) { 5758f6290f0SNicholas Piggin /* known failure KVM migration of CTRL */ 5768f6290f0SNicholas Piggin report_kfail(true && i == 136, 5778f6290f0SNicholas Piggin "%-10s(%4d):\t 0x%08lx <==> 0x%08lx", 5788f6290f0SNicholas Piggin sprs[i].name, i, 5798f6290f0SNicholas Piggin before[i], after[i]); 5808f6290f0SNicholas Piggin } else { 5818f6290f0SNicholas Piggin report(pass, "%-10s(%4d):\t0x%016lx <==> 0x%016lx", 5828f6290f0SNicholas Piggin sprs[i].name, i, 5838f6290f0SNicholas Piggin before[i], after[i]); 5848f6290f0SNicholas Piggin } 585ee30cf14SThomas Huth } 586ee30cf14SThomas Huth 587ee30cf14SThomas Huth return report_summary(); 588ee30cf14SThomas Huth } 589