akaros/user/perfmon/pfmlib_intel_snbep_unc.c
<<
>>
Prefs
   1/*
   2 * pfmlib_intel_snbep_unc.c : Intel SandyBridge-EP uncore PMU common code
   3 *
   4 * Copyright (c) 2012 Google, Inc
   5 * Contributed by Stephane Eranian <eranian@gmail.com>
   6 *
   7 * Permission is hereby granted, free of charge, to any person obtaining a copy
   8 * of this software and associated documentation files (the "Software"), to deal
   9 * in the Software without restriction, including without limitation the rights
  10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  11 * of the Software, and to permit persons to whom the Software is furnished to do so,
  12 * subject to the following conditions:
  13 *
  14 * The above copyright notice and this permission notice shall be included in all
  15 * copies or substantial portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  18 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  19 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  21 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  22 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23 */
  24#include <sys/types.h>
  25#include <ctype.h>
  26#include <string.h>
  27#include <stdlib.h>
  28#include <stdio.h>
  29
  30/* private headers */
  31#include "pfmlib_priv.h"
  32#include "pfmlib_intel_x86_priv.h"
  33#include "pfmlib_intel_snbep_unc_priv.h"
  34
  35const pfmlib_attr_desc_t snbep_unc_mods[]={
  36        PFM_ATTR_B("e", "edge detect"),                 /* edge */
  37        PFM_ATTR_B("i", "invert"),                      /* invert */
  38        PFM_ATTR_I("t", "threshold in range [0-255]"),  /* threshold */
  39        PFM_ATTR_I("t", "threshold in range [0-31]"),   /* threshold */
  40        PFM_ATTR_I("tf", "thread id filter [0-1]"),     /* thread id */
  41        PFM_ATTR_I("cf", "core id filter, includes non-thread data in bit 4 [0-15]"),   /* core id (ivbep) */
  42        PFM_ATTR_I("nf", "node id bitmask filter [0-255]"),/* nodeid mask filter0 */
  43        PFM_ATTR_I("ff", "frequency >= 100Mhz * [0-255]"),/* freq filter */
  44        PFM_ATTR_I("addr", "physical address matcher [40 bits]"),/* address matcher */
  45        PFM_ATTR_I("nf", "node id bitmask filter [0-255]"),/* nodeid mask filter1 */
  46        PFM_ATTR_B("isoc", "match isochronous requests"),   /* isochronous */
  47        PFM_ATTR_B("nc", "match non-coherent requests"),   /* non-coherent */
  48        PFM_ATTR_NULL
  49};
  50
  51int
  52pfm_intel_snbep_unc_detect(void *this)
  53{
  54        int ret;
  55
  56        ret = pfm_intel_x86_detect();
  57        if (ret != PFM_SUCCESS)
  58
  59        if (pfm_intel_x86_cfg.family != 6)
  60                return PFM_ERR_NOTSUPP;
  61
  62        switch(pfm_intel_x86_cfg.model) {
  63                case 45: /* SandyBridge-EP */
  64                          break;
  65                default:
  66                        return PFM_ERR_NOTSUPP;
  67        }
  68        return PFM_SUCCESS;
  69}
  70
  71int
  72pfm_intel_ivbep_unc_detect(void *this)
  73{
  74       int ret;
  75
  76       ret = pfm_intel_x86_detect();
  77       if (ret != PFM_SUCCESS)
  78
  79       if (pfm_intel_x86_cfg.family != 6)
  80               return PFM_ERR_NOTSUPP;
  81
  82       switch(pfm_intel_x86_cfg.model) {
  83               case 62: /* SandyBridge-EP */
  84                         break;
  85               default:
  86                       return PFM_ERR_NOTSUPP;
  87       }
  88       return PFM_SUCCESS;
  89}
  90
  91static void
  92display_com(void *this, pfmlib_event_desc_t *e, void *val)
  93{
  94        const intel_x86_entry_t *pe = this_pe(this);
  95        pfm_snbep_unc_reg_t *reg = val;
  96
  97        __pfm_vbprintf("[UNC=0x%"PRIx64" event=0x%x umask=0x%x en=%d "
  98                       "inv=%d edge=%d thres=%d] %s\n",
  99                        reg->val,
 100                        reg->com.unc_event,
 101                        reg->com.unc_umask,
 102                        reg->com.unc_en,
 103                        reg->com.unc_inv,
 104                        reg->com.unc_edge,
 105                        reg->com.unc_thres,
 106                        pe[e->event].name);
 107}
 108
 109static void
 110display_reg(void *this, pfmlib_event_desc_t *e, pfm_snbep_unc_reg_t reg)
 111{
 112        pfmlib_pmu_t *pmu = this;
 113        if (pmu->display_reg)
 114                pmu->display_reg(this, e, &reg);
 115        else
 116                display_com(this, e, &reg);
 117}
 118
 119static inline int
 120is_occ_event(void *this, int idx)
 121{
 122        pfmlib_pmu_t *pmu = this;
 123        const intel_x86_entry_t *pe = this_pe(this);
 124
 125        return (pmu->flags & INTEL_PMU_FL_UNC_OCC) && (pe[idx].code & 0x80);
 126}
 127
 128static inline int
 129get_pcu_filt_band(void *this, pfm_snbep_unc_reg_t reg)
 130{
 131#define PCU_FREQ_BAND0_CODE     0xb /* event code for UNC_P_FREQ_BAND0_CYCLES */
 132        return reg.pcu.unc_event - PCU_FREQ_BAND0_CODE;
 133}
 134
 135int
 136snbep_unc_add_defaults(void *this, pfmlib_event_desc_t *e,
 137                           unsigned int msk,
 138                           uint64_t *umask,
 139                           pfm_snbep_unc_reg_t *filters,
 140                           unsigned int max_grpid)
 141{
 142        const intel_x86_entry_t *pe = this_pe(this);
 143        const intel_x86_entry_t *ent;
 144        unsigned int i;
 145        int j, k, added, skip;
 146        int idx;
 147
 148        k = e->nattrs;
 149        ent = pe+e->event;
 150
 151        for(i=0; msk; msk >>=1, i++) {
 152
 153                if (!(msk & 0x1))
 154                        continue;
 155
 156                added = skip = 0;
 157
 158                for (j = 0; j < e->npattrs; j++) {
 159                        if (e->pattrs[j].ctrl != PFM_ATTR_CTRL_PMU)
 160                                continue;
 161
 162                        if (e->pattrs[j].type != PFM_ATTR_UMASK)
 163                                continue;
 164
 165                        idx = e->pattrs[j].idx;
 166
 167                        if (ent->umasks[idx].grpid != i)
 168                                continue;
 169
 170                        if (max_grpid != INTEL_X86_MAX_GRPID && i > max_grpid) {
 171                                skip = 1;
 172                                continue;
 173                        }
 174
 175                        if (intel_x86_uflag(this, e->event, idx, INTEL_X86_GRP_DFL_NONE)) {
 176                                skip = 1;
 177                                continue;
 178                        }
 179
 180                        /* umask is default for group */
 181                        if (intel_x86_uflag(this, e->event, idx, INTEL_X86_DFL)) {
 182                                DPRINT("added default %s for group %d j=%d idx=%d ucode=0x%"PRIx64"\n",
 183                                        ent->umasks[idx].uname,
 184                                        i,      
 185                                        j,
 186                                        idx,
 187                                        ent->umasks[idx].ucode);
 188                                /*
 189                                 * default could be an alias, but
 190                                 * ucode must reflect actual code
 191                                 */
 192                                *umask |= ent->umasks[idx].ucode >> 8;
 193
 194                                filters[0].val |= pe[e->event].umasks[idx].ufilters[0];
 195                                filters[1].val |= pe[e->event].umasks[idx].ufilters[1];
 196
 197                                e->attrs[k].id = j; /* pattrs index */
 198                                e->attrs[k].ival = 0;
 199                                k++;
 200
 201                                added++;
 202                                if (intel_x86_eflag(this, e->event, INTEL_X86_GRP_EXCL))
 203                                        goto done;
 204
 205                                if (intel_x86_uflag(this, e->event, idx, INTEL_X86_EXCL_GRP_GT)) {
 206                                        if (max_grpid != INTEL_X86_MAX_GRPID) {
 207                                                DPRINT("two max_grpid, old=%d new=%d\n", max_grpid, ent->umasks[idx].grpid);
 208                                                return PFM_ERR_UMASK;
 209                                        }
 210                                        max_grpid = ent->umasks[idx].grpid;
 211                                }
 212                        }
 213                }
 214                if (!added && !skip) {
 215                        DPRINT("no default found for event %s unit mask group %d (max_grpid=%d)\n", ent->name, i, max_grpid);
 216                        return PFM_ERR_UMASK;
 217                }
 218        }
 219        DPRINT("max_grpid=%d nattrs=%d k=%d umask=0x%"PRIx64"\n", max_grpid, e->nattrs, k, *umask);
 220done:
 221        e->nattrs = k;
 222        return PFM_SUCCESS;
 223}
 224
 225
 226/*
 227 * common encoding routine
 228 */
 229int
 230pfm_intel_snbep_unc_get_encoding(void *this, pfmlib_event_desc_t *e)
 231{
 232        const intel_x86_entry_t *pe = this_pe(this);
 233        unsigned int grpmsk, ugrpmsk = 0;
 234        unsigned int max_grpid = INTEL_X86_MAX_GRPID;
 235        unsigned int last_grpid =  INTEL_X86_MAX_GRPID;
 236        int umodmsk = 0, modmsk_r = 0;
 237        int pcu_filt_band = -1;
 238        pfm_snbep_unc_reg_t reg;
 239        pfm_snbep_unc_reg_t filters[INTEL_X86_MAX_FILTERS];
 240        pfm_snbep_unc_reg_t addr;
 241        pfm_event_attr_info_t *a;
 242        uint64_t val, umask1, umask2;
 243        int k, ret;
 244        int has_cbo_tid = 0;
 245        unsigned int grpid;
 246        int grpcounts[INTEL_X86_NUM_GRP];
 247        int ncombo[INTEL_X86_NUM_GRP];
 248        char umask_str[PFMLIB_EVT_MAX_NAME_LEN];
 249
 250        memset(grpcounts, 0, sizeof(grpcounts));
 251        memset(ncombo, 0, sizeof(ncombo));
 252        memset(filters, 0, sizeof(filters));
 253
 254        addr.val = 0;
 255
 256        pe = this_pe(this);
 257
 258        umask_str[0] = e->fstr[0] = '\0';
 259
 260        reg.val = val = pe[e->event].code;
 261
 262        /* take into account hardcoded umask */
 263        umask1 = (val >> 8) & 0xff;
 264        umask2 = umask1;
 265
 266        grpmsk = (1 << pe[e->event].ngrp)-1;
 267
 268        modmsk_r = pe[e->event].modmsk_req;
 269
 270        for(k=0; k < e->nattrs; k++) {
 271                a = attr(e, k);
 272
 273                if (a->ctrl != PFM_ATTR_CTRL_PMU)
 274                        continue;
 275
 276                if (a->type == PFM_ATTR_UMASK) {
 277                        uint64_t um;
 278
 279                        grpid = pe[e->event].umasks[a->idx].grpid;
 280
 281                        /*
 282                         * certain event groups are meant to be
 283                         * exclusive, i.e., only unit masks of one group
 284                         * can be used
 285                         */
 286                        if (last_grpid != INTEL_X86_MAX_GRPID && grpid != last_grpid
 287                            && intel_x86_eflag(this, e->event, INTEL_X86_GRP_EXCL)) {
 288                                DPRINT("exclusive unit mask group error\n");
 289                                return PFM_ERR_FEATCOMB;
 290                        }
 291
 292                        /*
 293                         * selecting certain umasks in a group may exclude any umasks
 294                         * from any groups with a higher index
 295                         *
 296                         * enforcement requires looking at the grpid of all the umasks
 297                         */
 298                        if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_EXCL_GRP_GT))
 299                                max_grpid = grpid;
 300
 301                        /*
 302                         * certain event groups are meant to be
 303                         * exclusive, i.e., only unit masks of one group
 304                         * can be used
 305                         */
 306                        if (last_grpid != INTEL_X86_MAX_GRPID && grpid != last_grpid
 307                            && intel_x86_eflag(this, e->event, INTEL_X86_GRP_EXCL)) {
 308                                DPRINT("exclusive unit mask group error\n");
 309                                return PFM_ERR_FEATCOMB;
 310                        }
 311                        /*
 312                         * upper layer has removed duplicates
 313                         * so if we come here more than once, it is for two
 314                         * disinct umasks
 315                         *
 316                         * NCOMBO=no combination of unit masks within the same
 317                         * umask group
 318                         */
 319                        ++grpcounts[grpid];
 320
 321                        /* mark that we have a umask with NCOMBO in this group */
 322                        if (intel_x86_uflag(this, e->event, a->idx, INTEL_X86_NCOMBO))
 323                                ncombo[grpid] = 1;
 324
 325                        /*
 326                         * if more than one umask in this group but one is marked
 327                         * with ncombo, then fail. It is okay to combine umask within
 328                         * a group as long as none is tagged with NCOMBO
 329                         */
 330                        if (grpcounts[grpid] > 1 && ncombo[grpid])  {
 331                                DPRINT("umask %s does not support unit mask combination within group %d\n", pe[e->event].umasks[a->idx].uname, grpid);
 332                                return PFM_ERR_FEATCOMB;
 333                        }
 334
 335                        last_grpid = grpid;
 336
 337                        um = pe[e->event].umasks[a->idx].ucode;
 338                        filters[0].val |= pe[e->event].umasks[a->idx].ufilters[0];
 339                        filters[1].val |= pe[e->event].umasks[a->idx].ufilters[1];
 340
 341                        um >>= 8;
 342                        umask2  |= um;
 343
 344                        ugrpmsk |= 1 << pe[e->event].umasks[a->idx].grpid;
 345
 346                        /* PCU occ event */
 347                        if (is_occ_event(this, e->event)) {
 348                                reg.pcu.unc_occ = umask2 >> 6;
 349                                umask2 = 0;
 350                        } else
 351                                reg.val |= umask2 << 8;
 352
 353                        evt_strcat(umask_str, ":%s", pe[e->event].umasks[a->idx].uname);
 354
 355                        modmsk_r |= pe[e->event].umasks[a->idx].umodmsk_req;
 356
 357                } else if (a->type == PFM_ATTR_RAW_UMASK) {
 358
 359                        /* there can only be one RAW_UMASK per event */
 360
 361                        /* sanity check */
 362                        if (a->idx & ~0xff) {
 363                                DPRINT("raw umask is 8-bit wide\n");
 364                                return PFM_ERR_ATTR;
 365                        }
 366                        /* override umask */
 367                        umask2 = a->idx & 0xff;
 368                        ugrpmsk = grpmsk;
 369                } else {
 370                        uint64_t ival = e->attrs[k].ival;
 371                        switch(a->idx) {
 372                                case SNBEP_UNC_ATTR_I: /* invert */
 373                                        if (is_occ_event(this, e->event))
 374                                                reg.pcu.unc_occ_inv = !!ival;
 375                                        else
 376                                                reg.com.unc_inv = !!ival;
 377                                        umodmsk |= _SNBEP_UNC_ATTR_I;
 378                                        break;
 379                                case SNBEP_UNC_ATTR_E: /* edge */
 380                                        if (is_occ_event(this, e->event))
 381                                                reg.pcu.unc_occ_edge = !!ival;
 382                                        else
 383                                                reg.com.unc_edge = !!ival;
 384                                        umodmsk |= _SNBEP_UNC_ATTR_E;
 385                                        break;
 386                                case SNBEP_UNC_ATTR_T8: /* counter-mask */
 387                                        /* already forced, cannot overwrite */
 388                                        if (ival > 255)
 389                                                return PFM_ERR_ATTR_VAL;
 390                                        reg.com.unc_thres = ival;
 391                                        umodmsk |= _SNBEP_UNC_ATTR_T8;
 392                                        break;
 393                                case SNBEP_UNC_ATTR_T5: /* pcu counter-mask */
 394                                        /* already forced, cannot overwrite */
 395                                        if (ival > 31)
 396                                                return PFM_ERR_ATTR_VAL;
 397                                        reg.pcu.unc_thres = ival;
 398                                        umodmsk |= _SNBEP_UNC_ATTR_T5;
 399                                        break;
 400                                case SNBEP_UNC_ATTR_TF: /* thread id */
 401                                        if (ival > 1) {
 402                                                DPRINT("invalid thread id, must be < 1");
 403                                                return PFM_ERR_ATTR_VAL;
 404                                        }
 405                                        reg.cbo.unc_tid = 1;
 406                                        has_cbo_tid = 1;
 407                                        filters[0].cbo_filt.tid = ival;
 408                                        umodmsk |= _SNBEP_UNC_ATTR_TF;
 409                                        break;
 410                                case SNBEP_UNC_ATTR_CF: /* core id */
 411                                        if (ival > 15)
 412                                                return PFM_ERR_ATTR_VAL;
 413                                        reg.cbo.unc_tid = 1;
 414                                        filters[0].cbo_filt.cid = ival;
 415                                        has_cbo_tid = 1;
 416                                        umodmsk |= _SNBEP_UNC_ATTR_CF;
 417                                        break;
 418                                case SNBEP_UNC_ATTR_NF: /* node id filter0 */
 419                                        if (ival > 255 || ival == 0) {
 420                                                DPRINT("invalid nf,  0 < nf < 256\n");
 421                                                return PFM_ERR_ATTR_VAL;
 422                                        }
 423                                        filters[0].cbo_filt.nid = ival;
 424                                        umodmsk |= _SNBEP_UNC_ATTR_NF;
 425                                        break;
 426                                case SNBEP_UNC_ATTR_NF1: /* node id filter1 */
 427                                        if (ival > 255 || ival == 0) {
 428                                                DPRINT("invalid nf,  0 < nf < 256\n");
 429                                                return PFM_ERR_ATTR_VAL;
 430                                        }
 431                                        filters[1].ivbep_cbo_filt1.nid = ival;
 432                                        umodmsk |= _SNBEP_UNC_ATTR_NF1;
 433                                        break;
 434                                case SNBEP_UNC_ATTR_FF: /* freq band filter */
 435                                        if (ival > 255)
 436                                                return PFM_ERR_ATTR_VAL;
 437                                        pcu_filt_band = get_pcu_filt_band(this, reg);
 438                                        filters[0].val = ival << (pcu_filt_band * 8);
 439                                        umodmsk |= _SNBEP_UNC_ATTR_FF;
 440                                        break;
 441                                case SNBEP_UNC_ATTR_A: /* addr filter */
 442                                        if (ival & ~((1ULL << 40)-1)) {
 443                                                DPRINT("address filter 40bits max\n");
 444                                                return PFM_ERR_ATTR_VAL;
 445                                        }
 446                                        addr.ha_addr.lo_addr = ival; /* LSB 26 bits */
 447                                        addr.ha_addr.hi_addr = (ival >> 26) & ((1ULL << 14)-1);
 448                                        umodmsk |= _SNBEP_UNC_ATTR_A;
 449                                        break;
 450                                case SNBEP_UNC_ATTR_ISOC: /* isoc filter */
 451                                        filters[1].ivbep_cbo_filt1.isoc = !!ival;
 452                                        break;
 453                                case SNBEP_UNC_ATTR_NC: /* nc filter */
 454                                        filters[1].ivbep_cbo_filt1.nc = !!ival;
 455                                        break;
 456                        }
 457                }
 458        }
 459        /*
 460         * check that there is at least of unit mask in each unit mask group
 461         */
 462        if (pe[e->event].numasks && (ugrpmsk != grpmsk || ugrpmsk == 0)) {
 463                uint64_t um = 0;
 464                ugrpmsk ^= grpmsk;
 465                ret = snbep_unc_add_defaults(this, e, ugrpmsk, &um, filters, max_grpid);
 466                if (ret != PFM_SUCCESS)
 467                        return ret;
 468                umask2 |= um;
 469        }
 470
 471        /*
 472         * nf= is only required on some events in CBO
 473         */
 474        if (!(modmsk_r & _SNBEP_UNC_ATTR_NF) && (umodmsk & _SNBEP_UNC_ATTR_NF)) {
 475                DPRINT("using nf= on an umask which does not require it\n");
 476                return PFM_ERR_ATTR;
 477        }
 478        if (!(modmsk_r & _SNBEP_UNC_ATTR_NF1) && (umodmsk & _SNBEP_UNC_ATTR_NF1)) {
 479                DPRINT("using nf= on an umask which does not require it\n");
 480                return PFM_ERR_ATTR;
 481        }
 482
 483        if (modmsk_r && !(umodmsk & modmsk_r)) {
 484                DPRINT("required modifiers missing: 0x%x\n", modmsk_r);
 485                return PFM_ERR_ATTR;
 486        }
 487
 488        evt_strcat(e->fstr, "%s", pe[e->event].name);
 489        pfmlib_sort_attr(e);
 490
 491        for(k = 0; k < e->nattrs; k++) {
 492                a = attr(e, k);
 493                if (a->ctrl != PFM_ATTR_CTRL_PMU)
 494                        continue;
 495                if (a->type == PFM_ATTR_UMASK)
 496                        evt_strcat(e->fstr, ":%s", pe[e->event].umasks[a->idx].uname);
 497                else if (a->type == PFM_ATTR_RAW_UMASK)
 498                        evt_strcat(e->fstr, ":0x%x", a->idx);
 499        }
 500        DPRINT("umask2=0x%"PRIx64" umask1=0x%"PRIx64"\n", umask2, umask1);
 501        e->count = 0;
 502        reg.val |= (umask1 | umask2)  << 8;
 503
 504        e->codes[e->count++] = reg.val;
 505
 506        /*
 507         * handles C-box filter
 508         */
 509        if (filters[0].val || filters[1].val || has_cbo_tid)
 510                e->codes[e->count++] = filters[0].val;
 511        if (filters[1].val)
 512                e->codes[e->count++] = filters[1].val;
 513
 514        /* HA address matcher */
 515        if (addr.val)
 516                e->codes[e->count++] = addr.val;
 517
 518        for (k = 0; k < e->npattrs; k++) {
 519                int idx;
 520
 521                if (e->pattrs[k].ctrl != PFM_ATTR_CTRL_PMU)
 522                        continue;
 523
 524                if (e->pattrs[k].type == PFM_ATTR_UMASK)
 525                        continue;
 526
 527                idx = e->pattrs[k].idx;
 528                switch(idx) {
 529                case SNBEP_UNC_ATTR_E:
 530                        if (is_occ_event(this, e->event))
 531                                evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.pcu.unc_occ_edge);
 532                        else
 533                                evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.com.unc_edge);
 534                        break;
 535                case SNBEP_UNC_ATTR_I:
 536                        if (is_occ_event(this, e->event))
 537                                evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.pcu.unc_occ_inv);
 538                        else
 539                                evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.com.unc_inv);
 540                        break;
 541                case SNBEP_UNC_ATTR_T8:
 542                        evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.com.unc_thres);
 543                        break;
 544                case SNBEP_UNC_ATTR_T5:
 545                        evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.pcu.unc_thres);
 546                        break;
 547                case SNBEP_UNC_ATTR_TF:
 548                        evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, reg.cbo.unc_tid);
 549                        break;
 550                case SNBEP_UNC_ATTR_CF:
 551                        evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[0].cbo_filt.cid);
 552                        break;
 553                case SNBEP_UNC_ATTR_FF:
 554                        evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, (filters[0].val >> (pcu_filt_band*8)) & 0xff);
 555                        break;
 556                case SNBEP_UNC_ATTR_ISOC:
 557                        evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[1].ivbep_cbo_filt1.isoc);
 558                        break;
 559                case SNBEP_UNC_ATTR_NC:
 560                        evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[1].ivbep_cbo_filt1.nc);
 561                        break;
 562                case SNBEP_UNC_ATTR_NF:
 563                        if (modmsk_r & _SNBEP_UNC_ATTR_NF)
 564                                evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[0].cbo_filt.nid);
 565                        break;
 566                case SNBEP_UNC_ATTR_NF1:
 567                        if (modmsk_r & _SNBEP_UNC_ATTR_NF1)
 568                                evt_strcat(e->fstr, ":%s=%lu", snbep_unc_mods[idx].name, filters[1].ivbep_cbo_filt1.nid);
 569                        break;
 570                case SNBEP_UNC_ATTR_A:
 571                        evt_strcat(e->fstr, ":%s=0x%lx", snbep_unc_mods[idx].name,
 572                                   addr.ha_addr.hi_addr << 26 | addr.ha_addr.lo_addr);
 573                        break;
 574                }
 575        }
 576        display_reg(this, e, reg);
 577        return PFM_SUCCESS;
 578}
 579
 580int
 581pfm_intel_snbep_unc_can_auto_encode(void *this, int pidx, int uidx)
 582{
 583        if (intel_x86_eflag(this, pidx, INTEL_X86_NO_AUTOENCODE))
 584                return 0;
 585
 586        return !intel_x86_uflag(this, pidx, uidx, INTEL_X86_NO_AUTOENCODE);
 587}
 588
 589int
 590pfm_intel_snbep_unc_get_event_attr_info(void *this, int pidx, int attr_idx, pfm_event_attr_info_t *info)
 591{
 592        const intel_x86_entry_t *pe = this_pe(this);
 593        const pfmlib_attr_desc_t *atdesc = this_atdesc(this);
 594        int numasks, idx;
 595
 596        numasks = intel_x86_num_umasks(this, pidx);
 597        if (attr_idx < numasks) {
 598                idx = intel_x86_attr2umask(this, pidx, attr_idx);
 599                info->name = pe[pidx].umasks[idx].uname;
 600                info->desc = pe[pidx].umasks[idx].udesc;
 601                info->equiv= pe[pidx].umasks[idx].uequiv;
 602
 603                info->code = pe[pidx].umasks[idx].ucode;
 604
 605                if (!intel_x86_uflag(this, pidx, idx, INTEL_X86_CODE_OVERRIDE))
 606                        info->code >>= 8;
 607
 608                if (info->code == 0)
 609                        info->code = pe[pidx].umasks[idx].ufilters[0];
 610
 611                info->type = PFM_ATTR_UMASK;
 612                info->is_dfl = intel_x86_uflag(this, pidx, idx, INTEL_X86_DFL);
 613                info->is_precise = intel_x86_uflag(this, pidx, idx, INTEL_X86_PEBS);
 614        } else {
 615                idx = intel_x86_attr2mod(this, pidx, attr_idx);
 616                info->name = atdesc[idx].name;
 617                info->desc = atdesc[idx].desc;
 618                info->type = atdesc[idx].type;
 619                info->equiv= NULL;
 620                info->code = idx;
 621                info->is_dfl = 0;
 622                info->is_precise = 0;
 623        }
 624
 625        info->ctrl = PFM_ATTR_CTRL_PMU;
 626        info->idx = idx; /* namespace specific index */
 627        info->dfl_val64 = 0;
 628
 629        return PFM_SUCCESS;
 630}
 631