linux/arch/powerpc/perf/isa207-common.c
<<
>>
Prefs
   1/*
   2 * Common Performance counter support functions for PowerISA v2.07 processors.
   3 *
   4 * Copyright 2009 Paul Mackerras, IBM Corporation.
   5 * Copyright 2013 Michael Ellerman, IBM Corporation.
   6 * Copyright 2016 Madhavan Srinivasan, IBM Corporation.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * as published by the Free Software Foundation; either version
  11 * 2 of the License, or (at your option) any later version.
  12 */
  13#include "isa207-common.h"
  14
  15PMU_FORMAT_ATTR(event,          "config:0-49");
  16PMU_FORMAT_ATTR(pmcxsel,        "config:0-7");
  17PMU_FORMAT_ATTR(mark,           "config:8");
  18PMU_FORMAT_ATTR(combine,        "config:11");
  19PMU_FORMAT_ATTR(unit,           "config:12-15");
  20PMU_FORMAT_ATTR(pmc,            "config:16-19");
  21PMU_FORMAT_ATTR(cache_sel,      "config:20-23");
  22PMU_FORMAT_ATTR(sample_mode,    "config:24-28");
  23PMU_FORMAT_ATTR(thresh_sel,     "config:29-31");
  24PMU_FORMAT_ATTR(thresh_stop,    "config:32-35");
  25PMU_FORMAT_ATTR(thresh_start,   "config:36-39");
  26PMU_FORMAT_ATTR(thresh_cmp,     "config:40-49");
  27
  28struct attribute *isa207_pmu_format_attr[] = {
  29        &format_attr_event.attr,
  30        &format_attr_pmcxsel.attr,
  31        &format_attr_mark.attr,
  32        &format_attr_combine.attr,
  33        &format_attr_unit.attr,
  34        &format_attr_pmc.attr,
  35        &format_attr_cache_sel.attr,
  36        &format_attr_sample_mode.attr,
  37        &format_attr_thresh_sel.attr,
  38        &format_attr_thresh_stop.attr,
  39        &format_attr_thresh_start.attr,
  40        &format_attr_thresh_cmp.attr,
  41        NULL,
  42};
  43
  44struct attribute_group isa207_pmu_format_group = {
  45        .name = "format",
  46        .attrs = isa207_pmu_format_attr,
  47};
  48
  49static inline bool event_is_fab_match(u64 event)
  50{
  51        /* Only check pmc, unit and pmcxsel, ignore the edge bit (0) */
  52        event &= 0xff0fe;
  53
  54        /* PM_MRK_FAB_RSP_MATCH & PM_MRK_FAB_RSP_MATCH_CYC */
  55        return (event == 0x30056 || event == 0x4f052);
  56}
  57
  58static bool is_event_valid(u64 event)
  59{
  60        u64 valid_mask = EVENT_VALID_MASK;
  61
  62        if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
  63                valid_mask = p9_EVENT_VALID_MASK;
  64
  65        return !(event & ~valid_mask);
  66}
  67
  68static inline bool is_event_marked(u64 event)
  69{
  70        if (event & EVENT_IS_MARKED)
  71                return true;
  72
  73        return false;
  74}
  75
  76static void mmcra_sdar_mode(u64 event, unsigned long *mmcra)
  77{
  78        /*
  79         * MMCRA[SDAR_MODE] specifices how the SDAR should be updated in
  80         * continous sampling mode.
  81         *
  82         * Incase of Power8:
  83         * MMCRA[SDAR_MODE] will be programmed as "0b01" for continous sampling
  84         * mode and will be un-changed when setting MMCRA[63] (Marked events).
  85         *
  86         * Incase of Power9:
  87         * Marked event: MMCRA[SDAR_MODE] will be set to 0b00 ('No Updates'),
  88         *               or if group already have any marked events.
  89         * Non-Marked events (for DD1):
  90         *      MMCRA[SDAR_MODE] will be set to 0b01
  91         * For rest
  92         *      MMCRA[SDAR_MODE] will be set from event code.
  93         */
  94        if (cpu_has_feature(CPU_FTR_ARCH_300)) {
  95                if (is_event_marked(event) || (*mmcra & MMCRA_SAMPLE_ENABLE))
  96                        *mmcra &= MMCRA_SDAR_MODE_NO_UPDATES;
  97                else if (!cpu_has_feature(CPU_FTR_POWER9_DD1))
  98                        *mmcra |=  p9_SDAR_MODE(event) << MMCRA_SDAR_MODE_SHIFT;
  99                else if (cpu_has_feature(CPU_FTR_POWER9_DD1))
 100                        *mmcra |= MMCRA_SDAR_MODE_TLB;
 101        } else
 102                *mmcra |= MMCRA_SDAR_MODE_TLB;
 103}
 104
 105static u64 thresh_cmp_val(u64 value)
 106{
 107        if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
 108                return value << p9_MMCRA_THR_CMP_SHIFT;
 109
 110        return value << MMCRA_THR_CMP_SHIFT;
 111}
 112
 113static unsigned long combine_from_event(u64 event)
 114{
 115        if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
 116                return p9_EVENT_COMBINE(event);
 117
 118        return EVENT_COMBINE(event);
 119}
 120
 121static unsigned long combine_shift(unsigned long pmc)
 122{
 123        if (cpu_has_feature(CPU_FTR_ARCH_300) && !cpu_has_feature(CPU_FTR_POWER9_DD1))
 124                return p9_MMCR1_COMBINE_SHIFT(pmc);
 125
 126        return MMCR1_COMBINE_SHIFT(pmc);
 127}
 128
 129static inline bool event_is_threshold(u64 event)
 130{
 131        return (event >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK;
 132}
 133
 134static bool is_thresh_cmp_valid(u64 event)
 135{
 136        unsigned int cmp, exp;
 137
 138        /*
 139         * Check the mantissa upper two bits are not zero, unless the
 140         * exponent is also zero. See the THRESH_CMP_MANTISSA doc.
 141         */
 142        cmp = (event >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK;
 143        exp = cmp >> 7;
 144
 145        if (exp && (cmp & 0x60) == 0)
 146                return false;
 147
 148        return true;
 149}
 150
 151int isa207_get_constraint(u64 event, unsigned long *maskp, unsigned long *valp)
 152{
 153        unsigned int unit, pmc, cache, ebb;
 154        unsigned long mask, value;
 155
 156        mask = value = 0;
 157
 158        if (!is_event_valid(event))
 159                return -1;
 160
 161        pmc   = (event >> EVENT_PMC_SHIFT)        & EVENT_PMC_MASK;
 162        unit  = (event >> EVENT_UNIT_SHIFT)       & EVENT_UNIT_MASK;
 163        cache = (event >> EVENT_CACHE_SEL_SHIFT)  & EVENT_CACHE_SEL_MASK;
 164        ebb   = (event >> EVENT_EBB_SHIFT)        & EVENT_EBB_MASK;
 165
 166        if (pmc) {
 167                u64 base_event;
 168
 169                if (pmc > 6)
 170                        return -1;
 171
 172                /* Ignore Linux defined bits when checking event below */
 173                base_event = event & ~EVENT_LINUX_MASK;
 174
 175                if (pmc >= 5 && base_event != 0x500fa &&
 176                                base_event != 0x600f4)
 177                        return -1;
 178
 179                mask  |= CNST_PMC_MASK(pmc);
 180                value |= CNST_PMC_VAL(pmc);
 181        }
 182
 183        if (pmc <= 4) {
 184                /*
 185                 * Add to number of counters in use. Note this includes events with
 186                 * a PMC of 0 - they still need a PMC, it's just assigned later.
 187                 * Don't count events on PMC 5 & 6, there is only one valid event
 188                 * on each of those counters, and they are handled above.
 189                 */
 190                mask  |= CNST_NC_MASK;
 191                value |= CNST_NC_VAL;
 192        }
 193
 194        if (unit >= 6 && unit <= 9) {
 195                /*
 196                 * L2/L3 events contain a cache selector field, which is
 197                 * supposed to be programmed into MMCRC. However MMCRC is only
 198                 * HV writable, and there is no API for guest kernels to modify
 199                 * it. The solution is for the hypervisor to initialise the
 200                 * field to zeroes, and for us to only ever allow events that
 201                 * have a cache selector of zero. The bank selector (bit 3) is
 202                 * irrelevant, as long as the rest of the value is 0.
 203                 */
 204                if (cache & 0x7)
 205                        return -1;
 206
 207        } else if (event & EVENT_IS_L1) {
 208                mask  |= CNST_L1_QUAL_MASK;
 209                value |= CNST_L1_QUAL_VAL(cache);
 210        }
 211
 212        if (is_event_marked(event)) {
 213                mask  |= CNST_SAMPLE_MASK;
 214                value |= CNST_SAMPLE_VAL(event >> EVENT_SAMPLE_SHIFT);
 215        }
 216
 217        if (cpu_has_feature(CPU_FTR_ARCH_300))  {
 218                if (event_is_threshold(event) && is_thresh_cmp_valid(event)) {
 219                        mask  |= CNST_THRESH_MASK;
 220                        value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT);
 221                }
 222        } else {
 223                /*
 224                 * Special case for PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
 225                 * the threshold control bits are used for the match value.
 226                 */
 227                if (event_is_fab_match(event)) {
 228                        mask  |= CNST_FAB_MATCH_MASK;
 229                        value |= CNST_FAB_MATCH_VAL(event >> EVENT_THR_CTL_SHIFT);
 230                } else {
 231                        if (!is_thresh_cmp_valid(event))
 232                                return -1;
 233
 234                        mask  |= CNST_THRESH_MASK;
 235                        value |= CNST_THRESH_VAL(event >> EVENT_THRESH_SHIFT);
 236                }
 237        }
 238
 239        if (!pmc && ebb)
 240                /* EBB events must specify the PMC */
 241                return -1;
 242
 243        if (event & EVENT_WANTS_BHRB) {
 244                if (!ebb)
 245                        /* Only EBB events can request BHRB */
 246                        return -1;
 247
 248                mask  |= CNST_IFM_MASK;
 249                value |= CNST_IFM_VAL(event >> EVENT_IFM_SHIFT);
 250        }
 251
 252        /*
 253         * All events must agree on EBB, either all request it or none.
 254         * EBB events are pinned & exclusive, so this should never actually
 255         * hit, but we leave it as a fallback in case.
 256         */
 257        mask  |= CNST_EBB_VAL(ebb);
 258        value |= CNST_EBB_MASK;
 259
 260        *maskp = mask;
 261        *valp = value;
 262
 263        return 0;
 264}
 265
 266int isa207_compute_mmcr(u64 event[], int n_ev,
 267                               unsigned int hwc[], unsigned long mmcr[],
 268                               struct perf_event *pevents[])
 269{
 270        unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val;
 271        unsigned int pmc, pmc_inuse;
 272        int i;
 273
 274        pmc_inuse = 0;
 275
 276        /* First pass to count resource use */
 277        for (i = 0; i < n_ev; ++i) {
 278                pmc = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK;
 279                if (pmc)
 280                        pmc_inuse |= 1 << pmc;
 281        }
 282
 283        mmcra = mmcr1 = mmcr2 = 0;
 284
 285        /* Second pass: assign PMCs, set all MMCR1 fields */
 286        for (i = 0; i < n_ev; ++i) {
 287                pmc     = (event[i] >> EVENT_PMC_SHIFT) & EVENT_PMC_MASK;
 288                unit    = (event[i] >> EVENT_UNIT_SHIFT) & EVENT_UNIT_MASK;
 289                combine = combine_from_event(event[i]);
 290                psel    =  event[i] & EVENT_PSEL_MASK;
 291
 292                if (!pmc) {
 293                        for (pmc = 1; pmc <= 4; ++pmc) {
 294                                if (!(pmc_inuse & (1 << pmc)))
 295                                        break;
 296                        }
 297
 298                        pmc_inuse |= 1 << pmc;
 299                }
 300
 301                if (pmc <= 4) {
 302                        mmcr1 |= unit << MMCR1_UNIT_SHIFT(pmc);
 303                        mmcr1 |= combine << combine_shift(pmc);
 304                        mmcr1 |= psel << MMCR1_PMCSEL_SHIFT(pmc);
 305                }
 306
 307                /* In continuous sampling mode, update SDAR on TLB miss */
 308                mmcra_sdar_mode(event[i], &mmcra);
 309
 310                if (event[i] & EVENT_IS_L1) {
 311                        cache = event[i] >> EVENT_CACHE_SEL_SHIFT;
 312                        mmcr1 |= (cache & 1) << MMCR1_IC_QUAL_SHIFT;
 313                        cache >>= 1;
 314                        mmcr1 |= (cache & 1) << MMCR1_DC_QUAL_SHIFT;
 315                }
 316
 317                if (is_event_marked(event[i])) {
 318                        mmcra |= MMCRA_SAMPLE_ENABLE;
 319
 320                        val = (event[i] >> EVENT_SAMPLE_SHIFT) & EVENT_SAMPLE_MASK;
 321                        if (val) {
 322                                mmcra |= (val &  3) << MMCRA_SAMP_MODE_SHIFT;
 323                                mmcra |= (val >> 2) << MMCRA_SAMP_ELIG_SHIFT;
 324                        }
 325                }
 326
 327                /*
 328                 * PM_MRK_FAB_RSP_MATCH and PM_MRK_FAB_RSP_MATCH_CYC,
 329                 * the threshold bits are used for the match value.
 330                 */
 331                if (!cpu_has_feature(CPU_FTR_ARCH_300) && event_is_fab_match(event[i])) {
 332                        mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) &
 333                                  EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT;
 334                } else {
 335                        val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK;
 336                        mmcra |= val << MMCRA_THR_CTL_SHIFT;
 337                        val = (event[i] >> EVENT_THR_SEL_SHIFT) & EVENT_THR_SEL_MASK;
 338                        mmcra |= val << MMCRA_THR_SEL_SHIFT;
 339                        val = (event[i] >> EVENT_THR_CMP_SHIFT) & EVENT_THR_CMP_MASK;
 340                        mmcra |= thresh_cmp_val(val);
 341                }
 342
 343                if (event[i] & EVENT_WANTS_BHRB) {
 344                        val = (event[i] >> EVENT_IFM_SHIFT) & EVENT_IFM_MASK;
 345                        mmcra |= val << MMCRA_IFM_SHIFT;
 346                }
 347
 348                if (pevents[i]->attr.exclude_user)
 349                        mmcr2 |= MMCR2_FCP(pmc);
 350
 351                if (pevents[i]->attr.exclude_hv)
 352                        mmcr2 |= MMCR2_FCH(pmc);
 353
 354                if (pevents[i]->attr.exclude_kernel) {
 355                        if (cpu_has_feature(CPU_FTR_HVMODE))
 356                                mmcr2 |= MMCR2_FCH(pmc);
 357                        else
 358                                mmcr2 |= MMCR2_FCS(pmc);
 359                }
 360
 361                hwc[i] = pmc - 1;
 362        }
 363
 364        /* Return MMCRx values */
 365        mmcr[0] = 0;
 366
 367        /* pmc_inuse is 1-based */
 368        if (pmc_inuse & 2)
 369                mmcr[0] = MMCR0_PMC1CE;
 370
 371        if (pmc_inuse & 0x7c)
 372                mmcr[0] |= MMCR0_PMCjCE;
 373
 374        /* If we're not using PMC 5 or 6, freeze them */
 375        if (!(pmc_inuse & 0x60))
 376                mmcr[0] |= MMCR0_FC56;
 377
 378        mmcr[1] = mmcr1;
 379        mmcr[2] = mmcra;
 380        mmcr[3] = mmcr2;
 381
 382        return 0;
 383}
 384
 385void isa207_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 386{
 387        if (pmc <= 3)
 388                mmcr[1] &= ~(0xffUL << MMCR1_PMCSEL_SHIFT(pmc + 1));
 389}
 390
 391static int find_alternative(u64 event, const unsigned int ev_alt[][MAX_ALT], int size)
 392{
 393        int i, j;
 394
 395        for (i = 0; i < size; ++i) {
 396                if (event < ev_alt[i][0])
 397                        break;
 398
 399                for (j = 0; j < MAX_ALT && ev_alt[i][j]; ++j)
 400                        if (event == ev_alt[i][j])
 401                                return i;
 402        }
 403
 404        return -1;
 405}
 406
 407int isa207_get_alternatives(u64 event, u64 alt[],
 408                                const unsigned int ev_alt[][MAX_ALT], int size)
 409{
 410        int i, j, num_alt = 0;
 411        u64 alt_event;
 412
 413        alt[num_alt++] = event;
 414        i = find_alternative(event, ev_alt, size);
 415        if (i >= 0) {
 416                /* Filter out the original event, it's already in alt[0] */
 417                for (j = 0; j < MAX_ALT; ++j) {
 418                        alt_event = ev_alt[i][j];
 419                        if (alt_event && alt_event != event)
 420                                alt[num_alt++] = alt_event;
 421                }
 422        }
 423
 424        return num_alt;
 425}
 426