akaros/user/perfmon/pfmlib_intel_netburst.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2005-2006 Hewlett-Packard Development Company, L.P.
   3 * Copyright (c) 2006 IBM Corp.
   4 * Contributed by Kevin Corry <kevcorry@us.ibm.com>
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a
   7 * copy of this software and associated documentation files (the "Software"),
   8 * to deal in the Software without restriction, including without limitation
   9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10 * and/or sell copies of the Software, and to permit persons to whom the
  11 * Software is furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  22 * IN THE SOFTWARE.
  23 *
  24 * pfmlib_intel_netburst.c
  25 *
  26 * Support for the Pentium4/Xeon/EM64T processor family (family=15).
  27 */
  28/* private headers */
  29#include "pfmlib_priv.h"
  30#include "pfmlib_intel_netburst_priv.h"
  31#include "pfmlib_intel_x86_priv.h"
  32#include "events/intel_netburst_events.h"
  33
  34const pfmlib_attr_desc_t netburst_mods[]={
  35        PFM_ATTR_B("u", "monitor at priv level 1, 2, 3"),       /* monitor priv level 1, 2, 3 */
  36        PFM_ATTR_B("k", "monitor at priv level 0"),             /* monitor priv level 0 */
  37        PFM_ATTR_B("cmpl", "complement"),                       /* set: <=, clear: > */
  38        PFM_ATTR_B("e", "edge"),                                /* edge */
  39        PFM_ATTR_I("thr", "event threshold in range [0-15]"),   /* threshold */
  40};
  41#define NETBURST_MODS_COUNT (sizeof(netburst_mods)/sizeof(pfmlib_attr_desc_t))
  42
  43
  44extern pfmlib_pmu_t netburst_support;
  45
  46static inline int
  47netburst_get_numasks(int pidx)
  48{
  49        int i = 0;
  50        /*
  51         * name = NULL is end-marker
  52         */
  53        while (netburst_events[pidx].event_masks[i].name)
  54                i++;
  55        return i;
  56}
  57
  58static void
  59netburst_display_reg(pfmlib_event_desc_t *e)
  60{
  61        netburst_escr_value_t escr;
  62        netburst_cccr_value_t cccr;
  63
  64        escr.val = e->codes[0];
  65        cccr.val = e->codes[1];
  66
  67        __pfm_vbprintf("[0x%"PRIx64" 0x%"PRIx64" 0x%"PRIx64" usr=%d os=%d tag_ena=%d tag_val=%d "
  68                       "evmask=0x%x evsel=0x%x escr_sel=0x%x comp=%d cmpl=%d thr=%d e=%d",
  69                        escr,
  70                        cccr,
  71                        e->codes[2], /* perf_event code */
  72                        escr.bits.t0_usr, /* t1 is identical */
  73                        escr.bits.t0_os,  /* t1 is identical */
  74                        escr.bits.tag_enable,
  75                        escr.bits.tag_value,
  76                        escr.bits.event_mask,
  77                        escr.bits.event_select,
  78                        cccr.bits.escr_select,
  79                        cccr.bits.compare,
  80                        cccr.bits.complement,
  81                        cccr.bits.threshold,
  82                        cccr.bits.edge);
  83
  84        __pfm_vbprintf("] %s\n", e->fstr);
  85}
  86
  87static int
  88netburst_add_defaults(pfmlib_event_desc_t *e, unsigned int *evmask)
  89{
  90        int i, n;
  91
  92        n = netburst_get_numasks(e->event);
  93
  94        for (i = 0; i < n; i++) {
  95
  96                if (netburst_events[e->event].event_masks[i].flags & NETBURST_FL_DFL)
  97                        goto found;
  98        }
  99        return PFM_ERR_ATTR;
 100found:
 101        *evmask = 1 << netburst_events[e->event].event_masks[i].bit;
 102        n = e->nattrs;
 103        e->attrs[n].id = i;
 104        e->attrs[n].ival = i;
 105        e->nattrs = n+1;
 106
 107        return PFM_SUCCESS;
 108}
 109
 110int
 111pfm_netburst_get_encoding(void *this, pfmlib_event_desc_t *e)
 112{
 113        pfm_event_attr_info_t *a;
 114        netburst_escr_value_t escr;
 115        netburst_cccr_value_t cccr;
 116        unsigned int evmask = 0;
 117        unsigned int plmmsk = 0;
 118        int umask_done = 0;
 119        const char *n;
 120        int k, id, bit, ret;
 121        int tag_enable = 0, tag_value = 0;
 122
 123        e->fstr[0] = '\0';
 124
 125        escr.val = 0;
 126        cccr.val = 0;
 127
 128        for(k=0; k < e->nattrs; k++) {
 129                a = attr(e, k);
 130
 131                if (a->ctrl != PFM_ATTR_CTRL_PMU)
 132                        continue;
 133
 134                if (a->type == PFM_ATTR_UMASK) {
 135
 136                        bit = netburst_events[e->event].event_masks[a->idx].bit;
 137                        n   = netburst_events[e->event].event_masks[a->idx].name;
 138                        /*
 139                         * umask combination seems possible, although it does
 140                         * not always make sense, e.g., BOGUS vs. NBOGUS
 141                         */
 142                        if (bit < EVENT_MASK_BITS && n) {
 143                                evmask |= (1 << bit);
 144                        } else  if (bit >= EVENT_MASK_BITS && n) {
 145                                tag_value |= (1 << (bit - EVENT_MASK_BITS));
 146                                tag_enable = 1;
 147                        }
 148                        umask_done = 1;
 149                } else if (a->type == PFM_ATTR_RAW_UMASK) {
 150                        /* should not happen */
 151                        return PFM_ERR_ATTR;
 152                } else {
 153                        uint64_t ival = e->attrs[k].ival;
 154                        switch (a->idx) {
 155                        case NETBURST_ATTR_U:
 156                                escr.bits.t1_usr = !!ival;
 157                                escr.bits.t0_usr = !!ival;
 158                                plmmsk |= _NETBURST_ATTR_U;
 159                                break;
 160                        case NETBURST_ATTR_K:
 161                                escr.bits.t1_os = !!ival;
 162                                escr.bits.t0_os = !!ival;
 163                                plmmsk |= _NETBURST_ATTR_K;
 164                                break;
 165                        case NETBURST_ATTR_E:
 166                                if (ival) {
 167                                        cccr.bits.compare = 1;
 168                                        cccr.bits.edge = 1;
 169                                }
 170                                break;
 171                        case NETBURST_ATTR_C:
 172                                if (ival) {
 173                                        cccr.bits.compare = 1;
 174                                        cccr.bits.complement = 1;
 175                                }
 176                                break;
 177                        case NETBURST_ATTR_T:
 178                                if (ival > 15)
 179                                        return PFM_ERR_ATTR_VAL;
 180
 181                                if (ival) {
 182                                        cccr.bits.compare = 1;
 183                                        cccr.bits.threshold = ival;
 184                                }
 185                                break;
 186                        default:
 187                                return PFM_ERR_ATTR;
 188                        }
 189                }
 190        }
 191        /*
 192         * handle case where no priv level mask was passed.
 193         * then we use the dfl_plm
 194         */
 195        if (!(plmmsk & (_NETBURST_ATTR_K|_NETBURST_ATTR_U))) {
 196                if (e->dfl_plm & PFM_PLM0) {
 197                        escr.bits.t1_os = 1;
 198                        escr.bits.t0_os = 1;
 199                }
 200                if (e->dfl_plm & PFM_PLM3) {
 201                        escr.bits.t1_usr = 1;
 202                        escr.bits.t0_usr = 1;
 203                }
 204        }
 205
 206        if (!umask_done) {
 207                ret = netburst_add_defaults(e, &evmask);
 208                if (ret != PFM_SUCCESS)
 209                        return ret;
 210        }
 211
 212        escr.bits.tag_enable   = tag_enable;
 213        escr.bits.tag_value    = tag_value;
 214        escr.bits.event_mask   = evmask;
 215        escr.bits.event_select = netburst_events[e->event].event_select;
 216
 217
 218        cccr.bits.enable        = 1;
 219        cccr.bits.escr_select   = netburst_events[e->event].escr_select;
 220        cccr.bits.active_thread = 3;
 221
 222        if (e->event == PME_REPLAY_EVENT)
 223                escr.bits.event_mask &= P4_REPLAY_REAL_MASK;     /* remove virtual mask bits */
 224
 225        /*
 226         * reorder all the attributes such that the fstr appears always
 227         * the same regardless of how the attributes were submitted.
 228         */
 229        evt_strcat(e->fstr, "%s", netburst_events[e->event].name);
 230        pfmlib_sort_attr(e);
 231        for(k=0; k < e->nattrs; k++) {
 232                a = attr(e, k);
 233                if (a->ctrl != PFM_ATTR_CTRL_PMU)
 234                        continue;
 235                if (a->type == PFM_ATTR_UMASK) {
 236                        id = e->attrs[k].id;
 237                        evt_strcat(e->fstr, ":%s", netburst_events[e->event].event_masks[id].name);
 238                }
 239        }
 240
 241        evt_strcat(e->fstr, ":%s=%lu", netburst_mods[NETBURST_ATTR_K].name, escr.bits.t0_os);
 242        evt_strcat(e->fstr, ":%s=%lu", netburst_mods[NETBURST_ATTR_U].name, escr.bits.t0_usr);
 243        evt_strcat(e->fstr, ":%s=%lu", netburst_mods[NETBURST_ATTR_E].name, cccr.bits.edge);
 244        evt_strcat(e->fstr, ":%s=%lu", netburst_mods[NETBURST_ATTR_C].name, cccr.bits.complement);
 245        evt_strcat(e->fstr, ":%s=%lu", netburst_mods[NETBURST_ATTR_T].name, cccr.bits.threshold);
 246
 247        e->count = 2;
 248        e->codes[0] = escr.val;
 249        e->codes[1] = cccr.val;
 250
 251        netburst_display_reg(e);
 252
 253        return PFM_SUCCESS;
 254}
 255
 256static int
 257pfm_netburst_detect(void *this)
 258{
 259        int ret;
 260        int model;
 261
 262        ret = pfm_intel_x86_detect();
 263        if (ret != PFM_SUCCESS)
 264                return ret;
 265
 266        if (pfm_intel_x86_cfg.family != 15)
 267                return PFM_ERR_NOTSUPP;
 268
 269        model = pfm_intel_x86_cfg.model;
 270        if (model == 3 || model == 4 || model == 6)
 271                return PFM_ERR_NOTSUPP;
 272
 273        return PFM_SUCCESS;
 274}
 275
 276static int
 277pfm_netburst_detect_prescott(void *this)
 278{
 279        int ret;
 280        int model;
 281
 282        ret = pfm_intel_x86_detect();
 283        if (ret != PFM_SUCCESS)
 284                return ret;
 285
 286        if (pfm_intel_x86_cfg.family != 15)
 287                return PFM_ERR_NOTSUPP;
 288
 289        /*
 290         * prescott has one more event (instr_completed)
 291         */
 292        model = pfm_intel_x86_cfg.model;
 293        if (model != 3 && model != 4 && model != 6)
 294                return PFM_ERR_NOTSUPP;
 295
 296        return PFM_SUCCESS;
 297}
 298
 299static int
 300pfm_netburst_get_event_first(void *this)
 301{
 302        pfmlib_pmu_t *p = this;
 303        return p->pme_count ? 0 : -1;
 304}
 305
 306static int
 307pfm_netburst_get_event_next(void *this, int idx)
 308{
 309        pfmlib_pmu_t *p = this;
 310
 311        if (idx >= (p->pme_count-1))
 312                return -1;
 313
 314        return idx+1;
 315}
 316
 317static int
 318pfm_netburst_event_is_valid(void *this, int pidx)
 319{
 320        pfmlib_pmu_t *p = this;
 321        return pidx >= 0 && pidx < p->pme_count;
 322}
 323
 324static int
 325pfm_netburst_get_event_attr_info(void *this, int pidx, int attr_idx, pfm_event_attr_info_t *info)
 326{
 327        const netburst_entry_t *pe = this_pe(this);
 328        int numasks, idx;
 329
 330        numasks = netburst_get_numasks(pidx);
 331        if (attr_idx < numasks) {
 332                //idx = pfm_intel_x86_attr2umask(this, pidx, attr_idx);
 333                idx = attr_idx;
 334                info->name = pe[pidx].event_masks[idx].name;
 335                info->desc = pe[pidx].event_masks[idx].desc;
 336                info->equiv= NULL;
 337                info->code = pe[pidx].event_masks[idx].bit;
 338                info->type = PFM_ATTR_UMASK;
 339                info->is_dfl = !!(pe[pidx].event_masks[idx].flags & NETBURST_FL_DFL);
 340        } else {
 341                idx = attr_idx - numasks;
 342                info->name = netburst_mods[idx].name;
 343                info->desc = netburst_mods[idx].desc;
 344                info->equiv= NULL;
 345                info->code = idx;
 346                info->type = netburst_mods[idx].type;
 347                info->is_dfl = 0;
 348        }
 349        info->ctrl = PFM_ATTR_CTRL_PMU;
 350        info->idx = idx; /* namespace specific index */
 351        info->dfl_val64 = 0;
 352
 353        return PFM_SUCCESS;
 354}
 355
 356static int
 357pfm_netburst_get_event_info(void *this, int idx, pfm_event_info_t *info)
 358{
 359        const netburst_entry_t *pe = this_pe(this);
 360        pfmlib_pmu_t *pmu = this;
 361
 362        /*
 363         * pmu and idx filled out by caller
 364         */
 365        info->name  = pe[idx].name;
 366        info->desc  = pe[idx].desc;
 367        info->code  = pe[idx].event_select | (pe[idx].escr_select << 8);
 368        info->equiv = NULL;
 369        info->idx   = idx; /* private index */
 370        info->pmu   = pmu->pmu;
 371
 372        info->nattrs  = netburst_get_numasks(idx);
 373        info->nattrs += NETBURST_MODS_COUNT;
 374
 375        return PFM_SUCCESS;
 376}
 377
 378static int
 379pfm_netburst_validate_table(void *this, FILE *fp)
 380{
 381        pfmlib_pmu_t *pmu = this;
 382        const netburst_entry_t *pe = netburst_events;
 383        const char *name =  pmu->name;
 384        int i, j, noname, ndfl;
 385        int error = 0;
 386
 387        for(i=0; i < pmu->pme_count; i++) {
 388
 389                if (!pe[i].name) {
 390                        fprintf(fp, "pmu: %s event%d: :: no name (prev event was %s)\n", pmu->name, i,
 391                        i > 1 ? pe[i-1].name : "??");
 392                        error++;
 393                }
 394
 395                if (!pe[i].desc) {
 396                        fprintf(fp, "pmu: %s event%d: %s :: no description\n", name, i, pe[i].name);
 397                        error++;
 398                }
 399
 400                noname = ndfl = 0;
 401
 402                /* name = NULL is end-marker, veryfy there is at least one */
 403                for(j= 0; j < EVENT_MASK_BITS; j++) {
 404
 405                        if (!pe[i].event_masks[j].name)
 406                                noname++;
 407
 408                        if (pe[i].event_masks[j].name) {
 409                                if (!pe[i].event_masks[j].desc) {
 410                                        fprintf(fp, "pmu: %s event%d:%s umask%d: %s :: no description\n", name, i, pe[i].name, j, pe[i].event_masks[j].name);
 411                                        error++;
 412                                }
 413                                if (pe[i].event_masks[j].bit >= (EVENT_MASK_BITS+4)) {
 414                                        fprintf(fp, "pmu: %s event%d:%s umask%d: %s :: invalid bit field\n", name, i, pe[i].name, j, pe[i].event_masks[j].name);
 415                                        error++;
 416                                }
 417
 418                                if (pe[i].event_masks[j].flags & NETBURST_FL_DFL)
 419                                        ndfl++;
 420                        }
 421                }
 422                if (ndfl > 1) {
 423                        fprintf(fp, "pmu: %s event%d:%s :: more than one default umask\n", name, i, pe[i].name);
 424                        error++;
 425                }
 426                if (!noname) {
 427                        fprintf(fp, "pmu: %s event%d:%s :: no event mask end-marker\n", name, i, pe[i].name);
 428                        error++;
 429                }
 430        }
 431        return error ? PFM_ERR_INVAL : PFM_SUCCESS;
 432}
 433
 434
 435static unsigned int
 436pfm_netburst_get_event_nattrs(void *this, int pidx)
 437{
 438        unsigned int nattrs;
 439        nattrs  = netburst_get_numasks(pidx);
 440        nattrs += NETBURST_MODS_COUNT;
 441        return nattrs;
 442}
 443
 444
 445pfmlib_pmu_t netburst_support = {
 446        .desc                   = "Pentium4",
 447        .name                   = "netburst",
 448        .pmu                    = PFM_PMU_INTEL_NETBURST,
 449        .pme_count              = LIBPFM_ARRAY_SIZE(netburst_events) - 1,
 450        .type                   = PFM_PMU_TYPE_CORE,
 451        .supported_plm          = INTEL_X86_PLM,
 452        .atdesc                 = netburst_mods,
 453        .pe                     = netburst_events,
 454        .max_encoding           = 3,
 455        .num_cntrs              = 18,
 456
 457        .pmu_detect             = pfm_netburst_detect,
 458        .get_event_encoding[PFM_OS_NONE] = pfm_netburst_get_encoding,
 459         PFMLIB_ENCODE_PERF(pfm_netburst_get_perf_encoding),
 460        .get_event_first        = pfm_netburst_get_event_first,
 461        .get_event_next         = pfm_netburst_get_event_next,
 462        .event_is_valid         = pfm_netburst_event_is_valid,
 463        .validate_table         = pfm_netburst_validate_table,
 464        .get_event_info         = pfm_netburst_get_event_info,
 465        .get_event_attr_info    = pfm_netburst_get_event_attr_info,
 466        .get_event_nattrs       = pfm_netburst_get_event_nattrs,
 467         PFMLIB_VALID_PERF_PATTRS(pfm_netburst_perf_validate_pattrs),
 468};
 469
 470pfmlib_pmu_t netburst_p_support = {
 471        .desc                   = "Pentium4 (Prescott)",
 472        .name                   = "netburst_p",
 473        .pmu                    = PFM_PMU_INTEL_NETBURST_P,
 474        .pme_count              = LIBPFM_ARRAY_SIZE(netburst_events),
 475        .type                   = PFM_PMU_TYPE_CORE,
 476        .supported_plm          = INTEL_X86_PLM,
 477        .atdesc                 = netburst_mods,
 478        .pe                     = netburst_events,
 479        .max_encoding           = 3,
 480        .num_cntrs              = 18,
 481
 482        .pmu_detect             = pfm_netburst_detect_prescott,
 483        .get_event_encoding[PFM_OS_NONE] = pfm_netburst_get_encoding,
 484         PFMLIB_ENCODE_PERF(pfm_netburst_get_perf_encoding),
 485        .get_event_first        = pfm_netburst_get_event_first,
 486        .get_event_next         = pfm_netburst_get_event_next,
 487        .event_is_valid         = pfm_netburst_event_is_valid,
 488        .validate_table         = pfm_netburst_validate_table,
 489        .get_event_info         = pfm_netburst_get_event_info,
 490        .get_event_attr_info    = pfm_netburst_get_event_attr_info,
 491        .get_event_nattrs       = pfm_netburst_get_event_nattrs,
 492         PFMLIB_VALID_PERF_PATTRS(pfm_netburst_perf_validate_pattrs),
 493};
 494