This source file includes following definitions.
- power5_get_constraint
- find_alternative
- find_alternative_bdecode
- power5_get_alternatives
- power5_marked_instr_event
- power5_compute_mmcr
- power5_disable_pmc
- init_power5_pmu
   1 
   2 
   3 
   4 
   5 
   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 
  14 
  15 
  16 #define PM_PMC_SH       20      
  17 #define PM_PMC_MSK      0xf
  18 #define PM_PMC_MSKS     (PM_PMC_MSK << PM_PMC_SH)
  19 #define PM_UNIT_SH      16      
  20 #define PM_UNIT_MSK     0xf
  21 #define PM_BYTE_SH      12      
  22 #define PM_BYTE_MSK     7
  23 #define PM_GRS_SH       8       
  24 #define PM_GRS_MSK      7
  25 #define PM_BUSEVENT_MSK 0x80    
  26 #define PM_PMCSEL_MSK   0x7f
  27 
  28 
  29 #define PM_FPU          0
  30 #define PM_ISU0         1
  31 #define PM_IFU          2
  32 #define PM_ISU1         3
  33 #define PM_IDU          4
  34 #define PM_ISU0_ALT     6
  35 #define PM_GRS          7
  36 #define PM_LSU0         8
  37 #define PM_LSU1         0xc
  38 #define PM_LASTUNIT     0xc
  39 
  40 
  41 
  42 
  43 #define MMCR1_TTM0SEL_SH        62
  44 #define MMCR1_TTM1SEL_SH        60
  45 #define MMCR1_TTM2SEL_SH        58
  46 #define MMCR1_TTM3SEL_SH        56
  47 #define MMCR1_TTMSEL_MSK        3
  48 #define MMCR1_TD_CP_DBG0SEL_SH  54
  49 #define MMCR1_TD_CP_DBG1SEL_SH  52
  50 #define MMCR1_TD_CP_DBG2SEL_SH  50
  51 #define MMCR1_TD_CP_DBG3SEL_SH  48
  52 #define MMCR1_GRS_L2SEL_SH      46
  53 #define MMCR1_GRS_L2SEL_MSK     3
  54 #define MMCR1_GRS_L3SEL_SH      44
  55 #define MMCR1_GRS_L3SEL_MSK     3
  56 #define MMCR1_GRS_MCSEL_SH      41
  57 #define MMCR1_GRS_MCSEL_MSK     7
  58 #define MMCR1_GRS_FABSEL_SH     39
  59 #define MMCR1_GRS_FABSEL_MSK    3
  60 #define MMCR1_PMC1_ADDER_SEL_SH 35
  61 #define MMCR1_PMC2_ADDER_SEL_SH 34
  62 #define MMCR1_PMC3_ADDER_SEL_SH 33
  63 #define MMCR1_PMC4_ADDER_SEL_SH 32
  64 #define MMCR1_PMC1SEL_SH        25
  65 #define MMCR1_PMC2SEL_SH        17
  66 #define MMCR1_PMC3SEL_SH        9
  67 #define MMCR1_PMC4SEL_SH        1
  68 #define MMCR1_PMCSEL_SH(n)      (MMCR1_PMC1SEL_SH - (n) * 8)
  69 #define MMCR1_PMCSEL_MSK        0x7f
  70 
  71 
  72 
  73 
  74 
  75 
  76 
  77 
  78 
  79 
  80 
  81 
  82 
  83 
  84 
  85 
  86 
  87 
  88 
  89 
  90 
  91 
  92 
  93 
  94 
  95 
  96 
  97 
  98 
  99 
 100 
 101 
 102 
 103 
 104 
 105 
 106 
 107 
 108 
 109 
 110 
 111 
 112 
 113 
 114 
 115 
 116 
 117 
 118 
 119 
 120 static const int grsel_shift[8] = {
 121         MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH, MMCR1_GRS_L2SEL_SH,
 122         MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH, MMCR1_GRS_L3SEL_SH,
 123         MMCR1_GRS_MCSEL_SH, MMCR1_GRS_FABSEL_SH
 124 };
 125 
 126 
 127 static unsigned long unit_cons[PM_LASTUNIT+1][2] = {
 128         [PM_FPU] =   { 0xc0002000000000ul, 0x00001000000000ul },
 129         [PM_ISU0] =  { 0x00002000000000ul, 0x00000800000000ul },
 130         [PM_ISU1] =  { 0xc0002000000000ul, 0xc0001000000000ul },
 131         [PM_IFU] =   { 0xc0002000000000ul, 0x80001000000000ul },
 132         [PM_IDU] =   { 0x30002000000000ul, 0x00000400000000ul },
 133         [PM_GRS] =   { 0x30002000000000ul, 0x30000400000000ul },
 134 };
 135 
 136 static int power5_get_constraint(u64 event, unsigned long *maskp,
 137                                  unsigned long *valp)
 138 {
 139         int pmc, byte, unit, sh;
 140         int bit, fmask;
 141         unsigned long mask = 0, value = 0;
 142         int grp = -1;
 143 
 144         pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
 145         if (pmc) {
 146                 if (pmc > 6)
 147                         return -1;
 148                 sh = (pmc - 1) * 2;
 149                 mask |= 2 << sh;
 150                 value |= 1 << sh;
 151                 if (pmc <= 4)
 152                         grp = (pmc - 1) >> 1;
 153                 else if (event != 0x500009 && event != 0x600005)
 154                         return -1;
 155         }
 156         if (event & PM_BUSEVENT_MSK) {
 157                 unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
 158                 if (unit > PM_LASTUNIT)
 159                         return -1;
 160                 if (unit == PM_ISU0_ALT)
 161                         unit = PM_ISU0;
 162                 mask |= unit_cons[unit][0];
 163                 value |= unit_cons[unit][1];
 164                 byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
 165                 if (byte >= 4) {
 166                         if (unit != PM_LSU1)
 167                                 return -1;
 168                         
 169                         ++unit;
 170                         byte &= 3;
 171                 }
 172                 if (unit == PM_GRS) {
 173                         bit = event & 7;
 174                         fmask = (bit == 6)? 7: 3;
 175                         sh = grsel_shift[bit];
 176                         mask |= (unsigned long)fmask << sh;
 177                         value |= (unsigned long)((event >> PM_GRS_SH) & fmask)
 178                                 << sh;
 179                 }
 180                 
 181 
 182 
 183 
 184                 if (!pmc)
 185                         grp = byte & 1;
 186                 
 187                 mask  |= 0xfUL << (24 - 4 * byte);
 188                 value |= (unsigned long)unit << (24 - 4 * byte);
 189         }
 190         if (grp == 0) {
 191                 
 192                 mask  |= 0x200000000ul;
 193                 value |= 0x080000000ul;
 194         } else if (grp == 1) {
 195                 
 196                 mask  |= 0x40000000ul;
 197                 value |= 0x10000000ul;
 198         }
 199         if (pmc < 5) {
 200                 
 201                 mask  |= 0x8000000000000ul;
 202                 value |= 0x1000000000000ul;
 203         }
 204         *maskp = mask;
 205         *valp = value;
 206         return 0;
 207 }
 208 
 209 #define MAX_ALT 3       
 210 
 211 static const unsigned int event_alternatives[][MAX_ALT] = {
 212         { 0x120e4,  0x400002 },                 
 213         { 0x410c7,  0x441084 },                 
 214         { 0x100005, 0x600005 },                 
 215         { 0x100009, 0x200009, 0x500009 },       
 216         { 0x300009, 0x400009 },                 
 217 };
 218 
 219 
 220 
 221 
 222 
 223 static int find_alternative(u64 event)
 224 {
 225         int i, j;
 226 
 227         for (i = 0; i < ARRAY_SIZE(event_alternatives); ++i) {
 228                 if (event < event_alternatives[i][0])
 229                         break;
 230                 for (j = 0; j < MAX_ALT && event_alternatives[i][j]; ++j)
 231                         if (event == event_alternatives[i][j])
 232                                 return i;
 233         }
 234         return -1;
 235 }
 236 
 237 static const unsigned char bytedecode_alternatives[4][4] = {
 238              { 0x21, 0x23, 0x25, 0x27 },
 239              { 0x07, 0x17, 0x0e, 0x1e },
 240              { 0x20, 0x22, 0x24, 0x26 },
 241              { 0x07, 0x17, 0x0e, 0x1e }
 242 };
 243 
 244 
 245 
 246 
 247 
 248 
 249 static s64 find_alternative_bdecode(u64 event)
 250 {
 251         int pmc, altpmc, pp, j;
 252 
 253         pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
 254         if (pmc == 0 || pmc > 4)
 255                 return -1;
 256         altpmc = 5 - pmc;       
 257         pp = event & PM_PMCSEL_MSK;
 258         for (j = 0; j < 4; ++j) {
 259                 if (bytedecode_alternatives[pmc - 1][j] == pp) {
 260                         return (event & ~(PM_PMC_MSKS | PM_PMCSEL_MSK)) |
 261                                 (altpmc << PM_PMC_SH) |
 262                                 bytedecode_alternatives[altpmc - 1][j];
 263                 }
 264         }
 265         return -1;
 266 }
 267 
 268 static int power5_get_alternatives(u64 event, unsigned int flags, u64 alt[])
 269 {
 270         int i, j, nalt = 1;
 271         s64 ae;
 272 
 273         alt[0] = event;
 274         nalt = 1;
 275         i = find_alternative(event);
 276         if (i >= 0) {
 277                 for (j = 0; j < MAX_ALT; ++j) {
 278                         ae = event_alternatives[i][j];
 279                         if (ae && ae != event)
 280                                 alt[nalt++] = ae;
 281                 }
 282         } else {
 283                 ae = find_alternative_bdecode(event);
 284                 if (ae > 0)
 285                         alt[nalt++] = ae;
 286         }
 287         return nalt;
 288 }
 289 
 290 
 291 
 292 
 293 
 294 
 295 
 296 static unsigned char direct_event_is_marked[0x28] = {
 297         0,      
 298         0x1f,   
 299         0x2,    
 300         0xe,    
 301         0,      
 302         0x1c,   
 303         0x80,   
 304         0x80,   
 305         0, 0, 0,
 306         0x18,   
 307         0,      
 308         0x80,   
 309         0x80,   
 310         0,      
 311         0,      
 312         0x14,   
 313         0,      
 314         0x10,   
 315         0x1f,   
 316         0x2,    
 317         0x80,   
 318         0x80,   
 319         0, 0, 0, 0, 0,
 320         0x80,   
 321         0x80,   
 322         0,      
 323         0x80,   
 324         0x80,   
 325         0x80,   
 326         0x80,   
 327         0x80,   
 328         0x80,   
 329         0x80,   
 330         0x80,   
 331 };
 332 
 333 
 334 
 335 
 336 
 337 static int power5_marked_instr_event(u64 event)
 338 {
 339         int pmc, psel;
 340         int bit, byte, unit;
 341         u32 mask;
 342 
 343         pmc = (event >> PM_PMC_SH) & PM_PMC_MSK;
 344         psel = event & PM_PMCSEL_MSK;
 345         if (pmc >= 5)
 346                 return 0;
 347 
 348         bit = -1;
 349         if (psel < sizeof(direct_event_is_marked)) {
 350                 if (direct_event_is_marked[psel] & (1 << pmc))
 351                         return 1;
 352                 if (direct_event_is_marked[psel] & 0x80)
 353                         bit = 4;
 354                 else if (psel == 0x08)
 355                         bit = pmc - 1;
 356                 else if (psel == 0x10)
 357                         bit = 4 - pmc;
 358                 else if (psel == 0x1b && (pmc == 1 || pmc == 3))
 359                         bit = 4;
 360         } else if ((psel & 0x58) == 0x40)
 361                 bit = psel & 7;
 362 
 363         if (!(event & PM_BUSEVENT_MSK))
 364                 return 0;
 365 
 366         byte = (event >> PM_BYTE_SH) & PM_BYTE_MSK;
 367         unit = (event >> PM_UNIT_SH) & PM_UNIT_MSK;
 368         if (unit == PM_LSU0) {
 369                 
 370                 mask = 0x5dff00;
 371         } else if (unit == PM_LSU1 && byte >= 4) {
 372                 byte -= 4;
 373                 
 374                 mask = 0x5f00c0aa;
 375         } else
 376                 return 0;
 377 
 378         return (mask >> (byte * 8 + bit)) & 1;
 379 }
 380 
 381 static int power5_compute_mmcr(u64 event[], int n_ev,
 382                                unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[])
 383 {
 384         unsigned long mmcr1 = 0;
 385         unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS;
 386         unsigned int pmc, unit, byte, psel;
 387         unsigned int ttm, grp;
 388         int i, isbus, bit, grsel;
 389         unsigned int pmc_inuse = 0;
 390         unsigned int pmc_grp_use[2];
 391         unsigned char busbyte[4];
 392         unsigned char unituse[16];
 393         int ttmuse;
 394 
 395         if (n_ev > 6)
 396                 return -1;
 397 
 398         
 399         pmc_grp_use[0] = pmc_grp_use[1] = 0;
 400         memset(busbyte, 0, sizeof(busbyte));
 401         memset(unituse, 0, sizeof(unituse));
 402         for (i = 0; i < n_ev; ++i) {
 403                 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
 404                 if (pmc) {
 405                         if (pmc > 6)
 406                                 return -1;
 407                         if (pmc_inuse & (1 << (pmc - 1)))
 408                                 return -1;
 409                         pmc_inuse |= 1 << (pmc - 1);
 410                         
 411                         if (pmc <= 4)
 412                                 ++pmc_grp_use[(pmc - 1) >> 1];
 413                 }
 414                 if (event[i] & PM_BUSEVENT_MSK) {
 415                         unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
 416                         byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
 417                         if (unit > PM_LASTUNIT)
 418                                 return -1;
 419                         if (unit == PM_ISU0_ALT)
 420                                 unit = PM_ISU0;
 421                         if (byte >= 4) {
 422                                 if (unit != PM_LSU1)
 423                                         return -1;
 424                                 ++unit;
 425                                 byte &= 3;
 426                         }
 427                         if (!pmc)
 428                                 ++pmc_grp_use[byte & 1];
 429                         if (busbyte[byte] && busbyte[byte] != unit)
 430                                 return -1;
 431                         busbyte[byte] = unit;
 432                         unituse[unit] = 1;
 433                 }
 434         }
 435         if (pmc_grp_use[0] > 2 || pmc_grp_use[1] > 2)
 436                 return -1;
 437 
 438         
 439 
 440 
 441 
 442 
 443 
 444         if (unituse[PM_ISU0] &
 445             (unituse[PM_FPU] | unituse[PM_IFU] | unituse[PM_ISU1])) {
 446                 unituse[PM_ISU0_ALT] = 1;       
 447                 unituse[PM_ISU0] = 0;
 448         }
 449         
 450         ttmuse = 0;
 451         for (i = PM_FPU; i <= PM_ISU1; ++i) {
 452                 if (!unituse[i])
 453                         continue;
 454                 if (ttmuse++)
 455                         return -1;
 456                 mmcr1 |= (unsigned long)i << MMCR1_TTM0SEL_SH;
 457         }
 458         ttmuse = 0;
 459         for (; i <= PM_GRS; ++i) {
 460                 if (!unituse[i])
 461                         continue;
 462                 if (ttmuse++)
 463                         return -1;
 464                 mmcr1 |= (unsigned long)(i & 3) << MMCR1_TTM1SEL_SH;
 465         }
 466         if (ttmuse > 1)
 467                 return -1;
 468 
 469         
 470         for (byte = 0; byte < 4; ++byte) {
 471                 unit = busbyte[byte];
 472                 if (!unit)
 473                         continue;
 474                 if (unit == PM_ISU0 && unituse[PM_ISU0_ALT]) {
 475                         
 476                         unit = PM_ISU0_ALT;
 477                 } else if (unit == PM_LSU1 + 1) {
 478                         
 479                         mmcr1 |= 1ul << (MMCR1_TTM3SEL_SH + 3 - byte);
 480                 }
 481                 ttm = unit >> 2;
 482                 mmcr1 |= (unsigned long)ttm
 483                         << (MMCR1_TD_CP_DBG0SEL_SH - 2 * byte);
 484         }
 485 
 486         
 487         for (i = 0; i < n_ev; ++i) {
 488                 pmc = (event[i] >> PM_PMC_SH) & PM_PMC_MSK;
 489                 unit = (event[i] >> PM_UNIT_SH) & PM_UNIT_MSK;
 490                 byte = (event[i] >> PM_BYTE_SH) & PM_BYTE_MSK;
 491                 psel = event[i] & PM_PMCSEL_MSK;
 492                 isbus = event[i] & PM_BUSEVENT_MSK;
 493                 if (!pmc) {
 494                         
 495                         for (pmc = 0; pmc < 4; ++pmc) {
 496                                 if (pmc_inuse & (1 << pmc))
 497                                         continue;
 498                                 grp = (pmc >> 1) & 1;
 499                                 if (isbus) {
 500                                         if (grp == (byte & 1))
 501                                                 break;
 502                                 } else if (pmc_grp_use[grp] < 2) {
 503                                         ++pmc_grp_use[grp];
 504                                         break;
 505                                 }
 506                         }
 507                         pmc_inuse |= 1 << pmc;
 508                 } else if (pmc <= 4) {
 509                         
 510                         --pmc;
 511                         if ((psel == 8 || psel == 0x10) && isbus && (byte & 2))
 512                                 
 513                                 mmcr1 |= 1ul << (MMCR1_PMC1_ADDER_SEL_SH - pmc);
 514                 } else {
 515                         
 516                         --pmc;
 517                 }
 518                 if (isbus && unit == PM_GRS) {
 519                         bit = psel & 7;
 520                         grsel = (event[i] >> PM_GRS_SH) & PM_GRS_MSK;
 521                         mmcr1 |= (unsigned long)grsel << grsel_shift[bit];
 522                 }
 523                 if (power5_marked_instr_event(event[i]))
 524                         mmcra |= MMCRA_SAMPLE_ENABLE;
 525                 if (pmc <= 3)
 526                         mmcr1 |= psel << MMCR1_PMCSEL_SH(pmc);
 527                 hwc[i] = pmc;
 528         }
 529 
 530         
 531         mmcr[0] = 0;
 532         if (pmc_inuse & 1)
 533                 mmcr[0] = MMCR0_PMC1CE;
 534         if (pmc_inuse & 0x3e)
 535                 mmcr[0] |= MMCR0_PMCjCE;
 536         mmcr[1] = mmcr1;
 537         mmcr[2] = mmcra;
 538         return 0;
 539 }
 540 
 541 static void power5_disable_pmc(unsigned int pmc, unsigned long mmcr[])
 542 {
 543         if (pmc <= 3)
 544                 mmcr[1] &= ~(0x7fUL << MMCR1_PMCSEL_SH(pmc));
 545 }
 546 
 547 static int power5_generic_events[] = {
 548         [PERF_COUNT_HW_CPU_CYCLES]              = 0xf,
 549         [PERF_COUNT_HW_INSTRUCTIONS]            = 0x100009,
 550         [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x4c1090, 
 551         [PERF_COUNT_HW_CACHE_MISSES]            = 0x3c1088, 
 552         [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0x230e4,  
 553         [PERF_COUNT_HW_BRANCH_MISSES]           = 0x230e5,  
 554 };
 555 
 556 #define C(x)    PERF_COUNT_HW_CACHE_##x
 557 
 558 
 559 
 560 
 561 
 562 
 563 static int power5_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
 564         [C(L1D)] = {            
 565                 [C(OP_READ)] = {        0x4c1090,       0x3c1088        },
 566                 [C(OP_WRITE)] = {       0x3c1090,       0xc10c3         },
 567                 [C(OP_PREFETCH)] = {    0xc70e7,        0               },
 568         },
 569         [C(L1I)] = {            
 570                 [C(OP_READ)] = {        0,              0               },
 571                 [C(OP_WRITE)] = {       -1,             -1              },
 572                 [C(OP_PREFETCH)] = {    0,              0               },
 573         },
 574         [C(LL)] = {             
 575                 [C(OP_READ)] = {        0,              0x3c309b        },
 576                 [C(OP_WRITE)] = {       0,              0               },
 577                 [C(OP_PREFETCH)] = {    0xc50c3,        0               },
 578         },
 579         [C(DTLB)] = {           
 580                 [C(OP_READ)] = {        0x2c4090,       0x800c4         },
 581                 [C(OP_WRITE)] = {       -1,             -1              },
 582                 [C(OP_PREFETCH)] = {    -1,             -1              },
 583         },
 584         [C(ITLB)] = {           
 585                 [C(OP_READ)] = {        0,              0x800c0         },
 586                 [C(OP_WRITE)] = {       -1,             -1              },
 587                 [C(OP_PREFETCH)] = {    -1,             -1              },
 588         },
 589         [C(BPU)] = {            
 590                 [C(OP_READ)] = {        0x230e4,        0x230e5         },
 591                 [C(OP_WRITE)] = {       -1,             -1              },
 592                 [C(OP_PREFETCH)] = {    -1,             -1              },
 593         },
 594         [C(NODE)] = {           
 595                 [C(OP_READ)] = {        -1,             -1              },
 596                 [C(OP_WRITE)] = {       -1,             -1              },
 597                 [C(OP_PREFETCH)] = {    -1,             -1              },
 598         },
 599 };
 600 
 601 static struct power_pmu power5_pmu = {
 602         .name                   = "POWER5",
 603         .n_counter              = 6,
 604         .max_alternatives       = MAX_ALT,
 605         .add_fields             = 0x7000090000555ul,
 606         .test_adder             = 0x3000490000000ul,
 607         .compute_mmcr           = power5_compute_mmcr,
 608         .get_constraint         = power5_get_constraint,
 609         .get_alternatives       = power5_get_alternatives,
 610         .disable_pmc            = power5_disable_pmc,
 611         .n_generic              = ARRAY_SIZE(power5_generic_events),
 612         .generic_events         = power5_generic_events,
 613         .cache_events           = &power5_cache_events,
 614         .flags                  = PPMU_HAS_SSLOT,
 615 };
 616 
 617 int init_power5_pmu(void)
 618 {
 619         if (!cur_cpu_spec->oprofile_cpu_type ||
 620             strcmp(cur_cpu_spec->oprofile_cpu_type, "ppc64/power5"))
 621                 return -ENODEV;
 622 
 623         return register_power_pmu(&power5_pmu);
 624 }