1277835Sbr/*- 2277835Sbr * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com> 3277835Sbr * All rights reserved. 4277835Sbr * 5277835Sbr * This software was developed by SRI International and the University of 6277835Sbr * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) 7277835Sbr * ("CTSRD"), as part of the DARPA CRASH research programme. 8277835Sbr * 9277835Sbr * Redistribution and use in source and binary forms, with or without 10277835Sbr * modification, are permitted provided that the following conditions 11277835Sbr * are met: 12277835Sbr * 1. Redistributions of source code must retain the above copyright 13277835Sbr * notice, this list of conditions and the following disclaimer. 14277835Sbr * 2. Redistributions in binary form must reproduce the above copyright 15277835Sbr * notice, this list of conditions and the following disclaimer in the 16277835Sbr * documentation and/or other materials provided with the distribution. 17277835Sbr * 18277835Sbr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19277835Sbr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20277835Sbr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21277835Sbr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22277835Sbr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23277835Sbr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24277835Sbr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25277835Sbr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26277835Sbr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27277835Sbr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28277835Sbr * SUCH DAMAGE. 29277835Sbr */ 30277835Sbr 31277835Sbr#include <sys/cdefs.h> 32277835Sbr__FBSDID("$FreeBSD$"); 33277835Sbr 34277835Sbr#include <sys/param.h> 35277835Sbr#include <sys/systm.h> 36277835Sbr#include <sys/pmc.h> 37277835Sbr#include <sys/pmckern.h> 38277835Sbr 39277835Sbr#include <machine/pmc_mdep.h> 40277835Sbr#include <machine/cpu.h> 41277835Sbr 42277835Sbrstatic int armv7_npmcs; 43277835Sbr 44277835Sbrstruct armv7_event_code_map { 45277835Sbr enum pmc_event pe_ev; 46277835Sbr uint8_t pe_code; 47277835Sbr}; 48277835Sbr 49277835Sbr/* 50277835Sbr * Per-processor information. 51277835Sbr */ 52277835Sbrstruct armv7_cpu { 53277835Sbr struct pmc_hw *pc_armv7pmcs; 54277835Sbr}; 55277835Sbr 56277835Sbrstatic struct armv7_cpu **armv7_pcpu; 57277835Sbr 58277835Sbr/* 59277835Sbr * Interrupt Enable Set Register 60277835Sbr */ 61277835Sbrstatic __inline void 62277835Sbrarmv7_interrupt_enable(uint32_t pmc) 63277835Sbr{ 64277835Sbr uint32_t reg; 65277835Sbr 66277835Sbr reg = (1 << pmc); 67280790Sbz cp15_pminten_set(reg); 68277835Sbr} 69277835Sbr 70277835Sbr/* 71277835Sbr * Interrupt Clear Set Register 72277835Sbr */ 73277835Sbrstatic __inline void 74277835Sbrarmv7_interrupt_disable(uint32_t pmc) 75277835Sbr{ 76277835Sbr uint32_t reg; 77277835Sbr 78277835Sbr reg = (1 << pmc); 79280790Sbz cp15_pminten_clr(reg); 80277835Sbr} 81277835Sbr 82277835Sbr/* 83277835Sbr * Counter Set Enable Register 84277835Sbr */ 85277835Sbrstatic __inline void 86277835Sbrarmv7_counter_enable(unsigned int pmc) 87277835Sbr{ 88277835Sbr uint32_t reg; 89277835Sbr 90277835Sbr reg = (1 << pmc); 91280790Sbz cp15_pmcnten_set(reg); 92277835Sbr} 93277835Sbr 94277835Sbr/* 95277835Sbr * Counter Clear Enable Register 96277835Sbr */ 97277835Sbrstatic __inline void 98277835Sbrarmv7_counter_disable(unsigned int pmc) 99277835Sbr{ 100277835Sbr uint32_t reg; 101277835Sbr 102277835Sbr reg = (1 << pmc); 103280790Sbz cp15_pmcnten_clr(reg); 104277835Sbr} 105277835Sbr 106277835Sbr/* 107277835Sbr * Performance Count Register N 108277835Sbr */ 109277835Sbrstatic uint32_t 110277835Sbrarmv7_pmcn_read(unsigned int pmc) 111277835Sbr{ 112277835Sbr 113280790Sbz KASSERT(pmc < armv7_npmcs, ("%s: illegal PMC number %d", __func__, pmc)); 114277835Sbr 115280790Sbz cp15_pmselr_set(pmc); 116280790Sbz return (cp15_pmxevcntr_get()); 117277835Sbr} 118277835Sbr 119277835Sbrstatic uint32_t 120277835Sbrarmv7_pmcn_write(unsigned int pmc, uint32_t reg) 121277835Sbr{ 122277835Sbr 123280790Sbz KASSERT(pmc < armv7_npmcs, ("%s: illegal PMC number %d", __func__, pmc)); 124277835Sbr 125280790Sbz cp15_pmselr_set(pmc); 126280790Sbz cp15_pmxevcntr_set(reg); 127277835Sbr 128277835Sbr return (reg); 129277835Sbr} 130277835Sbr 131277835Sbrstatic int 132277835Sbrarmv7_allocate_pmc(int cpu, int ri, struct pmc *pm, 133277835Sbr const struct pmc_op_pmcallocate *a) 134277835Sbr{ 135277835Sbr struct armv7_cpu *pac; 136277835Sbr enum pmc_event pe; 137284218Sbr uint32_t config; 138284218Sbr uint32_t caps; 139277835Sbr 140277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 141277835Sbr ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 142277835Sbr KASSERT(ri >= 0 && ri < armv7_npmcs, 143277835Sbr ("[armv7,%d] illegal row index %d", __LINE__, ri)); 144277835Sbr 145277835Sbr pac = armv7_pcpu[cpu]; 146277835Sbr 147277835Sbr caps = a->pm_caps; 148277835Sbr if (a->pm_class != PMC_CLASS_ARMV7) 149277835Sbr return (EINVAL); 150277835Sbr pe = a->pm_ev; 151277835Sbr 152284218Sbr config = (pe & EVENT_ID_MASK); 153277835Sbr pm->pm_md.pm_armv7.pm_armv7_evsel = config; 154277835Sbr 155284218Sbr PMCDBG2(MDP, ALL, 2, "armv7-allocate ri=%d -> config=0x%x", ri, config); 156277835Sbr 157277835Sbr return 0; 158277835Sbr} 159277835Sbr 160277835Sbr 161277835Sbrstatic int 162277835Sbrarmv7_read_pmc(int cpu, int ri, pmc_value_t *v) 163277835Sbr{ 164277835Sbr pmc_value_t tmp; 165277835Sbr struct pmc *pm; 166277835Sbr 167277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 168277835Sbr ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 169277835Sbr KASSERT(ri >= 0 && ri < armv7_npmcs, 170277835Sbr ("[armv7,%d] illegal row index %d", __LINE__, ri)); 171277835Sbr 172277835Sbr pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 173277835Sbr 174277835Sbr if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) 175280790Sbz tmp = cp15_pmccntr_get(); 176277835Sbr else 177277835Sbr tmp = armv7_pmcn_read(ri); 178277835Sbr 179284218Sbr PMCDBG2(MDP, REA, 2, "armv7-read id=%d -> %jd", ri, tmp); 180277835Sbr if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 181277835Sbr *v = ARMV7_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp); 182277835Sbr else 183277835Sbr *v = tmp; 184277835Sbr 185277835Sbr return 0; 186277835Sbr} 187277835Sbr 188277835Sbrstatic int 189277835Sbrarmv7_write_pmc(int cpu, int ri, pmc_value_t v) 190277835Sbr{ 191277835Sbr struct pmc *pm; 192277835Sbr 193277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 194277835Sbr ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 195277835Sbr KASSERT(ri >= 0 && ri < armv7_npmcs, 196277835Sbr ("[armv7,%d] illegal row-index %d", __LINE__, ri)); 197277835Sbr 198277835Sbr pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 199277835Sbr 200277835Sbr if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 201277835Sbr v = ARMV7_RELOAD_COUNT_TO_PERFCTR_VALUE(v); 202277835Sbr 203284218Sbr PMCDBG3(MDP, WRI, 1, "armv7-write cpu=%d ri=%d v=%jx", cpu, ri, v); 204277835Sbr 205277835Sbr if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) 206280790Sbz cp15_pmccntr_set(v); 207277835Sbr else 208277835Sbr armv7_pmcn_write(ri, v); 209277835Sbr 210277835Sbr return 0; 211277835Sbr} 212277835Sbr 213277835Sbrstatic int 214277835Sbrarmv7_config_pmc(int cpu, int ri, struct pmc *pm) 215277835Sbr{ 216277835Sbr struct pmc_hw *phw; 217277835Sbr 218284218Sbr PMCDBG3(MDP, CFG, 1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); 219277835Sbr 220277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 221277835Sbr ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 222277835Sbr KASSERT(ri >= 0 && ri < armv7_npmcs, 223277835Sbr ("[armv7,%d] illegal row-index %d", __LINE__, ri)); 224277835Sbr 225277835Sbr phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 226277835Sbr 227277835Sbr KASSERT(pm == NULL || phw->phw_pmc == NULL, 228277835Sbr ("[armv7,%d] pm=%p phw->pm=%p hwpmc not unconfigured", 229277835Sbr __LINE__, pm, phw->phw_pmc)); 230277835Sbr 231277835Sbr phw->phw_pmc = pm; 232277835Sbr 233277835Sbr return 0; 234277835Sbr} 235277835Sbr 236277835Sbrstatic int 237277835Sbrarmv7_start_pmc(int cpu, int ri) 238277835Sbr{ 239277835Sbr struct pmc_hw *phw; 240277835Sbr uint32_t config; 241277835Sbr struct pmc *pm; 242277835Sbr 243277835Sbr phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 244277835Sbr pm = phw->phw_pmc; 245277835Sbr config = pm->pm_md.pm_armv7.pm_armv7_evsel; 246277835Sbr 247277835Sbr /* 248277835Sbr * Configure the event selection. 249277835Sbr */ 250280790Sbz cp15_pmselr_set(ri); 251280790Sbz cp15_pmxevtyper_set(config); 252277835Sbr 253277835Sbr /* 254277835Sbr * Enable the PMC. 255277835Sbr */ 256277835Sbr armv7_interrupt_enable(ri); 257277835Sbr armv7_counter_enable(ri); 258277835Sbr 259277835Sbr return 0; 260277835Sbr} 261277835Sbr 262277835Sbrstatic int 263277835Sbrarmv7_stop_pmc(int cpu, int ri) 264277835Sbr{ 265277835Sbr struct pmc_hw *phw; 266277835Sbr struct pmc *pm; 267277835Sbr 268277835Sbr phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 269277835Sbr pm = phw->phw_pmc; 270277835Sbr 271277835Sbr /* 272277835Sbr * Disable the PMCs. 273277835Sbr */ 274277835Sbr armv7_counter_disable(ri); 275277835Sbr armv7_interrupt_disable(ri); 276277835Sbr 277277835Sbr return 0; 278277835Sbr} 279277835Sbr 280277835Sbrstatic int 281277835Sbrarmv7_release_pmc(int cpu, int ri, struct pmc *pmc) 282277835Sbr{ 283277835Sbr struct pmc_hw *phw; 284277835Sbr 285277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 286277835Sbr ("[armv7,%d] illegal CPU value %d", __LINE__, cpu)); 287277835Sbr KASSERT(ri >= 0 && ri < armv7_npmcs, 288277835Sbr ("[armv7,%d] illegal row-index %d", __LINE__, ri)); 289277835Sbr 290277835Sbr phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 291277835Sbr KASSERT(phw->phw_pmc == NULL, 292277835Sbr ("[armv7,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); 293277835Sbr 294277835Sbr return 0; 295277835Sbr} 296277835Sbr 297277835Sbrstatic int 298277835Sbrarmv7_intr(int cpu, struct trapframe *tf) 299277835Sbr{ 300277835Sbr struct armv7_cpu *pc; 301277835Sbr int retval, ri; 302277835Sbr struct pmc *pm; 303277835Sbr int error; 304277835Sbr int reg; 305277835Sbr 306277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 307277835Sbr ("[armv7,%d] CPU %d out of range", __LINE__, cpu)); 308277835Sbr 309277835Sbr retval = 0; 310277835Sbr pc = armv7_pcpu[cpu]; 311277835Sbr 312277835Sbr for (ri = 0; ri < armv7_npmcs; ri++) { 313277835Sbr pm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 314277835Sbr if (pm == NULL) 315277835Sbr continue; 316277835Sbr if (!PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) 317277835Sbr continue; 318277835Sbr 319277835Sbr /* Check if counter has overflowed */ 320277835Sbr if (pm->pm_md.pm_armv7.pm_armv7_evsel == 0xFF) 321277835Sbr reg = (1 << 31); 322277835Sbr else 323277835Sbr reg = (1 << ri); 324277835Sbr 325280790Sbz if ((cp15_pmovsr_get() & reg) == 0) { 326277835Sbr continue; 327277835Sbr } 328277835Sbr 329277835Sbr /* Clear Overflow Flag */ 330280790Sbz cp15_pmovsr_set(reg); 331277835Sbr 332277835Sbr retval = 1; /* Found an interrupting PMC. */ 333277835Sbr if (pm->pm_state != PMC_STATE_RUNNING) 334277835Sbr continue; 335277835Sbr 336277835Sbr error = pmc_process_interrupt(cpu, PMC_HR, pm, tf, 337277835Sbr TRAPF_USERMODE(tf)); 338277835Sbr if (error) 339277835Sbr armv7_stop_pmc(cpu, ri); 340277835Sbr 341277835Sbr /* Reload sampling count */ 342277835Sbr armv7_write_pmc(cpu, ri, pm->pm_sc.pm_reloadcount); 343277835Sbr } 344277835Sbr 345277835Sbr return (retval); 346277835Sbr} 347277835Sbr 348277835Sbrstatic int 349277835Sbrarmv7_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) 350277835Sbr{ 351277835Sbr char armv7_name[PMC_NAME_MAX]; 352277835Sbr struct pmc_hw *phw; 353277835Sbr int error; 354277835Sbr 355277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 356277835Sbr ("[armv7,%d], illegal CPU %d", __LINE__, cpu)); 357277835Sbr KASSERT(ri >= 0 && ri < armv7_npmcs, 358277835Sbr ("[armv7,%d] row-index %d out of range", __LINE__, ri)); 359277835Sbr 360277835Sbr phw = &armv7_pcpu[cpu]->pc_armv7pmcs[ri]; 361277835Sbr snprintf(armv7_name, sizeof(armv7_name), "ARMV7-%d", ri); 362277835Sbr if ((error = copystr(armv7_name, pi->pm_name, PMC_NAME_MAX, 363277835Sbr NULL)) != 0) 364277835Sbr return error; 365277835Sbr pi->pm_class = PMC_CLASS_ARMV7; 366277835Sbr if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) { 367277835Sbr pi->pm_enabled = TRUE; 368277835Sbr *ppmc = phw->phw_pmc; 369277835Sbr } else { 370277835Sbr pi->pm_enabled = FALSE; 371277835Sbr *ppmc = NULL; 372277835Sbr } 373277835Sbr 374277835Sbr return (0); 375277835Sbr} 376277835Sbr 377277835Sbrstatic int 378277835Sbrarmv7_get_config(int cpu, int ri, struct pmc **ppm) 379277835Sbr{ 380277835Sbr 381277835Sbr *ppm = armv7_pcpu[cpu]->pc_armv7pmcs[ri].phw_pmc; 382277835Sbr 383277835Sbr return 0; 384277835Sbr} 385277835Sbr 386277835Sbr/* 387277835Sbr * XXX don't know what we should do here. 388277835Sbr */ 389277835Sbrstatic int 390277835Sbrarmv7_switch_in(struct pmc_cpu *pc, struct pmc_process *pp) 391277835Sbr{ 392277835Sbr 393277835Sbr return 0; 394277835Sbr} 395277835Sbr 396277835Sbrstatic int 397277835Sbrarmv7_switch_out(struct pmc_cpu *pc, struct pmc_process *pp) 398277835Sbr{ 399277835Sbr 400277835Sbr return 0; 401277835Sbr} 402277835Sbr 403277835Sbrstatic int 404277835Sbrarmv7_pcpu_init(struct pmc_mdep *md, int cpu) 405277835Sbr{ 406277835Sbr struct armv7_cpu *pac; 407277835Sbr struct pmc_hw *phw; 408277835Sbr struct pmc_cpu *pc; 409277835Sbr uint32_t pmnc; 410277835Sbr int first_ri; 411277835Sbr int i; 412277835Sbr 413277835Sbr KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), 414277835Sbr ("[armv7,%d] wrong cpu number %d", __LINE__, cpu)); 415284218Sbr PMCDBG1(MDP, INI, 1, "armv7-init cpu=%d", cpu); 416277835Sbr 417277835Sbr armv7_pcpu[cpu] = pac = malloc(sizeof(struct armv7_cpu), M_PMC, 418277835Sbr M_WAITOK|M_ZERO); 419277835Sbr 420277835Sbr pac->pc_armv7pmcs = malloc(sizeof(struct pmc_hw) * armv7_npmcs, 421277835Sbr M_PMC, M_WAITOK|M_ZERO); 422277835Sbr pc = pmc_pcpu[cpu]; 423277835Sbr first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_ARMV7].pcd_ri; 424277835Sbr KASSERT(pc != NULL, ("[armv7,%d] NULL per-cpu pointer", __LINE__)); 425277835Sbr 426277835Sbr for (i = 0, phw = pac->pc_armv7pmcs; i < armv7_npmcs; i++, phw++) { 427277835Sbr phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | 428277835Sbr PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i); 429277835Sbr phw->phw_pmc = NULL; 430277835Sbr pc->pc_hwpmcs[i + first_ri] = phw; 431277835Sbr } 432277835Sbr 433277835Sbr /* Enable unit */ 434280790Sbz pmnc = cp15_pmcr_get(); 435277835Sbr pmnc |= ARMV7_PMNC_ENABLE; 436280790Sbz cp15_pmcr_set(pmnc); 437277835Sbr 438277835Sbr return 0; 439277835Sbr} 440277835Sbr 441277835Sbrstatic int 442277835Sbrarmv7_pcpu_fini(struct pmc_mdep *md, int cpu) 443277835Sbr{ 444277835Sbr uint32_t pmnc; 445277835Sbr 446280790Sbz pmnc = cp15_pmcr_get(); 447277835Sbr pmnc &= ~ARMV7_PMNC_ENABLE; 448280790Sbz cp15_pmcr_set(pmnc); 449277835Sbr 450277835Sbr return 0; 451277835Sbr} 452277835Sbr 453277835Sbrstruct pmc_mdep * 454277835Sbrpmc_armv7_initialize() 455277835Sbr{ 456277835Sbr struct pmc_mdep *pmc_mdep; 457277835Sbr struct pmc_classdep *pcd; 458284218Sbr int idcode; 459277835Sbr int reg; 460277835Sbr 461280790Sbz reg = cp15_pmcr_get(); 462277835Sbr armv7_npmcs = (reg >> ARMV7_PMNC_N_SHIFT) & \ 463277835Sbr ARMV7_PMNC_N_MASK; 464284218Sbr idcode = (reg & ARMV7_IDCODE_MASK) >> ARMV7_IDCODE_SHIFT; 465277835Sbr 466284218Sbr PMCDBG1(MDP, INI, 1, "armv7-init npmcs=%d", armv7_npmcs); 467277835Sbr 468277835Sbr /* 469277835Sbr * Allocate space for pointers to PMC HW descriptors and for 470277835Sbr * the MDEP structure used by MI code. 471277835Sbr */ 472277835Sbr armv7_pcpu = malloc(sizeof(struct armv7_cpu *) * pmc_cpu_max(), 473277835Sbr M_PMC, M_WAITOK | M_ZERO); 474277835Sbr 475277835Sbr /* Just one class */ 476277835Sbr pmc_mdep = pmc_mdep_alloc(1); 477277835Sbr 478284218Sbr switch (idcode) { 479284218Sbr case ARMV7_IDCODE_CORTEX_A9: 480284218Sbr pmc_mdep->pmd_cputype = PMC_CPU_ARMV7_CORTEX_A9; 481284218Sbr break; 482284218Sbr default: 483284218Sbr case ARMV7_IDCODE_CORTEX_A8: 484284218Sbr /* 485284218Sbr * On A8 we implemented common events only, 486284218Sbr * so use it for the rest of machines. 487284218Sbr */ 488284218Sbr pmc_mdep->pmd_cputype = PMC_CPU_ARMV7_CORTEX_A8; 489284218Sbr break; 490284218Sbr } 491284218Sbr 492277835Sbr pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_ARMV7]; 493277835Sbr pcd->pcd_caps = ARMV7_PMC_CAPS; 494277835Sbr pcd->pcd_class = PMC_CLASS_ARMV7; 495277835Sbr pcd->pcd_num = armv7_npmcs; 496277835Sbr pcd->pcd_ri = pmc_mdep->pmd_npmc; 497277835Sbr pcd->pcd_width = 32; 498277835Sbr 499277835Sbr pcd->pcd_allocate_pmc = armv7_allocate_pmc; 500277835Sbr pcd->pcd_config_pmc = armv7_config_pmc; 501277835Sbr pcd->pcd_pcpu_fini = armv7_pcpu_fini; 502277835Sbr pcd->pcd_pcpu_init = armv7_pcpu_init; 503277835Sbr pcd->pcd_describe = armv7_describe; 504277835Sbr pcd->pcd_get_config = armv7_get_config; 505277835Sbr pcd->pcd_read_pmc = armv7_read_pmc; 506277835Sbr pcd->pcd_release_pmc = armv7_release_pmc; 507277835Sbr pcd->pcd_start_pmc = armv7_start_pmc; 508277835Sbr pcd->pcd_stop_pmc = armv7_stop_pmc; 509277835Sbr pcd->pcd_write_pmc = armv7_write_pmc; 510277835Sbr 511277835Sbr pmc_mdep->pmd_intr = armv7_intr; 512277835Sbr pmc_mdep->pmd_switch_in = armv7_switch_in; 513277835Sbr pmc_mdep->pmd_switch_out = armv7_switch_out; 514277835Sbr 515277835Sbr pmc_mdep->pmd_npmc += armv7_npmcs; 516277835Sbr 517277835Sbr return (pmc_mdep); 518277835Sbr} 519277835Sbr 520277835Sbrvoid 521277835Sbrpmc_armv7_finalize(struct pmc_mdep *md) 522277835Sbr{ 523277835Sbr 524277835Sbr} 525