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