1 /*- 2 * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> 3 * All rights reserved. 4 * 5 * This software was developed by SRI International and the University of 6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7 * ("CTSRD"), as part of the DARPA CRASH research programme. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/pmc.h> 37 #include <sys/pmckern.h> 38 39 #include <machine/pmc_mdep.h> 40 #include <machine/cpu.h> 41 42 #define CPU_ID_CORTEX_VER_MASK 0xff 43 #define CPU_ID_CORTEX_VER_SHIFT 4 44 45 static int armv7_npmcs; 46 47 struct armv7_event_code_map { 48 enum pmc_event pe_ev; 49 uint8_t pe_code; 50 }; 51 52 const struct armv7_event_code_map armv7_event_codes[] = { 53 { PMC_EV_ARMV7_PMNC_SW_INCR, 0x00 }, 54 { PMC_EV_ARMV7_L1_ICACHE_REFILL, 0x01 }, 55 { PMC_EV_ARMV7_ITLB_REFILL, 0x02 }, 56 { PMC_EV_ARMV7_L1_DCACHE_REFILL, 0x03 }, 57 { PMC_EV_ARMV7_L1_DCACHE_ACCESS, 0x04 }, 58 { PMC_EV_ARMV7_DTLB_REFILL, 0x05 }, 59 { PMC_EV_ARMV7_MEM_READ, 0x06 }, 60 { PMC_EV_ARMV7_MEM_WRITE, 0x07 }, 61 { PMC_EV_ARMV7_INSTR_EXECUTED, 0x08 }, 62 { PMC_EV_ARMV7_EXC_TAKEN, 0x09 }, 63 { PMC_EV_ARMV7_EXC_EXECUTED, 0x0A }, 64 { PMC_EV_ARMV7_CID_WRITE, 0x0B }, 65 { PMC_EV_ARMV7_PC_WRITE, 0x0C }, 66 { PMC_EV_ARMV7_PC_IMM_BRANCH, 0x0D }, 67 { PMC_EV_ARMV7_PC_PROC_RETURN, 0x0E }, 68 { PMC_EV_ARMV7_MEM_UNALIGNED_ACCESS, 0x0F }, 69 { PMC_EV_ARMV7_PC_BRANCH_MIS_PRED, 0x10 }, 70 { PMC_EV_ARMV7_CLOCK_CYCLES, 0x11 }, 71 { PMC_EV_ARMV7_PC_BRANCH_PRED, 0x12 }, 72 { PMC_EV_ARMV7_MEM_ACCESS, 0x13 }, 73 { PMC_EV_ARMV7_L1_ICACHE_ACCESS, 0x14 }, 74 { PMC_EV_ARMV7_L1_DCACHE_WB, 0x15 }, 75 { PMC_EV_ARMV7_L2_CACHE_ACCESS, 0x16 }, 76 { PMC_EV_ARMV7_L2_CACHE_REFILL, 0x17 }, 77 { PMC_EV_ARMV7_L2_CACHE_WB, 0x18 }, 78 { PMC_EV_ARMV7_BUS_ACCESS, 0x19 }, 79 { PMC_EV_ARMV7_MEM_ERROR, 0x1A }, 80 { PMC_EV_ARMV7_INSTR_SPEC, 0x1B }, 81 { PMC_EV_ARMV7_TTBR_WRITE, 0x1C }, 82 { PMC_EV_ARMV7_BUS_CYCLES, 0x1D }, 83 { PMC_EV_ARMV7_CPU_CYCLES, 0xFF }, 84 }; 85 86 const int armv7_event_codes_size = 87 sizeof(armv7_event_codes) / sizeof(armv7_event_codes[0]); 88 89 /* 90 * Per-processor information. 91 */ 92 struct armv7_cpu { 93 struct pmc_hw *pc_armv7pmcs; 94 int cortex_ver; 95 }; 96 97 static struct armv7_cpu **armv7_pcpu; 98 99 /* 100 * Performance Monitor Control Register 101 */ 102 static __inline uint32_t 103 armv7_pmnc_read(void) 104 { 105 uint32_t reg; 106 107 __asm __volatile("mrc p15, 0, %0, c9, c12, 0" : "=r" (reg)); 108 109 return (reg); 110 } 111 112 static __inline void 113 armv7_pmnc_write(uint32_t reg) 114 { 115 116 __asm __volatile("mcr p15, 0, %0, c9, c12, 0" : : "r" (reg)); 117 } 118 119 /* 120 * Clock Counter Register (PMCCNTR) 121 * Counts processor clock cycles. 122 */ 123 static __inline uint32_t 124 armv7_ccnt_read(void) 125 { 126 uint32_t reg; 127 128 __asm __volatile("mrc p15, 0, %0, c9, c13, 0" : "=r" (reg)); 129 130 return (reg); 131 } 132 133 static __inline void 134 armv7_ccnt_write(uint32_t reg) 135 { 136 137 __asm __volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (reg)); 138 } 139 140 /* 141 * Interrupt Enable Set Register 142 */ 143 static __inline void 144 armv7_interrupt_enable(uint32_t pmc) 145 { 146 uint32_t reg; 147 148 reg = (1 << pmc); 149 150 __asm __volatile("mcr p15, 0, %0, c9, c14, 1" : : "r" (reg)); 151 } 152 153 /* 154 * Interrupt Clear Set Register 155 */ 156 static __inline void 157 armv7_interrupt_disable(uint32_t pmc) 158 { 159 uint32_t reg; 160 161 reg = (1 << pmc); 162 163 __asm __volatile("mcr p15, 0, %0, c9, c14, 2" : : "r" (reg)); 164 } 165 166 /* 167 * Overflow Flag Register 168 */ 169 static __inline uint32_t 170 armv7_flag_read(void) 171 { 172 uint32_t reg; 173 174 __asm __volatile("mrc p15, 0, %0, c9, c12, 3" : "=r" (reg)); 175 176 return (reg); 177 } 178 179 static __inline void 180 armv7_flag_write(uint32_t reg) 181 { 182 183 __asm __volatile("mcr p15, 0, %0, c9, c12, 3" : : "r" (reg)); 184 } 185 186 /* 187 * Event Selection Register 188 */ 189 static __inline void 190 armv7_evtsel_write(uint32_t reg) 191 { 192 193 __asm __volatile("mcr p15, 0, %0, c9, c13, 1" : : "r" (reg)); 194 } 195 196 /* 197 * PMSELR 198 */ 199 static __inline void 200 armv7_select_counter(unsigned int pmc) 201 { 202 203 __asm __volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (pmc)); 204 } 205 206 /* 207 * Counter Set Enable Register 208 */ 209 static __inline void 210 armv7_counter_enable(unsigned int pmc) 211 { 212 uint32_t reg; 213 214 reg = (1 << pmc); 215 216 __asm __volatile("mcr p15, 0, %0, c9, c12, 1" : : "r" (reg)); 217 } 218 219 /* 220 * Counter Clear Enable Register 221 */ 222 static __inline void 223 armv7_counter_disable(unsigned int pmc) 224 { 225 uint32_t reg; 226 227 reg = (1 << pmc); 228 229 __asm __volatile("mcr p15, 0, %0, c9, c12, 2" : : "r" (reg)); 230 } 231 232 /* 233 * Performance Count Register N 234 */ 235 static uint32_t 236 armv7_pmcn_read(unsigned int pmc) 237 { 238 uint32_t reg = 0; 239 240 KASSERT(pmc < 4, ("[armv7,%d] illegal PMC number %d", __LINE__, pmc)); 241 242 armv7_select_counter(pmc); 243 __asm __volatile("mrc p15, 0, %0, c9, c13, 2" : "=r" (reg)); 244 245 return (reg); 246 } 247 248 static uint32_t 249 armv7_pmcn_write(unsigned int pmc, uint32_t reg) 250 { 251 252 KASSERT(pmc < 4, ("[armv7,%d] illegal PMC number %d", __LINE__, pmc)); 253 254 armv7_select_counter(pmc); 255 __asm __volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (reg)); 256 257 return (reg); 258 } 259 260 static int 261 armv7_allocate_pmc(int cpu, int ri, struct pmc *pm, 262 const struct pmc_op_pmcallocate *a) 263 { 264 uint32_t caps, config; 265 struct armv7_cpu *pac; 266 enum pmc_event pe; 267 int i; 268 269 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 270 ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 271 KASSERT(ri >= 0 && ri < armv7_npmcs, 272 ("[armv7,%d] illegal row index %d", __LINE__, ri)); 273 274 pac = armv7_pcpu[cpu]; 275 276 caps = a->pm_caps; 277 if (a->pm_class != PMC_CLASS_ARMV7) 278 return (EINVAL); 279 pe = a->pm_ev; 280 281 for (i = 0; i < armv7_event_codes_size; i++) { 282 if (armv7_event_codes[i].pe_ev == pe) { 283 config = armv7_event_codes[i].pe_code; 284 break; 285 } 286 } 287 if (i == armv7_event_codes_size) 288 return EINVAL; 289 290 pm->pm_md.pm_armv7.pm_armv7_evsel = config; 291 292 PMCDBG(MDP,ALL,2,"armv7-allocate ri=%d -> config=0x%x", ri, config); 293 294 return 0; 295 } 296 297 298 static int 299 armv7_read_pmc(int cpu, int ri, pmc_value_t *v) 300 { 301 pmc_value_t tmp; 302 struct pmc *pm; 303 304 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 305 ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 306 KASSERT(ri >= 0 && ri < armv7_npmcs, 307 ("[armv7,%d] illegal row index %d", __LINE__, ri)); 308 309 pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 310 311 if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) 312 tmp = armv7_ccnt_read(); 313 else 314 tmp = armv7_pmcn_read(ri); 315 316 PMCDBG(MDP,REA,2,"armv7-read id=%d -> %jd", ri, tmp); 317 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 318 *v = ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); 319 else 320 *v = tmp; 321 322 return 0; 323 } 324 325 static int 326 armv7_write_pmc(int cpu, int ri, pmc_value_t v) 327 { 328 struct pmc *pm; 329 330 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 331 ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 332 KASSERT(ri >= 0 && ri < armv7_npmcs, 333 ("[armv7,%d] illegal row-index %d", __LINE__, ri)); 334 335 pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 336 337 if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 338 v = ARMV7_RELOAD_COUNT_TO_PERFCTR_VALUE(v); 339 340 PMCDBG(MDP,WRI,1,"armv7-write cpu=%d ri=%d v=%jx", cpu, ri, v); 341 342 if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) 343 armv7_ccnt_write(v); 344 else 345 armv7_pmcn_write(ri, v); 346 347 return 0; 348 } 349 350 static int 351 armv7_config_pmc(int cpu, int ri, struct pmc *pm) 352 { 353 struct pmc_hw *phw; 354 355 PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); 356 357 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 358 ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 359 KASSERT(ri >= 0 && ri < armv7_npmcs, 360 ("[armv7,%d] illegal row-index %d", __LINE__, ri)); 361 362 phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 363 364 KASSERT(pm == NULL || phw->phw_pmc == NULL, 365 ("[armv7,%d] pm=%p phw->pm=%p hwpmc not unconfigured", 366 __LINE__, pm, phw->phw_pmc)); 367 368 phw->phw_pmc = pm; 369 370 return 0; 371 } 372 373 static int 374 armv7_start_pmc(int cpu, int ri) 375 { 376 struct pmc_hw *phw; 377 uint32_t config; 378 struct pmc *pm; 379 380 phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 381 pm = phw->phw_pmc; 382 config = pm->pm_md.pm_armv7.pm_armv7_evsel; 383 384 /* 385 * Configure the event selection. 386 */ 387 armv7_select_counter(ri); 388 armv7_evtsel_write(config); 389 390 /* 391 * Enable the PMC. 392 */ 393 armv7_interrupt_enable(ri); 394 armv7_counter_enable(ri); 395 396 return 0; 397 } 398 399 static int 400 armv7_stop_pmc(int cpu, int ri) 401 { 402 struct pmc_hw *phw; 403 struct pmc *pm; 404 405 phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 406 pm = phw->phw_pmc; 407 408 /* 409 * Disable the PMCs. 410 */ 411 armv7_counter_disable(ri); 412 armv7_interrupt_disable(ri); 413 414 return 0; 415 } 416 417 static int 418 armv7_release_pmc(int cpu, int ri, struct pmc *pmc) 419 { 420 struct pmc_hw *phw; 421 422 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 423 ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 424 KASSERT(ri >= 0 && ri < armv7_npmcs, 425 ("[armv7,%d] illegal row-index %d", __LINE__, ri)); 426 427 phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 428 KASSERT(phw->phw_pmc == NULL, 429 ("[armv7,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 430 431 return 0; 432 } 433 434 static int 435 armv7_intr(int cpu, struct trapframe *tf) 436 { 437 struct armv7_cpu *pc; 438 int retval, ri; 439 struct pmc *pm; 440 int error; 441 int reg; 442 443 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 444 ("[armv7,%d] CPU %d out of range", __LINE__, cpu)); 445 446 retval = 0; 447 pc = armv7_pcpu[cpu]; 448 449 for (ri = 0; ri < armv7_npmcs; ri++) { 450 pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 451 if (pm == NULL) 452 continue; 453 if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 454 continue; 455 456 /* Check if counter has overflowed */ 457 if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) 458 reg = (1 << 31); 459 else 460 reg = (1 << ri); 461 462 if ((armv7_flag_read() & reg) == 0) { 463 continue; 464 } 465 466 /* Clear Overflow Flag */ 467 armv7_flag_write(reg); 468 469 retval = 1; /* Found an interrupting PMC. */ 470 if (pm->pm_state != PMC_STATE_RUNNING) 471 continue; 472 473 error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, 474 TRAPF_USERMODE(tf)); 475 if (error) 476 armv7_stop_pmc(cpu, ri); 477 478 /* Reload sampling count */ 479 armv7_write_pmc(cpu, ri, pm->pm_sc.pm_reloadcount); 480 } 481 482 return (retval); 483 } 484 485 static int 486 armv7_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 487 { 488 char armv7_name[PMC_NAME_MAX]; 489 struct pmc_hw *phw; 490 int error; 491 492 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 493 ("[armv7,%d], illegal CPU %d", __LINE__, cpu)); 494 KASSERT(ri >= 0 && ri < armv7_npmcs, 495 ("[armv7,%d] row-index %d out of range", __LINE__, ri)); 496 497 phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 498 snprintf(armv7_name, sizeof(armv7_name), "ARMV7-%d", ri); 499 if ((error = copystr(armv7_name, pi->pm_name, PMC_NAME_MAX, 500 NULL)) != 0) 501 return error; 502 pi->pm_class = PMC_CLASS_ARMV7; 503 if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 504 pi->pm_enabled = TRUE; 505 *ppmc = phw->phw_pmc; 506 } else { 507 pi->pm_enabled = FALSE; 508 *ppmc = NULL; 509 } 510 511 return (0); 512 } 513 514 static int 515 armv7_get_config(int cpu, int ri, struct pmc **ppm) 516 { 517 518 *ppm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 519 520 return 0; 521 } 522 523 /* 524 * XXX don't know what we should do here. 525 */ 526 static int 527 armv7_switch_in(struct pmc_cpu *pc, struct pmc_process *pp) 528 { 529 530 return 0; 531 } 532 533 static int 534 armv7_switch_out(struct pmc_cpu *pc, struct pmc_process *pp) 535 { 536 537 return 0; 538 } 539 540 static int 541 armv7_pcpu_init(struct pmc_mdep *md, int cpu) 542 { 543 struct armv7_cpu *pac; 544 struct pmc_hw *phw; 545 struct pmc_cpu *pc; 546 uint32_t pmnc; 547 int first_ri; 548 int cpuid; 549 int i; 550 551 KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 552 ("[armv7,%d] wrong cpu number %d", __LINE__, cpu)); 553 PMCDBG(MDP,INI,1,"armv7-init cpu=%d", cpu); 554 555 armv7_pcpu[cpu] = pac = malloc(sizeof(struct armv7_cpu), M_PMC, 556 M_WAITOK|M_ZERO); 557 558 cpuid = cpu_id(); 559 pac->cortex_ver = (cpuid >> CPU_ID_CORTEX_VER_SHIFT) & \ 560 CPU_ID_CORTEX_VER_MASK; 561 562 pac->pc_armv7pmcs = malloc(sizeof(struct pmc_hw) * armv7_npmcs, 563 M_PMC, M_WAITOK|M_ZERO); 564 pc = pmc_pcpu[cpu]; 565 first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_ARMV7].pcd_ri; 566 KASSERT(pc != NULL, ("[armv7,%d] NULL per-cpu pointer", __LINE__)); 567 568 for (i = 0, phw = pac->pc_armv7pmcs; i < armv7_npmcs; i++, phw++) { 569 phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 570 PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); 571 phw->phw_pmc = NULL; 572 pc->pc_hwpmcs[i + first_ri] = phw; 573 } 574 575 /* Enable unit */ 576 pmnc = armv7_pmnc_read(); 577 pmnc |= ARMV7_PMNC_ENABLE; 578 armv7_pmnc_write(pmnc); 579 580 return 0; 581 } 582 583 static int 584 armv7_pcpu_fini(struct pmc_mdep *md, int cpu) 585 { 586 uint32_t pmnc; 587 588 pmnc = armv7_pmnc_read(); 589 pmnc &= ~ARMV7_PMNC_ENABLE; 590 armv7_pmnc_write(pmnc); 591 592 return 0; 593 } 594 595 struct pmc_mdep * 596 pmc_armv7_initialize() 597 { 598 struct pmc_mdep *pmc_mdep; 599 struct pmc_classdep *pcd; 600 int reg; 601 602 reg = armv7_pmnc_read(); 603 604 armv7_npmcs = (reg >> ARMV7_PMNC_N_SHIFT) & \ 605 ARMV7_PMNC_N_MASK; 606 607 PMCDBG(MDP,INI,1,"armv7-init npmcs=%d", armv7_npmcs); 608 609 /* 610 * Allocate space for pointers to PMC HW descriptors and for 611 * the MDEP structure used by MI code. 612 */ 613 armv7_pcpu = malloc(sizeof(struct armv7_cpu *) * pmc_cpu_max(), 614 M_PMC, M_WAITOK | M_ZERO); 615 616 /* Just one class */ 617 pmc_mdep = pmc_mdep_alloc(1); 618 pmc_mdep->pmd_cputype = PMC_CPU_ARMV7; 619 620 pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_ARMV7]; 621 pcd->pcd_caps = ARMV7_PMC_CAPS; 622 pcd->pcd_class = PMC_CLASS_ARMV7; 623 pcd->pcd_num = armv7_npmcs; 624 pcd->pcd_ri = pmc_mdep->pmd_npmc; 625 pcd->pcd_width = 32; 626 627 pcd->pcd_allocate_pmc = armv7_allocate_pmc; 628 pcd->pcd_config_pmc = armv7_config_pmc; 629 pcd->pcd_pcpu_fini = armv7_pcpu_fini; 630 pcd->pcd_pcpu_init = armv7_pcpu_init; 631 pcd->pcd_describe = armv7_describe; 632 pcd->pcd_get_config = armv7_get_config; 633 pcd->pcd_read_pmc = armv7_read_pmc; 634 pcd->pcd_release_pmc = armv7_release_pmc; 635 pcd->pcd_start_pmc = armv7_start_pmc; 636 pcd->pcd_stop_pmc = armv7_stop_pmc; 637 pcd->pcd_write_pmc = armv7_write_pmc; 638 639 pmc_mdep->pmd_intr = armv7_intr; 640 pmc_mdep->pmd_switch_in = armv7_switch_in; 641 pmc_mdep->pmd_switch_out = armv7_switch_out; 642 643 pmc_mdep->pmd_npmc += armv7_npmcs; 644 645 return (pmc_mdep); 646 } 647 648 void 649 pmc_armv7_finalize(struct pmc_mdep *md) 650 { 651 652 } 653