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 */
__mfspr(unsigned spr)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
__mtspr(unsigned spr,uint64_t val)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, },
231cc2ece41SNicholas Piggin [896] = { "PPR", 64, RW, SPR_ASYNC, }, /* PPR(32) is changed by cpu_relax(), appears to be async */
232cc2ece41SNicholas 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
spr_read_perms(int spr)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
spr_write_perms(int spr)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
setup_sprs(void)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
get_sprs(uint64_t * v)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
set_sprs(uint64_t val)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
main(int argc,char ** argv)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 */
593*851ef516SNicholas Piggin report_kfail(host_is_kvm && 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