11 #include <linux/kernel.h>
12 #include <linux/perf_event.h>
13 #include <linux/string.h>
15 #include <asm/cputable.h>
21 #define PM_PMC_MSK 0xf
22 #define PM_PMC_MSKS (PM_PMC_MSK << PM_PMC_SH)
24 #define PM_UNIT_MSK 0xf
25 #define PM_COMBINE_SH 11
26 #define PM_COMBINE_MSK 1
27 #define PM_COMBINE_MSKS 0x800
29 #define PM_L2SEL_MSK 7
30 #define PM_PMCSEL_MSK 0xff
35 #define MMCR1_TTM0SEL_SH 60
36 #define MMCR1_TTM1SEL_SH 56
37 #define MMCR1_TTM2SEL_SH 52
38 #define MMCR1_TTM3SEL_SH 48
39 #define MMCR1_TTMSEL_MSK 0xf
40 #define MMCR1_L2SEL_SH 45
41 #define MMCR1_L2SEL_MSK 7
42 #define MMCR1_PMC1_COMBINE_SH 35
43 #define MMCR1_PMC2_COMBINE_SH 34
44 #define MMCR1_PMC3_COMBINE_SH 33
45 #define MMCR1_PMC4_COMBINE_SH 32
46 #define MMCR1_PMC1SEL_SH 24
47 #define MMCR1_PMC2SEL_SH 16
48 #define MMCR1_PMC3SEL_SH 8
49 #define MMCR1_PMC4SEL_SH 0
50 #define MMCR1_PMCSEL_SH(n) (MMCR1_PMC1SEL_SH - (n) * 8)
51 #define MMCR1_PMCSEL_MSK 0xff
72 static int power7_get_constraint(
u64 event,
unsigned long *maskp,
85 if (pmc >= 5 && !(event == 0x500fa || event == 0x600f4))
100 static const unsigned int event_alternatives[][
MAX_ALT] = {
101 { 0x200f2, 0x300f2 },
102 { 0x200f4, 0x600f4 },
103 { 0x400fa, 0x500fa },
110 static int find_alternative(
u64 event)
114 for (i = 0; i <
ARRAY_SIZE(event_alternatives); ++
i) {
115 if (event < event_alternatives[i][0])
117 for (j = 0; j <
MAX_ALT && event_alternatives[
i][
j]; ++
j)
118 if (event == event_alternatives[i][j])
124 static s64 find_alternative_decode(
u64 event)
131 if ((pmc == 2 || pmc == 4) && (psel & ~7) == 0x40)
133 if ((pmc == 1 || pmc == 3) && (psel & ~7) == 0x48)
138 static int power7_get_alternatives(
u64 event,
unsigned int flags,
u64 alt[])
145 i = find_alternative(event);
148 ae = event_alternatives[
i][
j];
149 if (ae && ae != event)
153 ae = find_alternative_decode(event);
167 for (i = 0; i < nalt; ++
i) {
193 static int power7_marked_instr_event(
u64 event)
206 return pmc == 2 || pmc == 4;
225 static int power7_compute_mmcr(
u64 event[],
int n_ev,
226 unsigned int hwc[],
unsigned long mmcr[])
228 unsigned long mmcr1 = 0;
229 unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
230 unsigned int pmc,
unit, combine, l2sel, psel;
231 unsigned int pmc_inuse = 0;
235 for (i = 0; i < n_ev; ++
i) {
240 if (pmc_inuse & (1 << (pmc - 1)))
242 pmc_inuse |= 1 << (pmc - 1);
247 for (i = 0; i < n_ev; ++
i) {
255 for (pmc = 0; pmc < 4; ++pmc) {
256 if (!(pmc_inuse & (1 << pmc)))
261 pmc_inuse |= 1 << pmc;
267 mmcr1 |= (
unsigned long) unit
269 mmcr1 |= (
unsigned long) combine
273 mmcr1 |= (
unsigned long) l2sel
276 if (power7_marked_instr_event(event[i]))
277 mmcra |= MMCRA_SAMPLE_ENABLE;
284 mmcr[0] = MMCR0_PMC1CE;
285 if (pmc_inuse & 0x3e)
286 mmcr[0] |= MMCR0_PMCjCE;
292 static void power7_disable_pmc(
unsigned int pmc,
unsigned long mmcr[])
298 static int power7_generic_events[] = {
309 #define C(x) PERF_COUNT_HW_CACHE_##x
316 static int power7_cache_events[
C(
MAX)][
C(
OP_MAX)][
C(RESULT_MAX)] = {
320 [
C(OP_PREFETCH)] = { 0xd8b8, 0 },
325 [
C(OP_PREFETCH)] = { 0x408a, 0 },
328 [
C(
OP_READ)] = { 0x16080, 0x26080 },
330 [
C(OP_PREFETCH)] = { 0, 0 },
335 [
C(OP_PREFETCH)] = { -1, -1 },
340 [
C(OP_PREFETCH)] = { -1, -1 },
343 [
C(
OP_READ)] = { 0x10068, 0x400f6 },
345 [
C(OP_PREFETCH)] = { -1, -1 },
350 [
C(OP_PREFETCH)] = { -1, -1 },
357 .max_alternatives = MAX_ALT + 1,
358 .add_fields = 0x1555ul,
359 .test_adder = 0x3000ul,
360 .compute_mmcr = power7_compute_mmcr,
361 .get_constraint = power7_get_constraint,
362 .get_alternatives = power7_get_alternatives,
363 .disable_pmc = power7_disable_pmc,
365 .n_generic =
ARRAY_SIZE(power7_generic_events),
366 .generic_events = power7_generic_events,
367 .cache_events = &power7_cache_events,
370 static int __init init_power7_pmu(
void)
376 if (pvr_version_is(PVR_POWER7p))