18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Copyright 2019 Madhavan Srinivasan, IBM Corporation.
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#define pr_fmt(fmt)	"generic-compat-pmu: " fmt
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "isa207-common.h"
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci/*
108c2ecf20Sopenharmony_ci * Raw event encoding:
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci *        60        56        52        48        44        40        36        32
138c2ecf20Sopenharmony_ci * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci *        28        24        20        16        12         8         4         0
168c2ecf20Sopenharmony_ci * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
178c2ecf20Sopenharmony_ci *                                 [ pmc ]   [unit ]   [ ]   m   [    pmcxsel    ]
188c2ecf20Sopenharmony_ci *                                                     |     |
198c2ecf20Sopenharmony_ci *                                                     |     *- mark
208c2ecf20Sopenharmony_ci *                                                     |
218c2ecf20Sopenharmony_ci *                                                     |
228c2ecf20Sopenharmony_ci *                                                     *- combine
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * Below uses IBM bit numbering.
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * MMCR1[x:y] = unit    (PMCxUNIT)
278c2ecf20Sopenharmony_ci * MMCR1[24]   = pmc1combine[0]
288c2ecf20Sopenharmony_ci * MMCR1[25]   = pmc1combine[1]
298c2ecf20Sopenharmony_ci * MMCR1[26]   = pmc2combine[0]
308c2ecf20Sopenharmony_ci * MMCR1[27]   = pmc2combine[1]
318c2ecf20Sopenharmony_ci * MMCR1[28]   = pmc3combine[0]
328c2ecf20Sopenharmony_ci * MMCR1[29]   = pmc3combine[1]
338c2ecf20Sopenharmony_ci * MMCR1[30]   = pmc4combine[0]
348c2ecf20Sopenharmony_ci * MMCR1[31]   = pmc4combine[1]
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci */
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * Some power9 event codes.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_ci#define EVENT(_name, _code)	_name = _code,
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cienum {
448c2ecf20Sopenharmony_ciEVENT(PM_CYC,					0x0001e)
458c2ecf20Sopenharmony_ciEVENT(PM_INST_CMPL,				0x00002)
468c2ecf20Sopenharmony_ci};
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci#undef EVENT
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciGENERIC_EVENT_ATTR(cpu-cycles,			PM_CYC);
518c2ecf20Sopenharmony_ciGENERIC_EVENT_ATTR(instructions,		PM_INST_CMPL);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic struct attribute *generic_compat_events_attr[] = {
548c2ecf20Sopenharmony_ci	GENERIC_EVENT_PTR(PM_CYC),
558c2ecf20Sopenharmony_ci	GENERIC_EVENT_PTR(PM_INST_CMPL),
568c2ecf20Sopenharmony_ci	NULL
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic struct attribute_group generic_compat_pmu_events_group = {
608c2ecf20Sopenharmony_ci	.name = "events",
618c2ecf20Sopenharmony_ci	.attrs = generic_compat_events_attr,
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(event,		"config:0-19");
658c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(pmcxsel,	"config:0-7");
668c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(mark,		"config:8");
678c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(combine,	"config:10-11");
688c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(unit,		"config:12-15");
698c2ecf20Sopenharmony_ciPMU_FORMAT_ATTR(pmc,		"config:16-19");
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic struct attribute *generic_compat_pmu_format_attr[] = {
728c2ecf20Sopenharmony_ci	&format_attr_event.attr,
738c2ecf20Sopenharmony_ci	&format_attr_pmcxsel.attr,
748c2ecf20Sopenharmony_ci	&format_attr_mark.attr,
758c2ecf20Sopenharmony_ci	&format_attr_combine.attr,
768c2ecf20Sopenharmony_ci	&format_attr_unit.attr,
778c2ecf20Sopenharmony_ci	&format_attr_pmc.attr,
788c2ecf20Sopenharmony_ci	NULL,
798c2ecf20Sopenharmony_ci};
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cistatic struct attribute_group generic_compat_pmu_format_group = {
828c2ecf20Sopenharmony_ci	.name = "format",
838c2ecf20Sopenharmony_ci	.attrs = generic_compat_pmu_format_attr,
848c2ecf20Sopenharmony_ci};
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistatic const struct attribute_group *generic_compat_pmu_attr_groups[] = {
878c2ecf20Sopenharmony_ci	&generic_compat_pmu_format_group,
888c2ecf20Sopenharmony_ci	&generic_compat_pmu_events_group,
898c2ecf20Sopenharmony_ci	NULL,
908c2ecf20Sopenharmony_ci};
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic int compat_generic_events[] = {
938c2ecf20Sopenharmony_ci	[PERF_COUNT_HW_CPU_CYCLES] =			PM_CYC,
948c2ecf20Sopenharmony_ci	[PERF_COUNT_HW_INSTRUCTIONS] =			PM_INST_CMPL,
958c2ecf20Sopenharmony_ci};
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci#define C(x)	PERF_COUNT_HW_CACHE_##x
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci/*
1008c2ecf20Sopenharmony_ci * Table of generalized cache-related events.
1018c2ecf20Sopenharmony_ci * 0 means not supported, -1 means nonsensical, other values
1028c2ecf20Sopenharmony_ci * are event codes.
1038c2ecf20Sopenharmony_ci */
1048c2ecf20Sopenharmony_cistatic u64 generic_compat_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
1058c2ecf20Sopenharmony_ci	[ C(L1D) ] = {
1068c2ecf20Sopenharmony_ci		[ C(OP_READ) ] = {
1078c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1088c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1098c2ecf20Sopenharmony_ci		},
1108c2ecf20Sopenharmony_ci		[ C(OP_WRITE) ] = {
1118c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1128c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1138c2ecf20Sopenharmony_ci		},
1148c2ecf20Sopenharmony_ci		[ C(OP_PREFETCH) ] = {
1158c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1168c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1178c2ecf20Sopenharmony_ci		},
1188c2ecf20Sopenharmony_ci	},
1198c2ecf20Sopenharmony_ci	[ C(L1I) ] = {
1208c2ecf20Sopenharmony_ci		[ C(OP_READ) ] = {
1218c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1228c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1238c2ecf20Sopenharmony_ci		},
1248c2ecf20Sopenharmony_ci		[ C(OP_WRITE) ] = {
1258c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1268c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1278c2ecf20Sopenharmony_ci		},
1288c2ecf20Sopenharmony_ci		[ C(OP_PREFETCH) ] = {
1298c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1308c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1318c2ecf20Sopenharmony_ci		},
1328c2ecf20Sopenharmony_ci	},
1338c2ecf20Sopenharmony_ci	[ C(LL) ] = {
1348c2ecf20Sopenharmony_ci		[ C(OP_READ) ] = {
1358c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1368c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1378c2ecf20Sopenharmony_ci		},
1388c2ecf20Sopenharmony_ci		[ C(OP_WRITE) ] = {
1398c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1408c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1418c2ecf20Sopenharmony_ci		},
1428c2ecf20Sopenharmony_ci		[ C(OP_PREFETCH) ] = {
1438c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1448c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1458c2ecf20Sopenharmony_ci		},
1468c2ecf20Sopenharmony_ci	},
1478c2ecf20Sopenharmony_ci	[ C(DTLB) ] = {
1488c2ecf20Sopenharmony_ci		[ C(OP_READ) ] = {
1498c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1508c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1518c2ecf20Sopenharmony_ci		},
1528c2ecf20Sopenharmony_ci		[ C(OP_WRITE) ] = {
1538c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1548c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1558c2ecf20Sopenharmony_ci		},
1568c2ecf20Sopenharmony_ci		[ C(OP_PREFETCH) ] = {
1578c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1588c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1598c2ecf20Sopenharmony_ci		},
1608c2ecf20Sopenharmony_ci	},
1618c2ecf20Sopenharmony_ci	[ C(ITLB) ] = {
1628c2ecf20Sopenharmony_ci		[ C(OP_READ) ] = {
1638c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1648c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1658c2ecf20Sopenharmony_ci		},
1668c2ecf20Sopenharmony_ci		[ C(OP_WRITE) ] = {
1678c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1688c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1698c2ecf20Sopenharmony_ci		},
1708c2ecf20Sopenharmony_ci		[ C(OP_PREFETCH) ] = {
1718c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1728c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1738c2ecf20Sopenharmony_ci		},
1748c2ecf20Sopenharmony_ci	},
1758c2ecf20Sopenharmony_ci	[ C(BPU) ] = {
1768c2ecf20Sopenharmony_ci		[ C(OP_READ) ] = {
1778c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = 0,
1788c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = 0,
1798c2ecf20Sopenharmony_ci		},
1808c2ecf20Sopenharmony_ci		[ C(OP_WRITE) ] = {
1818c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1828c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1838c2ecf20Sopenharmony_ci		},
1848c2ecf20Sopenharmony_ci		[ C(OP_PREFETCH) ] = {
1858c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1868c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1878c2ecf20Sopenharmony_ci		},
1888c2ecf20Sopenharmony_ci	},
1898c2ecf20Sopenharmony_ci	[ C(NODE) ] = {
1908c2ecf20Sopenharmony_ci		[ C(OP_READ) ] = {
1918c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1928c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1938c2ecf20Sopenharmony_ci		},
1948c2ecf20Sopenharmony_ci		[ C(OP_WRITE) ] = {
1958c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
1968c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
1978c2ecf20Sopenharmony_ci		},
1988c2ecf20Sopenharmony_ci		[ C(OP_PREFETCH) ] = {
1998c2ecf20Sopenharmony_ci			[ C(RESULT_ACCESS) ] = -1,
2008c2ecf20Sopenharmony_ci			[ C(RESULT_MISS)   ] = -1,
2018c2ecf20Sopenharmony_ci		},
2028c2ecf20Sopenharmony_ci	},
2038c2ecf20Sopenharmony_ci};
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci#undef C
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic struct power_pmu generic_compat_pmu = {
2088c2ecf20Sopenharmony_ci	.name			= "GENERIC_COMPAT",
2098c2ecf20Sopenharmony_ci	.n_counter		= MAX_PMU_COUNTERS,
2108c2ecf20Sopenharmony_ci	.add_fields		= ISA207_ADD_FIELDS,
2118c2ecf20Sopenharmony_ci	.test_adder		= ISA207_TEST_ADDER,
2128c2ecf20Sopenharmony_ci	.compute_mmcr		= isa207_compute_mmcr,
2138c2ecf20Sopenharmony_ci	.get_constraint		= isa207_get_constraint,
2148c2ecf20Sopenharmony_ci	.disable_pmc		= isa207_disable_pmc,
2158c2ecf20Sopenharmony_ci	.flags			= PPMU_HAS_SIER | PPMU_ARCH_207S,
2168c2ecf20Sopenharmony_ci	.n_generic		= ARRAY_SIZE(compat_generic_events),
2178c2ecf20Sopenharmony_ci	.generic_events		= compat_generic_events,
2188c2ecf20Sopenharmony_ci	.cache_events		= &generic_compat_cache_events,
2198c2ecf20Sopenharmony_ci	.attr_groups		= generic_compat_pmu_attr_groups,
2208c2ecf20Sopenharmony_ci};
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ciint init_generic_compat_pmu(void)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	int rc = 0;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	rc = register_power_pmu(&generic_compat_pmu);
2278c2ecf20Sopenharmony_ci	if (rc)
2288c2ecf20Sopenharmony_ci		return rc;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* Tell userspace that EBB is supported */
2318c2ecf20Sopenharmony_ci	cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_EBB;
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	return 0;
2348c2ecf20Sopenharmony_ci}
235