~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/perf/power6-pmu.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  2 /*
  3  * Performance counter support for POWER6 processors.
  4  *
  5  * Copyright 2008-2009 Paul Mackerras, IBM Corporation.
  6  */
  7 #include <linux/kernel.h>
  8 #include <linux/perf_event.h>
  9 #include <linux/string.h>
 10 #include <asm/reg.h>
 11 #include <asm/cputable.h>
 12 
 13 #include "internal.h"
 14 
 15 /*
 16  * Bits in event code for POWER6
 17  */
 18 #define PM_PMC_SH       20      /* PMC number (1-based) for direct events */
 19 #define PM_PMC_MSK      0x7
 20 #define PM_PMC_MSKS     (PM_PMC_MSK << PM_PMC_SH)
 21 #define PM_UNIT_SH      16      /* Unit event comes (TTMxSEL encoding) */
 22 #define PM_UNIT_MSK     0xf
 23 #define PM_UNIT_MSKS    (PM_UNIT_MSK << PM_UNIT_SH)
 24 #define PM_LLAV         0x8000  /* Load lookahead match value */
 25 #define PM_LLA          0x4000  /* Load lookahead match enable */
 26 #define PM_BYTE_SH      12      /* Byte of event bus to use */
 27 #define PM_BYTE_MSK     3
 28 #define PM_SUBUNIT_SH   8       /* Subunit event comes from (NEST_SEL enc.) */
 29 #define PM_SUBUNIT_MSK  7
 30 #define PM_SUBUNIT_MSKS (PM_SUBUNIT_MSK << PM_SUBUNIT_SH)
 31 #define PM_PMCSEL_MSK   0xff    /* PMCxSEL value */
 32 #define PM_BUSEVENT_MSK 0xf3700
 33 
 34 /*
 35  * Bits in MMCR1 for POWER6
 36  */
 37 #define MMCR1_TTM0SEL_SH        60
 38 #define MMCR1_TTMSEL_SH(n)      (MMCR1_TTM0SEL_SH - (n) * 4)
 39 #define MMCR1_TTMSEL_MSK        0xf
 40 #define MMCR1_TTMSEL(m, n)      (((m) >> MMCR1_TTMSEL_SH(n)) & MMCR1_TTMSEL_MSK)
 41 #define MMCR1_NESTSEL_SH        45
 42 #define MMCR1_NESTSEL_MSK       0x7
 43 #define MMCR1_NESTSEL(m)        (((m) >> MMCR1_NESTSEL_SH) & MMCR1_NESTSEL_MSK)
 44 #define MMCR1_PMC1_LLA          (1ul << 44)
 45 #define MMCR1_PMC1_LLA_VALUE    (1ul << 39)
 46 #define MMCR1_PMC1_ADDR_SEL     (1ul << 35)
 47 #define MMCR1_PMC1SEL_SH        24
 48 #define MMCR1_PMCSEL_SH(n)      (MMCR1_PMC1SEL_SH - (n) * 8)
 49 #define MMCR1_PMCSEL_MSK        0xff
 50 
 51 /*
 52  * Map of which direct events on which PMCs are marked instruction events.
 53  * Indexed by PMCSEL value >> 1.
 54  * Bottom 4 bits are a map of which PMCs are interesting,
 55  * top 4 bits say what sort of event:
 56  *   0 = direct marked event,
 57  *   1 = byte decode event,
 58  *   4 = add/and event (PMC1 -> bits 0 & 4),
 59  *   5 = add/and event (PMC1 -> bits 1 & 5),
 60  *   6 = add/and event (PMC1 -> bits 2 & 6),
 61  *   7 = add/and event (PMC1 -> bits 3 & 7).
 62  */
 63 static unsigned char direct_event_is_marked[0x60 >> 1] = {
 64         0,      /* 00 */
 65         0,      /* 02 */
 66         0,      /* 04 */
 67         0x07,   /* 06 PM_MRK_ST_CMPL, PM_MRK_ST_GPS, PM_MRK_ST_CMPL_INT */
 68         0x04,   /* 08 PM_MRK_DFU_FIN */
 69         0x06,   /* 0a PM_MRK_IFU_FIN, PM_MRK_INST_FIN */
 70         0,      /* 0c */
 71         0,      /* 0e */
 72         0x02,   /* 10 PM_MRK_INST_DISP */
 73         0x08,   /* 12 PM_MRK_LSU_DERAT_MISS */
 74         0,      /* 14 */
 75         0,      /* 16 */
 76         0x0c,   /* 18 PM_THRESH_TIMEO, PM_MRK_INST_FIN */
 77         0x0f,   /* 1a PM_MRK_INST_DISP, PM_MRK_{FXU,FPU,LSU}_FIN */
 78         0x01,   /* 1c PM_MRK_INST_ISSUED */
 79         0,      /* 1e */
 80         0,      /* 20 */
 81         0,      /* 22 */
 82         0,      /* 24 */
 83         0,      /* 26 */
 84         0x15,   /* 28 PM_MRK_DATA_FROM_L2MISS, PM_MRK_DATA_FROM_L3MISS */
 85         0,      /* 2a */
 86         0,      /* 2c */
 87         0,      /* 2e */
 88         0x4f,   /* 30 */
 89         0x7f,   /* 32 */
 90         0x4f,   /* 34 */
 91         0x5f,   /* 36 */
 92         0x6f,   /* 38 */
 93         0x4f,   /* 3a */
 94         0,      /* 3c */
 95         0x08,   /* 3e PM_MRK_INST_TIMEO */
 96         0x1f,   /* 40 */
 97         0x1f,   /* 42 */
 98         0x1f,   /* 44 */
 99         0x1f,   /* 46 */
100         0x1f,   /* 48 */
101         0x1f,   /* 4a */
102         0x1f,   /* 4c */
103         0x1f,   /* 4e */
104         0,      /* 50 */
105         0x05,   /* 52 PM_MRK_BR_TAKEN, PM_MRK_BR_MPRED */
106         0x1c,   /* 54 PM_MRK_PTEG_FROM_L3MISS, PM_MRK_PTEG_FROM_L2MISS */
107         0x02,   /* 56 PM_MRK_LD_MISS_L1 */
108         0,      /* 58 */
109         0,      /* 5a */
110         0,      /* 5c */
111         0,      /* 5e */
112 };
113 
114 /*
115  * Masks showing for each unit which bits are marked events.
116  * These masks are in LE order, i.e. 0x00000001 is byte 0, bit 0.
117  */
118 static u32 marked_bus_events[16] = {
119         0x01000000,     /* direct events set 1: byte 3 bit 0 */
120         0x00010000,     /* direct events set 2: byte 2 bit 0 */
121         0, 0, 0, 0,     /* IDU, IFU, nest: nothing */
122         0x00000088,     /* VMX set 1: byte 0 bits 3, 7 */
123         0x000000c0,     /* VMX set 2: byte 0 bits 4-7 */
124         0x04010000,     /* LSU set 1: byte 2 bit 0, byte 3 bit 2 */
125         0xff010000u,    /* LSU set 2: byte 2 bit 0, all of byte 3 */
126         0,              /* LSU set 3 */
127         0x00000010,     /* VMX set 3: byte 0 bit 4 */
128         0,              /* BFP set 1 */
129         0x00000022,     /* BFP set 2: byte 0 bits 1, 5 */
130         0, 0
131 };
132 
133 /*
134  * Returns 1 if event counts things relating to marked instructions
135  * and thus needs the MMCRA_SAMPLE_ENABLE bit set, or 0 if not.
136  */
137 static int power6_marked_instr_event(u64 event)
138 {
139         int pmc, psel, ptype;
140         int bit, byte, unit;
141         u32 mask;
142 
143         pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
144         psel = (event & PM_PMCSEL_MSK) >> 1;    /* drop edge/level bit */
145         if (pmc >= 5)
146                 return 0;
147 
148         bit = -1;
149         if (psel < sizeof(direct_event_is_marked)) {
150                 ptype = direct_event_is_marked[psel];
151                 if (pmc == 0 || !(ptype & (1 << (pmc - 1))))
152                         return 0;
153                 ptype >>= 4;
154                 if (ptype == 0)
155                         return 1;
156                 if (ptype == 1)
157                         bit = 0;
158                 else
159                         bit = ptype ^ (pmc - 1);
160         } else if ((psel & 0x48) == 0x40)
161                 bit = psel & 7;
162 
163         if (!(event & PM_BUSEVENT_MSK) || bit == -1)
164                 return 0;
165 
166         byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
167         unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
168         mask = marked_bus_events[unit];
169         return (mask >> (byte * 8 + bit)) & 1;
170 }
171 
172 /*
173  * Assign PMC numbers and compute MMCR1 value for a set of events
174  */
175 static int p6_compute_mmcr(u64 event[], int n_ev,
176                            unsigned int hwc[], struct mmcr_regs *mmcr, struct perf_event *pevents[],
177                            u32 flags __maybe_unused)
178 {
179         unsigned long mmcr1 = 0;
180         unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
181         int i;
182         unsigned int pmc, ev, b, u, s, psel;
183         unsigned int ttmset = 0;
184         unsigned int pmc_inuse = 0;
185 
186         if (n_ev > 6)
187                 return -1;
188         for (i = 0; i < n_ev; ++i) {
189                 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
190                 if (pmc) {
191                         if (pmc_inuse & (1 << (pmc - 1)))
192                                 return -1;      /* collision! */
193                         pmc_inuse |= 1 << (pmc - 1);
194                 }
195         }
196         for (i = 0; i < n_ev; ++i) {
197                 ev = event[i];
198                 pmc = (ev >> PM_PMC_SH) & PM_PMC_MSK;
199                 if (pmc) {
200                         --pmc;
201                 } else {
202                         /* can go on any PMC; find a free one */
203                         for (pmc = 0; pmc < 4; ++pmc)
204                                 if (!(pmc_inuse & (1 << pmc)))
205                                         break;
206                         if (pmc >= 4)
207                                 return -1;
208                         pmc_inuse |= 1 << pmc;
209                 }
210                 hwc[i] = pmc;
211                 psel = ev & PM_PMCSEL_MSK;
212                 if (ev & PM_BUSEVENT_MSK) {
213                         /* this event uses the event bus */
214                         b = (ev >> PM_BYTE_SH) & PM_BYTE_MSK;
215                         u = (ev >> PM_UNIT_SH) & PM_UNIT_MSK;
216                         /* check for conflict on this byte of event bus */
217                         if ((ttmset & (1 << b)) && MMCR1_TTMSEL(mmcr1, b) != u)
218                                 return -1;
219                         mmcr1 |= (unsigned long)u << MMCR1_TTMSEL_SH(b);
220                         ttmset |= 1 << b;
221                         if (u == 5) {
222                                 /* Nest events have a further mux */
223                                 s = (ev >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK;
224                                 if ((ttmset & 0x10) &&
225                                     MMCR1_NESTSEL(mmcr1) != s)
226                                         return -1;
227                                 ttmset |= 0x10;
228                                 mmcr1 |= (unsigned long)s << MMCR1_NESTSEL_SH;
229                         }
230                         if (0x30 <= psel && psel <= 0x3d) {
231                                 /* these need the PMCx_ADDR_SEL bits */
232                                 if (b >= 2)
233                                         mmcr1 |= MMCR1_PMC1_ADDR_SEL >> pmc;
234                         }
235                         /* bus select values are different for PMC3/4 */
236                         if (pmc >= 2 && (psel & 0x90) == 0x80)
237                                 psel ^= 0x20;
238                 }
239                 if (ev & PM_LLA) {
240                         mmcr1 |= MMCR1_PMC1_LLA >> pmc;
241                         if (ev & PM_LLAV)
242                                 mmcr1 |= MMCR1_PMC1_LLA_VALUE >> pmc;
243                 }
244                 if (power6_marked_instr_event(event[i]))
245                         mmcra |= MMCRA_SAMPLE_ENABLE;
246                 if (pmc < 4)
247                         mmcr1 |= (unsigned long)psel << MMCR1_PMCSEL_SH(pmc);
248         }
249         mmcr->mmcr0 = 0;
250         if (pmc_inuse & 1)
251                 mmcr->mmcr0 = MMCR0_PMC1CE;
252         if (pmc_inuse & 0xe)
253                 mmcr->mmcr0 |= MMCR0_PMCjCE;
254         mmcr->mmcr1 = mmcr1;
255         mmcr->mmcra = mmcra;
256         return 0;
257 }
258 
259 /*
260  * Layout of constraint bits:
261  *
262  *      0-1     add field: number of uses of PMC1 (max 1)
263  *      2-3, 4-5, 6-7, 8-9, 10-11: ditto for PMC2, 3, 4, 5, 6
264  *      12-15   add field: number of uses of PMC1-4 (max 4)
265  *      16-19   select field: unit on byte 0 of event bus
266  *      20-23, 24-27, 28-31 ditto for bytes 1, 2, 3
267  *      32-34   select field: nest (subunit) event selector
268  */
269 static int p6_get_constraint(u64 event, unsigned long *maskp,
270                              unsigned long *valp, u64 event_config1 __maybe_unused)
271 {
272         int pmc, byte, sh, subunit;
273         unsigned long mask = 0, value = 0;
274 
275         pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
276         if (pmc) {
277                 if (pmc > 4 && !(event == 0x500009 || event == 0x600005))
278                         return -1;
279                 sh = (pmc - 1) * 2;
280                 mask |= 2 << sh;
281                 value |= 1 << sh;
282         }
283         if (event & PM_BUSEVENT_MSK) {
284                 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
285                 sh = byte * 4 + (16 - PM_UNIT_SH);
286                 mask |= PM_UNIT_MSKS << sh;
287                 value |= (unsigned long)(event & PM_UNIT_MSKS) << sh;
288                 if ((event & PM_UNIT_MSKS) == (5 << PM_UNIT_SH)) {
289                         subunit = (event >> PM_SUBUNIT_SH) & PM_SUBUNIT_MSK;
290                         mask  |= (unsigned long)PM_SUBUNIT_MSK << 32;
291                         value |= (unsigned long)subunit << 32;
292                 }
293         }
294         if (pmc <= 4) {
295                 mask  |= 0x8000;        /* add field for count of PMC1-4 uses */
296                 value |= 0x1000;
297         }
298         *maskp = mask;
299         *valp = value;
300         return 0;
301 }
302 
303 static int p6_limited_pmc_event(u64 event)
304 {
305         int pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
306 
307         return pmc == 5 || pmc == 6;
308 }
309 
310 #define MAX_ALT 4       /* at most 4 alternatives for any event */
311 
312 static const unsigned int event_alternatives[][MAX_ALT] = {
313         { 0x0130e8, 0x2000f6, 0x3000fc },       /* PM_PTEG_RELOAD_VALID */
314         { 0x080080, 0x10000d, 0x30000c, 0x4000f0 }, /* PM_LD_MISS_L1 */
315         { 0x080088, 0x200054, 0x3000f0 },       /* PM_ST_MISS_L1 */
316         { 0x10000a, 0x2000f4, 0x600005 },       /* PM_RUN_CYC */
317         { 0x10000b, 0x2000f5 },                 /* PM_RUN_COUNT */
318         { 0x10000e, 0x400010 },                 /* PM_PURR */
319         { 0x100010, 0x4000f8 },                 /* PM_FLUSH */
320         { 0x10001a, 0x200010 },                 /* PM_MRK_INST_DISP */
321         { 0x100026, 0x3000f8 },                 /* PM_TB_BIT_TRANS */
322         { 0x100054, 0x2000f0 },                 /* PM_ST_FIN */
323         { 0x100056, 0x2000fc },                 /* PM_L1_ICACHE_MISS */
324         { 0x1000f0, 0x40000a },                 /* PM_INST_IMC_MATCH_CMPL */
325         { 0x1000f8, 0x200008 },                 /* PM_GCT_EMPTY_CYC */
326         { 0x1000fc, 0x400006 },                 /* PM_LSU_DERAT_MISS_CYC */
327         { 0x20000e, 0x400007 },                 /* PM_LSU_DERAT_MISS */
328         { 0x200012, 0x300012 },                 /* PM_INST_DISP */
329         { 0x2000f2, 0x3000f2 },                 /* PM_INST_DISP */
330         { 0x2000f8, 0x300010 },                 /* PM_EXT_INT */
331         { 0x2000fe, 0x300056 },                 /* PM_DATA_FROM_L2MISS */
332         { 0x2d0030, 0x30001a },                 /* PM_MRK_FPU_FIN */
333         { 0x30000a, 0x400018 },                 /* PM_MRK_INST_FIN */
334         { 0x3000f6, 0x40000e },                 /* PM_L1_DCACHE_RELOAD_VALID */
335         { 0x3000fe, 0x400056 },                 /* PM_DATA_FROM_L3MISS */
336 };
337 
338 static int find_alternatives_list(u64 event)
339 {
340         const unsigned int presorted_event_table[] = {
341                 0x0130e8, 0x080080, 0x080088, 0x10000a, 0x10000b, 0x10000d, 0x10000e,
342                 0x100010, 0x10001a, 0x100026, 0x100054, 0x100056, 0x1000f0, 0x1000f8,
343                 0x1000fc, 0x200008, 0x20000e, 0x200010, 0x200012, 0x200054, 0x2000f0,
344                 0x2000f2, 0x2000f4, 0x2000f5, 0x2000f6, 0x2000f8, 0x2000fc, 0x2000fe,
345                 0x2d0030, 0x30000a, 0x30000c, 0x300010, 0x300012, 0x30001a, 0x300056,
346                 0x3000f0, 0x3000f2, 0x3000f6, 0x3000f8, 0x3000fc, 0x3000fe, 0x400006,
347                 0x400007, 0x40000a, 0x40000e, 0x400010, 0x400018, 0x400056, 0x4000f0,
348                 0x4000f8, 0x600005
349         };
350         const unsigned int event_index_table[] = {
351                 0,  1,  2,  3,  4,  1, 5,  6,  7,  8,  9,  10, 11, 12, 13, 12, 14,
352                 7,  15, 2,  9,  16, 3, 4,  0,  17, 10, 18, 19, 20, 1,  17, 15, 19,
353                 18, 2,  16, 21, 8,  0, 22, 13, 14, 11, 21, 5,  20, 22, 1,  6,  3
354         };
355         int hi = ARRAY_SIZE(presorted_event_table) - 1;
356         int lo = 0;
357 
358         while (lo <= hi) {
359                 int mid = lo + (hi - lo) / 2;
360                 unsigned int alt = presorted_event_table[mid];
361 
362                 if (alt < event)
363                         lo = mid + 1;
364                 else if (alt > event)
365                         hi = mid - 1;
366                 else
367                         return event_index_table[mid];
368         }
369 
370         return -1;
371 }
372 
373 static int p6_get_alternatives(u64 event, unsigned int flags, u64 alt[])
374 {
375         int i, j, nlim;
376         unsigned int psel, pmc;
377         unsigned int nalt = 1;
378         u64 aevent;
379 
380         alt[0] = event;
381         nlim = p6_limited_pmc_event(event);
382 
383         /* check the alternatives table */
384         i = find_alternatives_list(event);
385         if (i >= 0) {
386                 /* copy out alternatives from list */
387                 for (j = 0; j < MAX_ALT; ++j) {
388                         aevent = event_alternatives[i][j];
389                         if (!aevent)
390                                 break;
391                         if (aevent != event)
392                                 alt[nalt++] = aevent;
393                         nlim += p6_limited_pmc_event(aevent);
394                 }
395 
396         } else {
397                 /* Check for alternative ways of computing sum events */
398                 /* PMCSEL 0x32 counter N == PMCSEL 0x34 counter 5-N */
399                 psel = event & (PM_PMCSEL_MSK & ~1);    /* ignore edge bit */
400                 pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
401                 if (pmc && (psel == 0x32 || psel == 0x34))
402                         alt[nalt++] = ((event ^ 0x6) & ~PM_PMC_MSKS) |
403                                 ((5 - pmc) << PM_PMC_SH);
404 
405                 /* PMCSEL 0x38 counter N == PMCSEL 0x3a counter N+/-2 */
406                 if (pmc && (psel == 0x38 || psel == 0x3a))
407                         alt[nalt++] = ((event ^ 0x2) & ~PM_PMC_MSKS) |
408                                 ((pmc > 2? pmc - 2: pmc + 2) << PM_PMC_SH);
409         }
410 
411         if (flags & PPMU_ONLY_COUNT_RUN) {
412                 /*
413                  * We're only counting in RUN state,
414                  * so PM_CYC is equivalent to PM_RUN_CYC,
415                  * PM_INST_CMPL === PM_RUN_INST_CMPL, PM_PURR === PM_RUN_PURR.
416                  * This doesn't include alternatives that don't provide
417                  * any extra flexibility in assigning PMCs (e.g.
418                  * 0x10000a for PM_RUN_CYC vs. 0x1e for PM_CYC).
419                  * Note that even with these additional alternatives
420                  * we never end up with more than 4 alternatives for any event.
421                  */
422                 j = nalt;
423                 for (i = 0; i < nalt; ++i) {
424                         switch (alt[i]) {
425                         case 0x1e:      /* PM_CYC */
426                                 alt[j++] = 0x600005;    /* PM_RUN_CYC */
427                                 ++nlim;
428                                 break;
429                         case 0x10000a:  /* PM_RUN_CYC */
430                                 alt[j++] = 0x1e;        /* PM_CYC */
431                                 break;
432                         case 2:         /* PM_INST_CMPL */
433                                 alt[j++] = 0x500009;    /* PM_RUN_INST_CMPL */
434                                 ++nlim;
435                                 break;
436                         case 0x500009:  /* PM_RUN_INST_CMPL */
437                                 alt[j++] = 2;           /* PM_INST_CMPL */
438                                 break;
439                         case 0x10000e:  /* PM_PURR */
440                                 alt[j++] = 0x4000f4;    /* PM_RUN_PURR */
441                                 break;
442                         case 0x4000f4:  /* PM_RUN_PURR */
443                                 alt[j++] = 0x10000e;    /* PM_PURR */
444                                 break;
445                         }
446                 }
447                 nalt = j;
448         }
449 
450         if (!(flags & PPMU_LIMITED_PMC_OK) && nlim) {
451                 /* remove the limited PMC events */
452                 j = 0;
453                 for (i = 0; i < nalt; ++i) {
454                         if (!p6_limited_pmc_event(alt[i])) {
455                                 alt[j] = alt[i];
456                                 ++j;
457                         }
458                 }
459                 nalt = j;
460         } else if ((flags & PPMU_LIMITED_PMC_REQD) && nlim < nalt) {
461                 /* remove all but the limited PMC events */
462                 j = 0;
463                 for (i = 0; i < nalt; ++i) {
464                         if (p6_limited_pmc_event(alt[i])) {
465                                 alt[j] = alt[i];
466                                 ++j;
467                         }
468                 }
469                 nalt = j;
470         }
471 
472         return nalt;
473 }
474 
475 static void p6_disable_pmc(unsigned int pmc, struct mmcr_regs *mmcr)
476 {
477         /* Set PMCxSEL to 0 to disable PMCx */
478         if (pmc <= 3)
479                 mmcr->mmcr1 &= ~(0xffUL << MMCR1_PMCSEL_SH(pmc));
480 }
481 
482 static int power6_generic_events[] = {
483         [PERF_COUNT_HW_CPU_CYCLES]              = 0x1e,
484         [PERF_COUNT_HW_INSTRUCTIONS]            = 2,
485         [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x280030, /* LD_REF_L1 */
486         [PERF_COUNT_HW_CACHE_MISSES]            = 0x30000c, /* LD_MISS_L1 */
487         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0x410a0,  /* BR_PRED */
488         [PERF_COUNT_HW_BRANCH_MISSES]           = 0x400052, /* BR_MPRED */
489 };
490 
491 #define C(x)    PERF_COUNT_HW_CACHE_##x
492 
493 /*
494  * Table of generalized cache-related events.
495  * 0 means not supported, -1 means nonsensical, other values
496  * are event codes.
497  * The "DTLB" and "ITLB" events relate to the DERAT and IERAT.
498  */
499 static u64 power6_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
500         [C(L1D)] = {            /*      RESULT_ACCESS   RESULT_MISS */
501                 [C(OP_READ)] = {        0x280030,       0x80080         },
502                 [C(OP_WRITE)] = {       0x180032,       0x80088         },
503                 [C(OP_PREFETCH)] = {    0x810a4,        0               },
504         },
505         [C(L1I)] = {            /*      RESULT_ACCESS   RESULT_MISS */
506                 [C(OP_READ)] = {        0,              0x100056        },
507                 [C(OP_WRITE)] = {       -1,             -1              },
508                 [C(OP_PREFETCH)] = {    0x4008c,        0               },
509         },
510         [C(LL)] = {             /*      RESULT_ACCESS   RESULT_MISS */
511                 [C(OP_READ)] = {        0x150730,       0x250532        },
512                 [C(OP_WRITE)] = {       0x250432,       0x150432        },
513                 [C(OP_PREFETCH)] = {    0x810a6,        0               },
514         },
515         [C(DTLB)] = {           /*      RESULT_ACCESS   RESULT_MISS */
516                 [C(OP_READ)] = {        0,              0x20000e        },
517                 [C(OP_WRITE)] = {       -1,             -1              },
518                 [C(OP_PREFETCH)] = {    -1,             -1              },
519         },
520         [C(ITLB)] = {           /*      RESULT_ACCESS   RESULT_MISS */
521                 [C(OP_READ)] = {        0,              0x420ce         },
522                 [C(OP_WRITE)] = {       -1,             -1              },
523                 [C(OP_PREFETCH)] = {    -1,             -1              },
524         },
525         [C(BPU)] = {            /*      RESULT_ACCESS   RESULT_MISS */
526                 [C(OP_READ)] = {        0x430e6,        0x400052        },
527                 [C(OP_WRITE)] = {       -1,             -1              },
528                 [C(OP_PREFETCH)] = {    -1,             -1              },
529         },
530         [C(NODE)] = {           /*      RESULT_ACCESS   RESULT_MISS */
531                 [C(OP_READ)] = {        -1,             -1              },
532                 [C(OP_WRITE)] = {       -1,             -1              },
533                 [C(OP_PREFETCH)] = {    -1,             -1              },
534         },
535 };
536 
537 static struct power_pmu power6_pmu = {
538         .name                   = "POWER6",
539         .n_counter              = 6,
540         .max_alternatives       = MAX_ALT,
541         .add_fields             = 0x1555,
542         .test_adder             = 0x3000,
543         .compute_mmcr           = p6_compute_mmcr,
544         .get_constraint         = p6_get_constraint,
545         .get_alternatives       = p6_get_alternatives,
546         .disable_pmc            = p6_disable_pmc,
547         .limited_pmc_event      = p6_limited_pmc_event,
548         .flags                  = PPMU_LIMITED_PMC5_6 | PPMU_ALT_SIPR,
549         .n_generic              = ARRAY_SIZE(power6_generic_events),
550         .generic_events         = power6_generic_events,
551         .cache_events           = &power6_cache_events,
552 };
553 
554 int __init init_power6_pmu(void)
555 {
556         unsigned int pvr = mfspr(SPRN_PVR);
557 
558         if (PVR_VER(pvr) != PVR_POWER6)
559                 return -ENODEV;
560 
561         return register_power_pmu(&power6_pmu);
562 }
563 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php