11e8a1faeSThomas Huth /*
21e8a1faeSThomas Huth * QTest testcase for PowerNV XSCOM bus
31e8a1faeSThomas Huth *
41e8a1faeSThomas Huth * Copyright (c) 2016, IBM Corporation.
51e8a1faeSThomas Huth *
61e8a1faeSThomas Huth * This work is licensed under the terms of the GNU GPL, version 2 or
71e8a1faeSThomas Huth * later. See the COPYING file in the top-level directory.
81e8a1faeSThomas Huth */
91e8a1faeSThomas Huth #include "qemu/osdep.h"
101e8a1faeSThomas Huth
11907b5105SMarc-André Lureau #include "libqtest.h"
121e8a1faeSThomas Huth
131e8a1faeSThomas Huth typedef enum PnvChipType {
141e8a1faeSThomas Huth PNV_CHIP_POWER8E, /* AKA Murano (default) */
151e8a1faeSThomas Huth PNV_CHIP_POWER8, /* AKA Venice */
161e8a1faeSThomas Huth PNV_CHIP_POWER8NVL, /* AKA Naples */
171e8a1faeSThomas Huth PNV_CHIP_POWER9, /* AKA Nimbus */
18*e1a821d4SNicholas Piggin PNV_CHIP_POWER10,
191e8a1faeSThomas Huth } PnvChipType;
201e8a1faeSThomas Huth
211e8a1faeSThomas Huth typedef struct PnvChip {
221e8a1faeSThomas Huth PnvChipType chip_type;
231e8a1faeSThomas Huth const char *cpu_model;
241e8a1faeSThomas Huth uint64_t xscom_base;
251e8a1faeSThomas Huth uint64_t cfam_id;
261e8a1faeSThomas Huth uint32_t first_core;
271e8a1faeSThomas Huth } PnvChip;
281e8a1faeSThomas Huth
291e8a1faeSThomas Huth static const PnvChip pnv_chips[] = {
301e8a1faeSThomas Huth {
311e8a1faeSThomas Huth .chip_type = PNV_CHIP_POWER8,
321e8a1faeSThomas Huth .cpu_model = "POWER8",
331e8a1faeSThomas Huth .xscom_base = 0x0003fc0000000000ull,
341e8a1faeSThomas Huth .cfam_id = 0x220ea04980000000ull,
351e8a1faeSThomas Huth .first_core = 0x1,
361e8a1faeSThomas Huth }, {
371e8a1faeSThomas Huth .chip_type = PNV_CHIP_POWER8NVL,
381e8a1faeSThomas Huth .cpu_model = "POWER8NVL",
391e8a1faeSThomas Huth .xscom_base = 0x0003fc0000000000ull,
401e8a1faeSThomas Huth .cfam_id = 0x120d304980000000ull,
411e8a1faeSThomas Huth .first_core = 0x1,
421e8a1faeSThomas Huth },
431e8a1faeSThomas Huth {
441e8a1faeSThomas Huth .chip_type = PNV_CHIP_POWER9,
451e8a1faeSThomas Huth .cpu_model = "POWER9",
461e8a1faeSThomas Huth .xscom_base = 0x000603fc00000000ull,
471e8a1faeSThomas Huth .cfam_id = 0x220d104900008000ull,
481e8a1faeSThomas Huth .first_core = 0x0,
491e8a1faeSThomas Huth },
50*e1a821d4SNicholas Piggin {
51*e1a821d4SNicholas Piggin .chip_type = PNV_CHIP_POWER10,
52*e1a821d4SNicholas Piggin .cpu_model = "POWER10",
53*e1a821d4SNicholas Piggin .xscom_base = 0x000603fc00000000ull,
54*e1a821d4SNicholas Piggin .cfam_id = 0x120da04900008000ull,
55*e1a821d4SNicholas Piggin .first_core = 0x0,
56*e1a821d4SNicholas Piggin },
571e8a1faeSThomas Huth };
581e8a1faeSThomas Huth
pnv_xscom_addr(const PnvChip * chip,uint32_t pcba)591e8a1faeSThomas Huth static uint64_t pnv_xscom_addr(const PnvChip *chip, uint32_t pcba)
601e8a1faeSThomas Huth {
611e8a1faeSThomas Huth uint64_t addr = chip->xscom_base;
621e8a1faeSThomas Huth
63*e1a821d4SNicholas Piggin if (chip->chip_type == PNV_CHIP_POWER10) {
64*e1a821d4SNicholas Piggin addr |= ((uint64_t) pcba << 3);
65*e1a821d4SNicholas Piggin } else if (chip->chip_type == PNV_CHIP_POWER9) {
661e8a1faeSThomas Huth addr |= ((uint64_t) pcba << 3);
671e8a1faeSThomas Huth } else {
681e8a1faeSThomas Huth addr |= (((uint64_t) pcba << 4) & ~0xffull) |
691e8a1faeSThomas Huth (((uint64_t) pcba << 3) & 0x78);
701e8a1faeSThomas Huth }
711e8a1faeSThomas Huth return addr;
721e8a1faeSThomas Huth }
731e8a1faeSThomas Huth
pnv_xscom_read(QTestState * qts,const PnvChip * chip,uint32_t pcba)741e8a1faeSThomas Huth static uint64_t pnv_xscom_read(QTestState *qts, const PnvChip *chip,
751e8a1faeSThomas Huth uint32_t pcba)
761e8a1faeSThomas Huth {
771e8a1faeSThomas Huth return qtest_readq(qts, pnv_xscom_addr(chip, pcba));
781e8a1faeSThomas Huth }
791e8a1faeSThomas Huth
test_xscom_cfam_id(QTestState * qts,const PnvChip * chip)801e8a1faeSThomas Huth static void test_xscom_cfam_id(QTestState *qts, const PnvChip *chip)
811e8a1faeSThomas Huth {
821e8a1faeSThomas Huth uint64_t f000f = pnv_xscom_read(qts, chip, 0xf000f);
831e8a1faeSThomas Huth
841e8a1faeSThomas Huth g_assert_cmphex(f000f, ==, chip->cfam_id);
851e8a1faeSThomas Huth }
861e8a1faeSThomas Huth
test_cfam_id(const void * data)871e8a1faeSThomas Huth static void test_cfam_id(const void *data)
881e8a1faeSThomas Huth {
891e8a1faeSThomas Huth const PnvChip *chip = data;
901e8a1faeSThomas Huth const char *machine = "powernv8";
911e8a1faeSThomas Huth QTestState *qts;
921e8a1faeSThomas Huth
931e8a1faeSThomas Huth if (chip->chip_type == PNV_CHIP_POWER9) {
941e8a1faeSThomas Huth machine = "powernv9";
95*e1a821d4SNicholas Piggin } else if (chip->chip_type == PNV_CHIP_POWER10) {
96*e1a821d4SNicholas Piggin machine = "powernv10";
971e8a1faeSThomas Huth }
981e8a1faeSThomas Huth
991e8a1faeSThomas Huth qts = qtest_initf("-M %s -accel tcg -cpu %s",
1001e8a1faeSThomas Huth machine, chip->cpu_model);
1011e8a1faeSThomas Huth test_xscom_cfam_id(qts, chip);
1021e8a1faeSThomas Huth qtest_quit(qts);
1031e8a1faeSThomas Huth }
1041e8a1faeSThomas Huth
1051e8a1faeSThomas Huth
1061e8a1faeSThomas Huth #define PNV_XSCOM_EX_CORE_BASE 0x10000000ull
1071e8a1faeSThomas Huth #define PNV_XSCOM_EX_BASE(core) \
1081e8a1faeSThomas Huth (PNV_XSCOM_EX_CORE_BASE | ((uint64_t)(core) << 24))
1091e8a1faeSThomas Huth #define PNV_XSCOM_P9_EC_BASE(core) \
1101e8a1faeSThomas Huth ((uint64_t)(((core) & 0x1F) + 0x20) << 24)
111*e1a821d4SNicholas Piggin #define PNV_XSCOM_P10_EC_BASE(core) \
112*e1a821d4SNicholas Piggin ((uint64_t)((((core) & ~0x3) + 0x20) << 24) + 0x20000 + \
113*e1a821d4SNicholas Piggin (0x1000 << (3 - (core & 0x3))))
1141e8a1faeSThomas Huth
1151e8a1faeSThomas Huth #define PNV_XSCOM_EX_DTS_RESULT0 0x50000
1161e8a1faeSThomas Huth
test_xscom_core(QTestState * qts,const PnvChip * chip)1171e8a1faeSThomas Huth static void test_xscom_core(QTestState *qts, const PnvChip *chip)
1181e8a1faeSThomas Huth {
119*e1a821d4SNicholas Piggin if (chip->chip_type == PNV_CHIP_POWER10) {
120*e1a821d4SNicholas Piggin uint32_t first_core_thread_state =
121*e1a821d4SNicholas Piggin PNV_XSCOM_P10_EC_BASE(chip->first_core) + 0x412;
122*e1a821d4SNicholas Piggin uint64_t thread_state;
123*e1a821d4SNicholas Piggin
124*e1a821d4SNicholas Piggin thread_state = pnv_xscom_read(qts, chip, first_core_thread_state);
125*e1a821d4SNicholas Piggin
126*e1a821d4SNicholas Piggin g_assert_cmphex(thread_state, ==, 0);
127*e1a821d4SNicholas Piggin } else {
1281e8a1faeSThomas Huth uint32_t first_core_dts0 = PNV_XSCOM_EX_DTS_RESULT0;
1291e8a1faeSThomas Huth uint64_t dts0;
1301e8a1faeSThomas Huth
131*e1a821d4SNicholas Piggin if (chip->chip_type == PNV_CHIP_POWER9) {
1321e8a1faeSThomas Huth first_core_dts0 |= PNV_XSCOM_P9_EC_BASE(chip->first_core);
133*e1a821d4SNicholas Piggin } else { /* POWER8 */
134*e1a821d4SNicholas Piggin first_core_dts0 |= PNV_XSCOM_EX_BASE(chip->first_core);
1351e8a1faeSThomas Huth }
1361e8a1faeSThomas Huth
1371e8a1faeSThomas Huth dts0 = pnv_xscom_read(qts, chip, first_core_dts0);
1381e8a1faeSThomas Huth
1391e8a1faeSThomas Huth g_assert_cmphex(dts0, ==, 0x26f024f023f0000ull);
1401e8a1faeSThomas Huth }
141*e1a821d4SNicholas Piggin }
1421e8a1faeSThomas Huth
test_core(const void * data)1431e8a1faeSThomas Huth static void test_core(const void *data)
1441e8a1faeSThomas Huth {
1451e8a1faeSThomas Huth const PnvChip *chip = data;
1461e8a1faeSThomas Huth QTestState *qts;
1471e8a1faeSThomas Huth const char *machine = "powernv8";
1481e8a1faeSThomas Huth
1491e8a1faeSThomas Huth if (chip->chip_type == PNV_CHIP_POWER9) {
1501e8a1faeSThomas Huth machine = "powernv9";
151*e1a821d4SNicholas Piggin } else if (chip->chip_type == PNV_CHIP_POWER10) {
152*e1a821d4SNicholas Piggin machine = "powernv10";
1531e8a1faeSThomas Huth }
1541e8a1faeSThomas Huth
1551e8a1faeSThomas Huth qts = qtest_initf("-M %s -accel tcg -cpu %s",
1561e8a1faeSThomas Huth machine, chip->cpu_model);
1571e8a1faeSThomas Huth test_xscom_core(qts, chip);
1581e8a1faeSThomas Huth qtest_quit(qts);
1591e8a1faeSThomas Huth }
1601e8a1faeSThomas Huth
add_test(const char * name,void (* test)(const void * data))1611e8a1faeSThomas Huth static void add_test(const char *name, void (*test)(const void *data))
1621e8a1faeSThomas Huth {
1631e8a1faeSThomas Huth int i;
1641e8a1faeSThomas Huth
1651e8a1faeSThomas Huth for (i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
1661e8a1faeSThomas Huth char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
1671e8a1faeSThomas Huth pnv_chips[i].cpu_model);
1681e8a1faeSThomas Huth qtest_add_data_func(tname, &pnv_chips[i], test);
1691e8a1faeSThomas Huth g_free(tname);
1701e8a1faeSThomas Huth }
1711e8a1faeSThomas Huth }
1721e8a1faeSThomas Huth
main(int argc,char ** argv)1731e8a1faeSThomas Huth int main(int argc, char **argv)
1741e8a1faeSThomas Huth {
1751e8a1faeSThomas Huth g_test_init(&argc, &argv, NULL);
1761e8a1faeSThomas Huth
1771e8a1faeSThomas Huth add_test("cfam_id", test_cfam_id);
1781e8a1faeSThomas Huth add_test("core", test_core);
1791e8a1faeSThomas Huth return g_test_run();
1801e8a1faeSThomas Huth }
181