]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/dev/hwpmc/hwpmc_powerpc.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / dev / hwpmc / hwpmc_powerpc.c
1 /*-
2  * Copyright (c) 2011 Justin Hibbits
3  * Copyright (c) 2005, Joseph Koshy
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/pmc.h>
34 #include <sys/pmckern.h>
35 #include <sys/systm.h>
36
37 #include <machine/pmc_mdep.h>
38 #include <machine/spr.h>
39 #include <machine/cpu.h>
40
41 #define POWERPC_PMC_CAPS        (PMC_CAP_INTERRUPT | PMC_CAP_USER |     \
42                                  PMC_CAP_SYSTEM | PMC_CAP_EDGE |        \
43                                  PMC_CAP_THRESHOLD | PMC_CAP_READ |     \
44                                  PMC_CAP_WRITE | PMC_CAP_INVERT |       \
45                                  PMC_CAP_QUALIFIER)
46
47 #define PPC_SET_PMC1SEL(r, x)   ((r & ~(SPR_MMCR0_PMC1SEL(0x3f))) | SPR_MMCR0_PMC1SEL(x))
48 #define PPC_SET_PMC2SEL(r, x)   ((r & ~(SPR_MMCR0_PMC2SEL(0x3f))) | SPR_MMCR0_PMC2SEL(x))
49 #define PPC_SET_PMC3SEL(r, x)   ((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x))
50 #define PPC_SET_PMC4SEL(r, x)   ((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x))
51 #define PPC_SET_PMC5SEL(r, x)   ((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x))
52 #define PPC_SET_PMC6SEL(r, x)   ((r & ~(SPR_MMCR1_PMC6SEL(0x3f))) | SPR_MMCR1_PMC6SEL(x))
53
54 /* Change this when we support more than just the 7450. */
55 #define PPC_MAX_PMCS    6
56
57 #define POWERPC_PMC_KERNEL_ENABLE       (0x1 << 30)
58 #define POWERPC_PMC_USER_ENABLE         (0x1 << 31)
59
60 #define POWERPC_PMC_ENABLE              (POWERPC_PMC_KERNEL_ENABLE | POWERPC_PMC_USER_ENABLE)
61 #define POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(V)        (0x80000000-(V))
62 #define POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(P)        ((P)-0x80000000)
63 #define POWERPC_PMC_HAS_OVERFLOWED(x) (powerpc_pmcn_read(x) & (0x1 << 31))
64
65
66 /*
67  * This should work for every 32-bit PowerPC implementation I know of (G3 and G4
68  * specifically).  PoewrPC 970 will take more work.
69  */
70
71 /*
72  * Per-processor information.
73  */
74 struct powerpc_cpu {
75         struct pmc_hw   *pc_ppcpmcs;
76 };
77
78 static struct powerpc_cpu **powerpc_pcpu;
79
80 struct powerpc_event_code_map {
81         enum pmc_event  pe_ev;       /* enum value */
82         uint8_t         pe_counter_mask;  /* Which counter this can be counted in. */
83         uint8_t                 pe_code;     /* numeric code */
84 };
85
86 #define PPC_PMC_MASK1   0
87 #define PPC_PMC_MASK2   1
88 #define PPC_PMC_MASK3   2
89 #define PPC_PMC_MASK4   3
90 #define PPC_PMC_MASK5   4
91 #define PPC_PMC_MASK6   5
92 #define PPC_PMC_MASK_ALL        0x3f
93
94 #define PMC_POWERPC_EVENT(id, mask, number) \
95         { .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number }
96
97 static struct powerpc_event_code_map powerpc_event_codes[] = {
98         PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1),
99         PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2),
100         PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3),
101         PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4),
102         PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5),
103         PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7),
104         PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8),
105         PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9),
106         PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10),
107         PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11),
108         PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12),
109         PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13),
110         PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14),
111         PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15),
112         PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16),
113         PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17),
114         PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18),
115         PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19),
116         PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20),
117         PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21),
118         PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22),
119         PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23),
120         PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24),
121         PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25),
122         PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26),
123         PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27),
124         PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28),
125         PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29),
126         PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30),
127         PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31),
128         PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32),
129         PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33),
130         PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34),
131         PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35),
132         PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36),
133         PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37),
134         PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38),
135         PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39),
136         PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40),
137         PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41),
138         PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42),
139         PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43),
140         PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44),
141         PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45),
142         PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46),
143         PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47),
144         PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48),
145         PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49),
146         PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50),
147         PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51),
148         PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52),
149         PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53),
150         PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54),
151         PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55),
152         PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56),
153         PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57),
154         PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58),
155         PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59),
156         PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60),
157         PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61),
158         PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62),
159         PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63),
160         PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64),
161         PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65),
162         PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66),
163         PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67),
164         PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68),
165         PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70),
166         PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71),
167         PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72),
168         PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73),
169         PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74),
170         PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75),
171         PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76),
172         PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77),
173         PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78),
174         PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79),
175         PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80),
176         PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81),
177         PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82),
178         PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83),
179         PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84),
180         PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85),
181         PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86),
182         PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87),
183         PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88),
184         PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89),
185         PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90),
186         PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91),
187         PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92),
188         PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93),
189         PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94),
190         PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23),
191         PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24),
192         PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25),
193         PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26),
194         PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27),
195         PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28),
196         PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29),
197         PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30),
198         PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31),
199         PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32),
200         PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33),
201         PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34),
202         PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35),
203         PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36),
204         PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37),
205         PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38),
206         PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39),
207         PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40),
208         PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41),
209         PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42),
210         PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43),
211         PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44),
212         PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45),
213         PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46),
214         PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47),
215         PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48),
216         PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49),
217         PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50),
218         PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51),
219         PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52),
220         PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53),
221         PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54),
222         PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55),
223         PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56),
224         PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57),
225         PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58),
226         PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59),
227         PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60),
228         PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61),
229         PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62),
230         PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8),
231         PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9),
232         PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10),
233         PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11),
234         PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12),
235         PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13),
236         PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14),
237         PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15),
238         PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16),
239         PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17),
240         PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18),
241         PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19),
242         PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20),
243         PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21),
244         PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22),
245         PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23),
246         PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24),
247         PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25),
248         PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26),
249         PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27),
250         PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28),
251         PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29),
252         PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30),
253         PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31),
254         PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14),
255         PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15),
256         PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16),
257         PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17),
258         PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18),
259         PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19),
260         PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20),
261         PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21),
262         PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22),
263         PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23),
264         PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24),
265         PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25),
266         PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26),
267         PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27),
268         PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28),
269         PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29),
270         PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30),
271         PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2),
272         PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3),
273         PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4),
274         PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5),
275         PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6),
276         PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7),
277         PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8),
278         PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9),
279         PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10),
280         PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11),
281         PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13),
282         PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14),
283         PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15),
284         PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16),
285         PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17),
286         PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18),
287         PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19),
288         PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20),
289         PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8),
290         PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9),
291         PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10),
292         PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11),
293         PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16),
294         PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17),
295         PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19),
296         PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20),
297         PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21),
298         PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22),
299         PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23),
300         PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24),
301         PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25),
302         PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26),
303         PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27),
304         PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28),
305         PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42),
306         PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43),
307         PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44),
308         PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45),
309         PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46),
310         PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47),
311         PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48),
312         PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49),
313         PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50),
314         PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51),
315         PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52),
316         PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53),
317         PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54),
318         PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55),
319         PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56),
320         PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57)
321 };
322
323 const size_t powerpc_event_codes_size = 
324         sizeof(powerpc_event_codes) / sizeof(powerpc_event_codes[0]);
325
326 int
327 pmc_save_kernel_callchain(uintptr_t *cc, int maxsamples,
328     struct trapframe *tf)
329 {
330         (void) cc;
331         (void) maxsamples;
332         (void) tf;
333         return (0);
334 }
335
336 static pmc_value_t
337 powerpc_pmcn_read(unsigned int pmc)
338 {
339         switch (pmc) {
340                 case 0:
341                         return mfspr(SPR_PMC1);
342                         break;
343                 case 1:
344                         return mfspr(SPR_PMC2);
345                         break;
346                 case 2:
347                         return mfspr(SPR_PMC3);
348                         break;
349                 case 3:
350                         return mfspr(SPR_PMC4);
351                         break;
352                 case 4:
353                         return mfspr(SPR_PMC5);
354                         break;
355                 case 5:
356                         return mfspr(SPR_PMC6);
357                 default:
358                         panic("Invalid PMC number: %d\n", pmc);
359         }
360 }
361
362 static void
363 powerpc_pmcn_write(unsigned int pmc, uint32_t val)
364 {
365         switch (pmc) {
366                 case 0:
367                         mtspr(SPR_PMC1, val);
368                         break;
369                 case 1:
370                         mtspr(SPR_PMC2, val);
371                         break;
372                 case 2:
373                         mtspr(SPR_PMC3, val);
374                         break;
375                 case 3:
376                         mtspr(SPR_PMC4, val);
377                         break;
378                 case 4:
379                         mtspr(SPR_PMC5, val);
380                         break;
381                 case 5:
382                         mtspr(SPR_PMC6, val);
383                         break;
384                 default:
385                         panic("Invalid PMC number: %d\n", pmc);
386         }
387 }
388
389 static int
390 powerpc_allocate_pmc(int cpu, int ri, struct pmc *pm,
391   const struct pmc_op_pmcallocate *a)
392 {
393         enum pmc_event pe;
394         uint32_t caps, config, counter;
395         int i;
396
397         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
398             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
399         KASSERT(ri >= 0 && ri < PPC_MAX_PMCS,
400             ("[powerpc,%d] illegal row index %d", __LINE__, ri));
401
402         caps = a->pm_caps;
403
404         /*
405          * TODO: Check actual class for different generations.
406          */
407         if (a->pm_class != PMC_CLASS_PPC7450)
408                 return (EINVAL);
409         pe = a->pm_ev;
410         for (i = 0; i < powerpc_event_codes_size; i++) {
411                 if (powerpc_event_codes[i].pe_ev == pe) {
412                         config = powerpc_event_codes[i].pe_code;
413                         counter =  powerpc_event_codes[i].pe_counter_mask;
414                         break;
415                 }
416         }
417         if (i == powerpc_event_codes_size)
418                 return (EINVAL);
419
420         if ((counter & (1 << ri)) == 0)
421                 return (EINVAL);
422
423         if (caps & PMC_CAP_SYSTEM)
424                 config |= POWERPC_PMC_KERNEL_ENABLE;
425         if (caps & PMC_CAP_USER)
426                 config |= POWERPC_PMC_USER_ENABLE;
427         if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
428                 config |= POWERPC_PMC_ENABLE;
429
430         pm->pm_md.pm_powerpc.pm_powerpc_evsel = config;
431
432         PMCDBG(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config);
433
434         return 0;
435 }
436
437 static int
438 powerpc_read_pmc(int cpu, int ri, pmc_value_t *v)
439 {
440         struct pmc *pm;
441         pmc_value_t tmp;
442
443         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
444             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
445         KASSERT(ri >= 0 && ri < PPC_MAX_PMCS,
446             ("[powerpc,%d] illegal row index %d", __LINE__, ri));
447
448         pm  = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
449         tmp = powerpc_pmcn_read(ri);
450         PMCDBG(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 powerpc_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 < PPC_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         PMCDBG(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v);
475
476         powerpc_pmcn_write(ri, v);
477
478         return 0;
479 }
480
481 static int
482 powerpc_config_pmc(int cpu, int ri, struct pmc *pm)
483 {
484         struct pmc_hw *phw;
485
486         PMCDBG(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
487
488         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
489             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
490         KASSERT(ri >= 0 && ri < PPC_MAX_PMCS,
491             ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
492
493         phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
494
495         KASSERT(pm == NULL || phw->phw_pmc == NULL,
496             ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
497             __LINE__, pm, phw->phw_pmc));
498
499         phw->phw_pmc = pm;
500
501         return 0;
502 }
503
504 static int
505 powerpc_start_pmc(int cpu, int ri)
506 {
507         uint32_t config;
508         struct pmc *pm;
509         struct pmc_hw *phw;
510         register_t pmc_mmcr;
511
512         phw    = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
513         pm     = phw->phw_pmc;
514         config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE;
515
516         /* Enable the PMC. */
517         switch (ri) {
518         case 0:
519                 pmc_mmcr = mfspr(SPR_MMCR0);
520                 pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config);
521                 mtspr(SPR_MMCR0, pmc_mmcr);
522                 break;
523         case 1:
524                 pmc_mmcr = mfspr(SPR_MMCR0);
525                 pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config);
526                 mtspr(SPR_MMCR0, pmc_mmcr);
527                 break;
528         case 2:
529                 pmc_mmcr = mfspr(SPR_MMCR1);
530                 pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config);
531                 mtspr(SPR_MMCR1, pmc_mmcr);
532                 break;
533         case 3:
534                 pmc_mmcr = mfspr(SPR_MMCR0);
535                 pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config);
536                 mtspr(SPR_MMCR0, pmc_mmcr);
537                 break;
538         case 4:
539                 pmc_mmcr = mfspr(SPR_MMCR1);
540                 pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config);
541                 mtspr(SPR_MMCR1, pmc_mmcr);
542                 break;
543         case 5:
544                 pmc_mmcr = mfspr(SPR_MMCR1);
545                 pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config);
546                 mtspr(SPR_MMCR1, pmc_mmcr);
547                 break;
548         default:
549                 break;
550         }
551         
552         /* The mask is inverted (enable is 1) compared to the flags in MMCR0, which
553          * are Freeze flags.
554          */
555         config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE;
556
557         pmc_mmcr = mfspr(SPR_MMCR0);
558         pmc_mmcr &= ~SPR_MMCR0_FC;
559         pmc_mmcr |= config;
560         mtspr(SPR_MMCR0, pmc_mmcr);
561
562         return 0;
563 }
564
565 static int
566 powerpc_stop_pmc(int cpu, int ri)
567 {
568         struct pmc *pm;
569         struct pmc_hw *phw;
570         register_t pmc_mmcr;
571
572         phw    = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
573         pm     = phw->phw_pmc;
574
575         /*
576          * Disable the PMCs.
577          */
578         switch (ri) {
579         case 0:
580                 pmc_mmcr = mfspr(SPR_MMCR0);
581                 pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, 0);
582                 mtspr(SPR_MMCR0, pmc_mmcr);
583                 break;
584         case 1:
585                 pmc_mmcr = mfspr(SPR_MMCR0);
586                 pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, 0);
587                 mtspr(SPR_MMCR0, pmc_mmcr);
588                 break;
589         case 2:
590                 pmc_mmcr = mfspr(SPR_MMCR1);
591                 pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, 0);
592                 mtspr(SPR_MMCR1, pmc_mmcr);
593                 break;
594         case 3:
595                 pmc_mmcr = mfspr(SPR_MMCR0);
596                 pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, 0);
597                 mtspr(SPR_MMCR0, pmc_mmcr);
598                 break;
599         case 4:
600                 pmc_mmcr = mfspr(SPR_MMCR1);
601                 pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, 0);
602                 mtspr(SPR_MMCR1, pmc_mmcr);
603                 break;
604         case 5:
605                 pmc_mmcr = mfspr(SPR_MMCR1);
606                 pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, 0);
607                 mtspr(SPR_MMCR1, pmc_mmcr);
608                 break;
609         default:
610                 break;
611         }
612         return 0;
613 }
614
615 static int
616 powerpc_release_pmc(int cpu, int ri, struct pmc *pmc)
617 {
618         struct pmc_hw *phw;
619
620         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
621             ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
622         KASSERT(ri >= 0 && ri < PPC_MAX_PMCS,
623             ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
624
625         phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
626         KASSERT(phw->phw_pmc == NULL,
627             ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
628
629         return 0;
630 }
631
632 static int
633 powerpc_switch_in(struct pmc_cpu *pc, struct pmc_process *pp)
634 {
635         return 0;
636 }
637
638 static int
639 powerpc_switch_out(struct pmc_cpu *pc, struct pmc_process *pp)
640 {
641         return 0;
642 }
643
644 static int
645 powerpc_intr(int cpu, struct trapframe *tf)
646 {
647         int i, error, retval;
648         uint32_t config;
649         struct pmc *pm;
650         struct powerpc_cpu *pac;
651         pmc_value_t v;
652
653         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
654             ("[powerpc,%d] out of range CPU %d", __LINE__, cpu));
655
656         PMCDBG(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf,
657             TRAPF_USERMODE(tf));
658
659         retval = 0;
660
661         pac = powerpc_pcpu[cpu];
662
663         /*
664          * look for all PMCs that have interrupted:
665          * - look for a running, sampling PMC which has overflowed
666          *   and which has a valid 'struct pmc' association
667          *
668          * If found, we call a helper to process the interrupt.
669          */
670
671         for (i = 0; i < PPC_MAX_PMCS; i++) {
672                 if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL ||
673                     !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
674                         continue;
675                 }
676
677                 if (!POWERPC_PMC_HAS_OVERFLOWED(i))
678                         continue;
679
680                 retval = 1;     /* Found an interrupting PMC. */
681
682                 if (pm->pm_state != PMC_STATE_RUNNING)
683                         continue;
684
685                 /* Stop the PMC, reload count. */
686                 v       = pm->pm_sc.pm_reloadcount;
687                 config  = mfspr(SPR_MMCR0);
688
689                 mtspr(SPR_MMCR0, config | SPR_MMCR0_FC);
690                 powerpc_pmcn_write(i, v);
691
692                 /* Restart the counter if logging succeeded. */
693                 error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
694                     TRAPF_USERMODE(tf));
695                 mtspr(SPR_MMCR0, config);
696                 if (error != 0)
697                         powerpc_stop_pmc(cpu, i);
698                 atomic_add_int(retval ? &pmc_stats.pm_intr_processed :
699                                 &pmc_stats.pm_intr_ignored, 1);
700
701         }
702
703         /* Re-enable PERF exceptions. */
704         mtspr(SPR_MMCR0, mfspr(SPR_MMCR0) | SPR_MMCR0_PMXE);
705
706         return (retval);
707 }
708
709 static int
710 powerpc_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc)
711 {
712         int error;
713         struct pmc_hw *phw;
714         char powerpc_name[PMC_NAME_MAX];
715
716         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
717             ("[powerpc,%d], illegal CPU %d", __LINE__, cpu));
718         KASSERT(ri >= 0 && ri < PPC_MAX_PMCS,
719             ("[powerpc,%d] row-index %d out of range", __LINE__, ri));
720
721         phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
722         snprintf(powerpc_name, sizeof(powerpc_name), "POWERPC-%d", ri);
723         if ((error = copystr(powerpc_name, pi->pm_name, PMC_NAME_MAX,
724             NULL)) != 0)
725                 return error;
726         pi->pm_class = PMC_CLASS_PPC7450;
727         if (phw->phw_state & PMC_PHW_FLAG_IS_ENABLED) {
728                 pi->pm_enabled = TRUE;
729                 *ppmc          = phw->phw_pmc;
730         } else {
731                 pi->pm_enabled = FALSE;
732                 *ppmc          = NULL;
733         }
734
735         return (0);
736 }
737
738 static int
739 powerpc_get_config(int cpu, int ri, struct pmc **ppm)
740 {
741         *ppm = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
742
743         return 0;
744 }
745
746 static int
747 powerpc_pcpu_init(struct pmc_mdep *md, int cpu)
748 {
749         int first_ri, i;
750         struct pmc_cpu *pc;
751         struct powerpc_cpu *pac;
752         struct pmc_hw  *phw;
753
754         KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
755             ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu));
756         PMCDBG(MDP,INI,1,"powerpc-init cpu=%d", cpu);
757
758         powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC,
759             M_WAITOK|M_ZERO);
760         pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * PPC_MAX_PMCS,
761             M_PMC, M_WAITOK|M_ZERO);
762         pc = pmc_pcpu[cpu];
763         first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450].pcd_ri;
764         KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__));
765
766         for (i = 0, phw = pac->pc_ppcpmcs; i < PPC_MAX_PMCS; i++, phw++) {
767                 phw->phw_state    = PMC_PHW_FLAG_IS_ENABLED |
768                     PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i);
769                 phw->phw_pmc      = NULL;
770                 pc->pc_hwpmcs[i + first_ri] = phw;
771         }
772
773         /* Clear the MMCRs, and set FC, to disable all PMCs. */
774         mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE);
775         mtspr(SPR_MMCR1, 0);
776
777         return 0;
778 }
779
780 static int
781 powerpc_pcpu_fini(struct pmc_mdep *md, int cpu)
782 {
783         uint32_t mmcr0 = mfspr(SPR_MMCR0);
784
785         mmcr0 |= SPR_MMCR0_FC;
786         mtspr(SPR_MMCR0, mmcr0);
787         free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC);
788         free(powerpc_pcpu[cpu], M_PMC);
789         return 0;
790 }
791
792 struct pmc_mdep *
793 pmc_md_initialize()
794 {
795         struct pmc_mdep *pmc_mdep;
796         struct pmc_classdep *pcd;
797         
798         /*
799          * Allocate space for pointers to PMC HW descriptors and for
800          * the MDEP structure used by MI code.
801          */
802         powerpc_pcpu = malloc(sizeof(struct powerpc_cpu *) * pmc_cpu_max(), M_PMC,
803                            M_WAITOK|M_ZERO);
804
805         /* Just one class */
806         pmc_mdep = pmc_mdep_alloc(1);
807
808         pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450;
809
810         pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_PPC7450];
811         pcd->pcd_caps  = POWERPC_PMC_CAPS;
812         pcd->pcd_class = PMC_CLASS_PPC7450;
813         pcd->pcd_num   = PPC_MAX_PMCS;
814         pcd->pcd_ri    = pmc_mdep->pmd_npmc;
815         pcd->pcd_width = 32;    /* All PMCs, even in ppc970, are 32-bit */
816
817         pcd->pcd_allocate_pmc   = powerpc_allocate_pmc;
818         pcd->pcd_config_pmc     = powerpc_config_pmc;
819         pcd->pcd_pcpu_fini      = powerpc_pcpu_fini;
820         pcd->pcd_pcpu_init      = powerpc_pcpu_init;
821         pcd->pcd_describe       = powerpc_describe;
822         pcd->pcd_get_config     = powerpc_get_config;
823         pcd->pcd_read_pmc       = powerpc_read_pmc;
824         pcd->pcd_release_pmc    = powerpc_release_pmc;
825         pcd->pcd_start_pmc      = powerpc_start_pmc;
826         pcd->pcd_stop_pmc       = powerpc_stop_pmc;
827         pcd->pcd_write_pmc      = powerpc_write_pmc;
828
829         pmc_mdep->pmd_intr       = powerpc_intr;
830         pmc_mdep->pmd_switch_in  = powerpc_switch_in;
831         pmc_mdep->pmd_switch_out = powerpc_switch_out;
832         
833         pmc_mdep->pmd_npmc   += PPC_MAX_PMCS;
834
835         return (pmc_mdep);
836 }
837
838 void
839 pmc_md_finalize(struct pmc_mdep *md)
840 {
841         free(md, M_PMC);
842 }
843
844 int
845 pmc_save_user_callchain(uintptr_t *cc, int maxsamples,
846     struct trapframe *tf)
847 {
848         (void) cc;
849         (void) maxsamples;
850         (void) tf;
851         return (0);
852 }