1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2013 Justin Hibbits 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/pmc.h> 35 #include <sys/pmckern.h> 36 #include <sys/systm.h> 37 38 #include <machine/pmc_mdep.h> 39 #include <machine/spr.h> 40 #include <machine/cpu.h> 41 42 #include "hwpmc_powerpc.h" 43 44 #define PPC970_MAX_PMCS 8 45 46 /* MMCR0, PMC1 is 8 bytes in, PMC2 is 1 byte in. */ 47 #define PPC970_SET_MMCR0_PMCSEL(r, x, i) \ 48 ((r & ~(0x1f << (7 * (1 - i) + 1))) | (x << (7 * (1 - i) + 1))) 49 /* MMCR1 has 6 PMC*SEL items (PMC3->PMC8), in sequence. */ 50 #define PPC970_SET_MMCR1_PMCSEL(r, x, i) \ 51 ((r & ~(0x1f << (5 * (7 - i) + 2))) | (x << (5 * (7 - i) + 2))) 52 53 #define PPC970_PMC_HAS_OVERFLOWED(x) (ppc970_pmcn_read(x) & (0x1 << 31)) 54 55 /* How PMC works on PPC970: 56 * 57 * Any PMC can count a direct event. Indirect events are handled specially. 58 * Direct events: As published. 59 * 60 * Encoding 00 000 -- Add byte lane bit counters 61 * MMCR1[24:31] -- select bit matching PMC being an adder. 62 * Bus events: 63 * PMCxSEL: 1x -- select from byte lane: 10 == lower lane (0/1), 11 == upper 64 * lane (2/3). 65 * PMCxSEL[2:4] -- bit in the byte lane selected. 66 * 67 * PMC[1,2,5,6] == lane 0/lane 2 68 * PMC[3,4,7,8] == lane 1,3 69 * 70 * 71 * Lanes: 72 * Lane 0 -- TTM0(FPU,ISU,IFU,VPU) 73 * TTM1(IDU,ISU,STS) 74 * LSU0 byte 0 75 * LSU1 byte 0 76 * Lane 1 -- TTM0 77 * TTM1 78 * LSU0 byte 1 79 * LSU1 byte 1 80 * Lane 2 -- TTM0 81 * TTM1 82 * LSU0 byte 2 83 * LSU1 byte 2 or byte 6 84 * Lane 3 -- TTM0 85 * TTM1 86 * LSU0 byte 3 87 * LSU1 byte 3 or byte 7 88 * 89 * Adders: 90 * Add byte lane for PMC (above), bit 0+4, 1+5, 2+6, 3+7 91 */ 92 93 struct pmc_ppc970_event { 94 enum pmc_event pe_event; 95 uint32_t pe_flags; 96 #define PMC_PPC970_FLAG_PMCS 0x000000ff 97 #define PMC_PPC970_FLAG_PMC1 0x01 98 #define PMC_PPC970_FLAG_PMC2 0x02 99 #define PMC_PPC970_FLAG_PMC3 0x04 100 #define PMC_PPC970_FLAG_PMC4 0x08 101 #define PMC_PPC970_FLAG_PMC5 0x10 102 #define PMC_PPC970_FLAG_PMC6 0x20 103 #define PMC_PPC970_FLAG_PMC7 0x40 104 #define PMC_PPC970_FLAG_PMC8 0x80 105 uint32_t pe_code; 106 }; 107 108 static struct pmc_ppc970_event ppc970_event_codes[] = { 109 {PMC_EV_PPC970_INSTR_COMPLETED, 110 .pe_flags = PMC_PPC970_FLAG_PMCS, 111 .pe_code = 0x09 112 }, 113 {PMC_EV_PPC970_MARKED_GROUP_DISPATCH, 114 .pe_flags = PMC_PPC970_FLAG_PMC1, 115 .pe_code = 0x2 116 }, 117 {PMC_EV_PPC970_MARKED_STORE_COMPLETED, 118 .pe_flags = PMC_PPC970_FLAG_PMC1, 119 .pe_code = 0x03 120 }, 121 {PMC_EV_PPC970_GCT_EMPTY, 122 .pe_flags = PMC_PPC970_FLAG_PMC1, 123 .pe_code = 0x04 124 }, 125 {PMC_EV_PPC970_RUN_CYCLES, 126 .pe_flags = PMC_PPC970_FLAG_PMC1, 127 .pe_code = 0x05 128 }, 129 {PMC_EV_PPC970_OVERFLOW, 130 .pe_flags = PMC_PPC970_FLAG_PMCS, 131 .pe_code = 0x0a 132 }, 133 {PMC_EV_PPC970_CYCLES, 134 .pe_flags = PMC_PPC970_FLAG_PMCS, 135 .pe_code = 0x0f 136 }, 137 {PMC_EV_PPC970_THRESHOLD_TIMEOUT, 138 .pe_flags = PMC_PPC970_FLAG_PMC2, 139 .pe_code = 0x3 140 }, 141 {PMC_EV_PPC970_GROUP_DISPATCH, 142 .pe_flags = PMC_PPC970_FLAG_PMC2, 143 .pe_code = 0x4 144 }, 145 {PMC_EV_PPC970_BR_MARKED_INSTR_FINISH, 146 .pe_flags = PMC_PPC970_FLAG_PMC2, 147 .pe_code = 0x5 148 }, 149 {PMC_EV_PPC970_GCT_EMPTY_BY_SRQ_FULL, 150 .pe_flags = PMC_PPC970_FLAG_PMC2, 151 .pe_code = 0xb 152 }, 153 {PMC_EV_PPC970_STOP_COMPLETION, 154 .pe_flags = PMC_PPC970_FLAG_PMC3, 155 .pe_code = 0x1 156 }, 157 {PMC_EV_PPC970_LSU_EMPTY, 158 .pe_flags = PMC_PPC970_FLAG_PMC3, 159 .pe_code = 0x2 160 }, 161 {PMC_EV_PPC970_MARKED_STORE_WITH_INTR, 162 .pe_flags = PMC_PPC970_FLAG_PMC3, 163 .pe_code = 0x3 164 }, 165 {PMC_EV_PPC970_CYCLES_IN_SUPER, 166 .pe_flags = PMC_PPC970_FLAG_PMC3, 167 .pe_code = 0x4 168 }, 169 {PMC_EV_PPC970_VPU_MARKED_INSTR_COMPLETED, 170 .pe_flags = PMC_PPC970_FLAG_PMC3, 171 .pe_code = 0x5 172 }, 173 {PMC_EV_PPC970_FXU0_IDLE_FXU1_BUSY, 174 .pe_flags = PMC_PPC970_FLAG_PMC4, 175 .pe_code = 0x2 176 }, 177 {PMC_EV_PPC970_SRQ_EMPTY, 178 .pe_flags = PMC_PPC970_FLAG_PMC4, 179 .pe_code = 0x3 180 }, 181 {PMC_EV_PPC970_MARKED_GROUP_COMPLETED, 182 .pe_flags = PMC_PPC970_FLAG_PMC4, 183 .pe_code = 0x4 184 }, 185 {PMC_EV_PPC970_CR_MARKED_INSTR_FINISH, 186 .pe_flags = PMC_PPC970_FLAG_PMC4, 187 .pe_code = 0x5 188 }, 189 {PMC_EV_PPC970_DISPATCH_SUCCESS, 190 .pe_flags = PMC_PPC970_FLAG_PMC5, 191 .pe_code = 0x1 192 }, 193 {PMC_EV_PPC970_FXU0_IDLE_FXU1_IDLE, 194 .pe_flags = PMC_PPC970_FLAG_PMC5, 195 .pe_code = 0x2 196 }, 197 {PMC_EV_PPC970_ONE_PLUS_INSTR_COMPLETED, 198 .pe_flags = PMC_PPC970_FLAG_PMC5, 199 .pe_code = 0x3 200 }, 201 {PMC_EV_PPC970_GROUP_MARKED_IDU, 202 .pe_flags = PMC_PPC970_FLAG_PMC5, 203 .pe_code = 0x4 204 }, 205 {PMC_EV_PPC970_MARKED_GROUP_COMPLETE_TIMEOUT, 206 .pe_flags = PMC_PPC970_FLAG_PMC5, 207 .pe_code = 0x5 208 }, 209 {PMC_EV_PPC970_FXU0_BUSY_FXU1_BUSY, 210 .pe_flags = PMC_PPC970_FLAG_PMC6, 211 .pe_code = 0x2 212 }, 213 {PMC_EV_PPC970_MARKED_STORE_SENT_TO_STS, 214 .pe_flags = PMC_PPC970_FLAG_PMC6, 215 .pe_code = 0x3 216 }, 217 {PMC_EV_PPC970_FXU_MARKED_INSTR_FINISHED, 218 .pe_flags = PMC_PPC970_FLAG_PMC6, 219 .pe_code = 0x4 220 }, 221 {PMC_EV_PPC970_MARKED_GROUP_ISSUED, 222 .pe_flags = PMC_PPC970_FLAG_PMC6, 223 .pe_code = 0x5 224 }, 225 {PMC_EV_PPC970_FXU0_BUSY_FXU1_IDLE, 226 .pe_flags = PMC_PPC970_FLAG_PMC7, 227 .pe_code = 0x2 228 }, 229 {PMC_EV_PPC970_GROUP_COMPLETED, 230 .pe_flags = PMC_PPC970_FLAG_PMC7, 231 .pe_code = 0x3 232 }, 233 {PMC_EV_PPC970_FPU_MARKED_INSTR_COMPLETED, 234 .pe_flags = PMC_PPC970_FLAG_PMC7, 235 .pe_code = 0x4 236 }, 237 {PMC_EV_PPC970_MARKED_INSTR_FINISH_ANY_UNIT, 238 .pe_flags = PMC_PPC970_FLAG_PMC7, 239 .pe_code = 0x5 240 }, 241 {PMC_EV_PPC970_EXTERNAL_INTERRUPT, 242 .pe_flags = PMC_PPC970_FLAG_PMC8, 243 .pe_code = 0x2 244 }, 245 {PMC_EV_PPC970_GROUP_DISPATCH_REJECT, 246 .pe_flags = PMC_PPC970_FLAG_PMC8, 247 .pe_code = 0x3 248 }, 249 {PMC_EV_PPC970_LSU_MARKED_INSTR_FINISH, 250 .pe_flags = PMC_PPC970_FLAG_PMC8, 251 .pe_code = 0x4 252 }, 253 {PMC_EV_PPC970_TIMEBASE_EVENT, 254 .pe_flags = PMC_PPC970_FLAG_PMC8, 255 .pe_code = 0x5 256 }, 257 #if 0 258 {PMC_EV_PPC970_LSU_COMPLETION_STALL, }, 259 {PMC_EV_PPC970_FXU_COMPLETION_STALL, }, 260 {PMC_EV_PPC970_DCACHE_MISS_COMPLETION_STALL, }, 261 {PMC_EV_PPC970_FPU_COMPLETION_STALL, }, 262 {PMC_EV_PPC970_FXU_LONG_INSTR_COMPLETION_STALL, }, 263 {PMC_EV_PPC970_REJECT_COMPLETION_STALL, }, 264 {PMC_EV_PPC970_FPU_LONG_INSTR_COMPLETION_STALL, }, 265 {PMC_EV_PPC970_GCT_EMPTY_BY_ICACHE_MISS, }, 266 {PMC_EV_PPC970_REJECT_COMPLETION_STALL_ERAT_MISS, }, 267 {PMC_EV_PPC970_GCT_EMPTY_BY_BRANCH_MISS_PREDICT, }, 268 #endif 269 }; 270 static size_t ppc970_event_codes_size = nitems(ppc970_event_codes); 271 272 static pmc_value_t 273 ppc970_pmcn_read(unsigned int pmc) 274 { 275 pmc_value_t val; 276 277 switch (pmc) { 278 case 0: 279 val = mfspr(SPR_970PMC1); 280 break; 281 case 1: 282 val = mfspr(SPR_970PMC2); 283 break; 284 case 2: 285 val = mfspr(SPR_970PMC3); 286 break; 287 case 3: 288 val = mfspr(SPR_970PMC4); 289 break; 290 case 4: 291 val = mfspr(SPR_970PMC5); 292 break; 293 case 5: 294 val = mfspr(SPR_970PMC6); 295 break; 296 case 6: 297 val = mfspr(SPR_970PMC7); 298 break; 299 case 7: 300 val = mfspr(SPR_970PMC8); 301 break; 302 default: 303 panic("Invalid PMC number: %d\n", pmc); 304 } 305 306 return (val); 307 } 308 309 static void 310 ppc970_pmcn_write(unsigned int pmc, uint32_t val) 311 { 312 switch (pmc) { 313 case 0: 314 mtspr(SPR_970PMC1, val); 315 break; 316 case 1: 317 mtspr(SPR_970PMC2, val); 318 break; 319 case 2: 320 mtspr(SPR_970PMC3, val); 321 break; 322 case 3: 323 mtspr(SPR_970PMC4, val); 324 break; 325 case 4: 326 mtspr(SPR_970PMC5, val); 327 break; 328 case 5: 329 mtspr(SPR_970PMC6, val); 330 break; 331 case 6: 332 mtspr(SPR_970PMC7, val); 333 break; 334 case 7: 335 mtspr(SPR_970PMC8, val); 336 break; 337 default: 338 panic("Invalid PMC number: %d\n", pmc); 339 } 340 } 341 342 static int 343 ppc970_config_pmc(int cpu, int ri, struct pmc *pm) 344 { 345 struct pmc_hw *phw; 346 347 PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); 348 349 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 350 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 351 KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, 352 ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 353 354 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 355 356 KASSERT(pm == NULL || phw->phw_pmc == NULL, 357 ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured", 358 __LINE__, pm, phw->phw_pmc)); 359 360 phw->phw_pmc = pm; 361 362 return 0; 363 } 364 365 static int 366 ppc970_set_pmc(int cpu, int ri, int config) 367 { 368 struct pmc *pm; 369 struct pmc_hw *phw; 370 register_t pmc_mmcr; 371 372 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 373 pm = phw->phw_pmc; 374 375 /* 376 * Disable the PMCs. 377 */ 378 switch (ri) { 379 case 0: 380 case 1: 381 pmc_mmcr = mfspr(SPR_970MMCR0); 382 pmc_mmcr = PPC970_SET_MMCR0_PMCSEL(pmc_mmcr, config, ri); 383 mtspr(SPR_970MMCR0, pmc_mmcr); 384 break; 385 case 2: 386 case 3: 387 case 4: 388 case 5: 389 case 6: 390 case 7: 391 pmc_mmcr = mfspr(SPR_970MMCR1); 392 pmc_mmcr = PPC970_SET_MMCR1_PMCSEL(pmc_mmcr, config, ri); 393 mtspr(SPR_970MMCR1, pmc_mmcr); 394 break; 395 } 396 return 0; 397 } 398 399 static int 400 ppc970_start_pmc(int cpu, int ri) 401 { 402 struct pmc *pm; 403 struct pmc_hw *phw; 404 register_t pmc_mmcr; 405 uint32_t config; 406 int error; 407 408 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 409 pm = phw->phw_pmc; 410 config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE; 411 412 error = ppc970_set_pmc(cpu, ri, config); 413 414 /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which 415 * are Freeze flags. 416 */ 417 config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE; 418 419 pmc_mmcr = mfspr(SPR_970MMCR0); 420 pmc_mmcr &= ~SPR_MMCR0_FC; 421 pmc_mmcr |= config; 422 mtspr(SPR_970MMCR0, pmc_mmcr); 423 424 return 0; 425 } 426 427 static int 428 ppc970_stop_pmc(int cpu, int ri) 429 { 430 return ppc970_set_pmc(cpu, ri, PMC970N_NONE); 431 } 432 433 static int 434 ppc970_read_pmc(int cpu, int ri, pmc_value_t *v) 435 { 436 struct pmc *pm; 437 pmc_value_t tmp; 438 439 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 440 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 441 KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, 442 ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 443 444 pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 445 KASSERT(pm, 446 ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu, 447 ri)); 448 449 tmp = ppc970_pmcn_read(ri); 450 PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp); 451 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 452 *v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); 453 else 454 *v = tmp; 455 456 return 0; 457 } 458 459 static int 460 ppc970_write_pmc(int cpu, int ri, pmc_value_t v) 461 { 462 struct pmc *pm; 463 464 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 465 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 466 KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, 467 ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 468 469 pm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc; 470 471 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 472 v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v); 473 474 PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v); 475 476 ppc970_pmcn_write(ri, v); 477 478 return 0; 479 } 480 481 static int 482 ppc970_intr(struct trapframe *tf) 483 { 484 struct pmc *pm; 485 struct powerpc_cpu *pac; 486 uint32_t config; 487 int i, error, retval, cpu; 488 489 cpu = curcpu; 490 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 491 ("[powerpc,%d] out of range CPU %d", __LINE__, cpu)); 492 493 PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf, 494 TRAPF_USERMODE(tf)); 495 496 retval = 0; 497 498 pac = powerpc_pcpu[cpu]; 499 500 /* 501 * look for all PMCs that have interrupted: 502 * - look for a running, sampling PMC which has overflowed 503 * and which has a valid 'struct pmc' association 504 * 505 * If found, we call a helper to process the interrupt. 506 */ 507 508 config = mfspr(SPR_970MMCR0) & ~SPR_MMCR0_FC; 509 for (i = 0; i < PPC970_MAX_PMCS; i++) { 510 if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL || 511 !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { 512 continue; 513 } 514 515 if (!PPC970_PMC_HAS_OVERFLOWED(i)) 516 continue; 517 518 retval = 1; /* Found an interrupting PMC. */ 519 520 if (pm->pm_state != PMC_STATE_RUNNING) 521 continue; 522 523 error = pmc_process_interrupt(PMC_HR, pm, tf); 524 if (error != 0) 525 ppc970_stop_pmc(cpu, i); 526 527 /* reload sampling count. */ 528 ppc970_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount); 529 } 530 531 if (retval) 532 counter_u64_add(pmc_stats.pm_intr_processed, 1); 533 else 534 counter_u64_add(pmc_stats.pm_intr_ignored, 1); 535 536 /* Re-enable PERF exceptions. */ 537 if (retval) 538 mtspr(SPR_970MMCR0, config | SPR_MMCR0_PMXE); 539 540 return (retval); 541 } 542 543 static int 544 ppc970_pcpu_init(struct pmc_mdep *md, int cpu) 545 { 546 struct pmc_cpu *pc; 547 struct powerpc_cpu *pac; 548 struct pmc_hw *phw; 549 int first_ri, i; 550 551 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 552 ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu)); 553 PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu); 554 555 powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC, 556 M_WAITOK|M_ZERO); 557 pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * PPC970_MAX_PMCS, 558 M_PMC, M_WAITOK|M_ZERO); 559 pac->pc_class = PMC_CLASS_PPC970; 560 561 pc = pmc_pcpu[cpu]; 562 first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri; 563 KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__)); 564 565 for (i = 0, phw = pac->pc_ppcpmcs; i < PPC970_MAX_PMCS; i++, phw++) { 566 phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 567 PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); 568 phw->phw_pmc = NULL; 569 pc->pc_hwpmcs[i + first_ri] = phw; 570 } 571 572 /* Clear the MMCRs, and set FC, to disable all PMCs. */ 573 /* 970 PMC is not counted when set to 0x08 */ 574 mtspr(SPR_970MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | 575 SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE | 576 SPR_970MMCR0_PMC1SEL(0x8) | SPR_970MMCR0_PMC2SEL(0x8)); 577 mtspr(SPR_970MMCR1, 0x4218420); 578 579 return 0; 580 } 581 582 static int 583 ppc970_pcpu_fini(struct pmc_mdep *md, int cpu) 584 { 585 register_t mmcr0 = mfspr(SPR_MMCR0); 586 587 mmcr0 |= SPR_MMCR0_FC; 588 mmcr0 &= ~SPR_MMCR0_PMXE; 589 mtspr(SPR_MMCR0, mmcr0); 590 591 free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC); 592 free(powerpc_pcpu[cpu], M_PMC); 593 594 return 0; 595 } 596 597 static int 598 ppc970_allocate_pmc(int cpu, int ri, struct pmc *pm, 599 const struct pmc_op_pmcallocate *a) 600 { 601 enum pmc_event pe; 602 uint32_t caps, config = 0, counter = 0; 603 int i; 604 605 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 606 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 607 KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, 608 ("[powerpc,%d] illegal row index %d", __LINE__, ri)); 609 610 caps = a->pm_caps; 611 612 pe = a->pm_ev; 613 614 if (pe < PMC_EV_PPC970_FIRST || pe > PMC_EV_PPC970_LAST) 615 return (EINVAL); 616 617 for (i = 0; i < ppc970_event_codes_size; i++) { 618 if (ppc970_event_codes[i].pe_event == pe) { 619 config = ppc970_event_codes[i].pe_code; 620 counter = ppc970_event_codes[i].pe_flags; 621 break; 622 } 623 } 624 if (i == ppc970_event_codes_size) 625 return (EINVAL); 626 627 if ((counter & (1 << ri)) == 0) 628 return (EINVAL); 629 630 if (caps & PMC_CAP_SYSTEM) 631 config |= POWERPC_PMC_KERNEL_ENABLE; 632 if (caps & PMC_CAP_USER) 633 config |= POWERPC_PMC_USER_ENABLE; 634 if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0) 635 config |= POWERPC_PMC_ENABLE; 636 637 pm->pm_md.pm_powerpc.pm_powerpc_evsel = config; 638 639 PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config); 640 641 return 0; 642 } 643 644 static int 645 ppc970_release_pmc(int cpu, int ri, struct pmc *pmc) 646 { 647 struct pmc_hw *phw; 648 649 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 650 ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu)); 651 KASSERT(ri >= 0 && ri < PPC970_MAX_PMCS, 652 ("[powerpc,%d] illegal row-index %d", __LINE__, ri)); 653 654 phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri]; 655 KASSERT(phw->phw_pmc == NULL, 656 ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 657 658 return 0; 659 } 660 661 int 662 pmc_ppc970_initialize(struct pmc_mdep *pmc_mdep) 663 { 664 struct pmc_classdep *pcd; 665 666 pmc_mdep->pmd_cputype = PMC_CPU_PPC_970; 667 668 pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC]; 669 pcd->pcd_caps = POWERPC_PMC_CAPS; 670 pcd->pcd_class = PMC_CLASS_PPC970; 671 pcd->pcd_num = PPC970_MAX_PMCS; 672 pcd->pcd_ri = pmc_mdep->pmd_npmc; 673 pcd->pcd_width = 32; 674 675 pcd->pcd_allocate_pmc = ppc970_allocate_pmc; 676 pcd->pcd_config_pmc = ppc970_config_pmc; 677 pcd->pcd_pcpu_fini = ppc970_pcpu_fini; 678 pcd->pcd_pcpu_init = ppc970_pcpu_init; 679 pcd->pcd_describe = powerpc_describe; 680 pcd->pcd_get_config = powerpc_get_config; 681 pcd->pcd_read_pmc = ppc970_read_pmc; 682 pcd->pcd_release_pmc = ppc970_release_pmc; 683 pcd->pcd_start_pmc = ppc970_start_pmc; 684 pcd->pcd_stop_pmc = ppc970_stop_pmc; 685 pcd->pcd_write_pmc = ppc970_write_pmc; 686 687 pmc_mdep->pmd_npmc += PPC970_MAX_PMCS; 688 pmc_mdep->pmd_intr = ppc970_intr; 689 690 return (0); 691 } 692