xref: /freebsd/sys/dev/hwpmc/hwpmc_mpc7xxx.c (revision 93e779a26c651610ac6e7986d67ecc9ed2cadcbf)
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 #include "hwpmc_powerpc.h"
42 
43 #define	POWERPC_PMC_CAPS	(PMC_CAP_INTERRUPT | PMC_CAP_USER |     \
44 				 PMC_CAP_SYSTEM | PMC_CAP_EDGE |	\
45 				 PMC_CAP_THRESHOLD | PMC_CAP_READ |	\
46 				 PMC_CAP_WRITE | PMC_CAP_INVERT |	\
47 				 PMC_CAP_QUALIFIER)
48 
49 #define PPC_SET_PMC1SEL(r, x)	((r & ~(SPR_MMCR0_PMC1SEL(0x3f))) | SPR_MMCR0_PMC1SEL(x))
50 #define PPC_SET_PMC2SEL(r, x)	((r & ~(SPR_MMCR0_PMC2SEL(0x3f))) | SPR_MMCR0_PMC2SEL(x))
51 #define PPC_SET_PMC3SEL(r, x)	((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x))
52 #define PPC_SET_PMC4SEL(r, x)	((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x))
53 #define PPC_SET_PMC5SEL(r, x)	((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x))
54 #define PPC_SET_PMC6SEL(r, x)	((r & ~(SPR_MMCR1_PMC6SEL(0x3f))) | SPR_MMCR1_PMC6SEL(x))
55 
56 /* Change this when we support more than just the 7450. */
57 #define MPC7XXX_MAX_PMCS	6
58 
59 #define MPC7XXX_PMC_HAS_OVERFLOWED(x) (mpc7xxx_pmcn_read(x) & (0x1 << 31))
60 
61 /*
62  * Things to improve on this:
63  * - It stops (clears to 0) the PMC and resets it at every context switch
64  *   currently.
65  */
66 
67 /*
68  * This should work for every 32-bit PowerPC implementation I know of (G3 and G4
69  * specifically).
70  */
71 
72 struct mpc7xxx_event_code_map {
73 	enum pmc_event	pe_ev;       /* enum value */
74 	uint8_t         pe_counter_mask;  /* Which counter this can be counted in. */
75 	uint8_t		pe_code;     /* numeric code */
76 };
77 
78 #define PPC_PMC_MASK1	0
79 #define PPC_PMC_MASK2	1
80 #define PPC_PMC_MASK3	2
81 #define PPC_PMC_MASK4	3
82 #define PPC_PMC_MASK5	4
83 #define PPC_PMC_MASK6	5
84 #define PPC_PMC_MASK_ALL	0x3f
85 #define PMC_POWERPC_EVENT(id, mask, number) \
86 	{ .pe_ev = PMC_EV_PPC7450_##id, .pe_counter_mask = mask, .pe_code = number }
87 
88 static struct mpc7xxx_event_code_map mpc7xxx_event_codes[] = {
89 	PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1),
90 	PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2),
91 	PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3),
92 	PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4),
93 	PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5),
94 	PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7),
95 	PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8),
96 	PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9),
97 	PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10),
98 	PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11),
99 	PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12),
100 	PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13),
101 	PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14),
102 	PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15),
103 	PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16),
104 	PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17),
105 	PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18),
106 	PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19),
107 	PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20),
108 	PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21),
109 	PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22),
110 	PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23),
111 	PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24),
112 	PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25),
113 	PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26),
114 	PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27),
115 	PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28),
116 	PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29),
117 	PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30),
118 	PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31),
119 	PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32),
120 	PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33),
121 	PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34),
122 	PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35),
123 	PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36),
124 	PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37),
125 	PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38),
126 	PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39),
127 	PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40),
128 	PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41),
129 	PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42),
130 	PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43),
131 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44),
132 	PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45),
133 	PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46),
134 	PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47),
135 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48),
136 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49),
137 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50),
138 	PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51),
139 	PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52),
140 	PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53),
141 	PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54),
142 	PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55),
143 	PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56),
144 	PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57),
145 	PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58),
146 	PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59),
147 	PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60),
148 	PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61),
149 	PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62),
150 	PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63),
151 	PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64),
152 	PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65),
153 	PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66),
154 	PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67),
155 	PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68),
156 	PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70),
157 	PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71),
158 	PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72),
159 	PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73),
160 	PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74),
161 	PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75),
162 	PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76),
163 	PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77),
164 	PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78),
165 	PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79),
166 	PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80),
167 	PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81),
168 	PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82),
169 	PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83),
170 	PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84),
171 	PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85),
172 	PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86),
173 	PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87),
174 	PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88),
175 	PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89),
176 	PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90),
177 	PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91),
178 	PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92),
179 	PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93),
180 	PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94),
181 	PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23),
182 	PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24),
183 	PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25),
184 	PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26),
185 	PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27),
186 	PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28),
187 	PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29),
188 	PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30),
189 	PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31),
190 	PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32),
191 	PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33),
192 	PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34),
193 	PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35),
194 	PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36),
195 	PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37),
196 	PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38),
197 	PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39),
198 	PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40),
199 	PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41),
200 	PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42),
201 	PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43),
202 	PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44),
203 	PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45),
204 	PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46),
205 	PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47),
206 	PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48),
207 	PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49),
208 	PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50),
209 	PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51),
210 	PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52),
211 	PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53),
212 	PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54),
213 	PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55),
214 	PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56),
215 	PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57),
216 	PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58),
217 	PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59),
218 	PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60),
219 	PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61),
220 	PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62),
221 	PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8),
222 	PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9),
223 	PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10),
224 	PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11),
225 	PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12),
226 	PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13),
227 	PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14),
228 	PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15),
229 	PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16),
230 	PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17),
231 	PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18),
232 	PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19),
233 	PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20),
234 	PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21),
235 	PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22),
236 	PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23),
237 	PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24),
238 	PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25),
239 	PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26),
240 	PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27),
241 	PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28),
242 	PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29),
243 	PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30),
244 	PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31),
245 	PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14),
246 	PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15),
247 	PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16),
248 	PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17),
249 	PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18),
250 	PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19),
251 	PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20),
252 	PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21),
253 	PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22),
254 	PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23),
255 	PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24),
256 	PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25),
257 	PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26),
258 	PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27),
259 	PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28),
260 	PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29),
261 	PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30),
262 	PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2),
263 	PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3),
264 	PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4),
265 	PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5),
266 	PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6),
267 	PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7),
268 	PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8),
269 	PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9),
270 	PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10),
271 	PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11),
272 	PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13),
273 	PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14),
274 	PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15),
275 	PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16),
276 	PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17),
277 	PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18),
278 	PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19),
279 	PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20),
280 	PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8),
281 	PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9),
282 	PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10),
283 	PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11),
284 	PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16),
285 	PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17),
286 	PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19),
287 	PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20),
288 	PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21),
289 	PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22),
290 	PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23),
291 	PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24),
292 	PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25),
293 	PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26),
294 	PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27),
295 	PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28),
296 	PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42),
297 	PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43),
298 	PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44),
299 	PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45),
300 	PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46),
301 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47),
302 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48),
303 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49),
304 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50),
305 	PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51),
306 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52),
307 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53),
308 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54),
309 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55),
310 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56),
311 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57)
312 };
313 
314 const size_t mpc7xxx_event_codes_size =
315 	sizeof(mpc7xxx_event_codes) / sizeof(mpc7xxx_event_codes[0]);
316 
317 static pmc_value_t
318 mpc7xxx_pmcn_read(unsigned int pmc)
319 {
320 	switch (pmc) {
321 		case 0:
322 			return mfspr(SPR_PMC1);
323 			break;
324 		case 1:
325 			return mfspr(SPR_PMC2);
326 			break;
327 		case 2:
328 			return mfspr(SPR_PMC3);
329 			break;
330 		case 3:
331 			return mfspr(SPR_PMC4);
332 			break;
333 		case 4:
334 			return mfspr(SPR_PMC5);
335 			break;
336 		case 5:
337 			return mfspr(SPR_PMC6);
338 		default:
339 			panic("Invalid PMC number: %d\n", pmc);
340 	}
341 }
342 
343 static void
344 mpc7xxx_pmcn_write(unsigned int pmc, uint32_t val)
345 {
346 	switch (pmc) {
347 		case 0:
348 			mtspr(SPR_PMC1, val);
349 			break;
350 		case 1:
351 			mtspr(SPR_PMC2, val);
352 			break;
353 		case 2:
354 			mtspr(SPR_PMC3, val);
355 			break;
356 		case 3:
357 			mtspr(SPR_PMC4, val);
358 			break;
359 		case 4:
360 			mtspr(SPR_PMC5, val);
361 			break;
362 		case 5:
363 			mtspr(SPR_PMC6, val);
364 			break;
365 		default:
366 			panic("Invalid PMC number: %d\n", pmc);
367 	}
368 }
369 
370 static int
371 mpc7xxx_read_pmc(int cpu, int ri, pmc_value_t *v)
372 {
373 	struct pmc *pm;
374 	pmc_value_t tmp;
375 
376 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
377 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
378 	KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS,
379 	    ("[powerpc,%d] illegal row index %d", __LINE__, ri));
380 
381 	pm  = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
382 	KASSERT(pm,
383 	    ("[core,%d] cpu %d ri %d pmc not configured", __LINE__, cpu,
384 		ri));
385 
386 	tmp = mpc7xxx_pmcn_read(ri);
387 	PMCDBG2(MDP,REA,2,"ppc-read id=%d -> %jd", ri, tmp);
388 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
389 		*v = POWERPC_PERFCTR_VALUE_TO_RELOAD_COUNT(tmp);
390 	else
391 		*v = tmp;
392 
393 	return 0;
394 }
395 
396 static int
397 mpc7xxx_write_pmc(int cpu, int ri, pmc_value_t v)
398 {
399 	struct pmc *pm;
400 
401 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
402 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
403 	KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS,
404 	    ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
405 
406 	pm  = powerpc_pcpu[cpu]->pc_ppcpmcs[ri].phw_pmc;
407 
408 	if (PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm)))
409 		v = POWERPC_RELOAD_COUNT_TO_PERFCTR_VALUE(v);
410 
411 	PMCDBG3(MDP,WRI,1,"powerpc-write cpu=%d ri=%d v=%jx", cpu, ri, v);
412 
413 	mpc7xxx_pmcn_write(ri, v);
414 
415 	return 0;
416 }
417 
418 static int
419 mpc7xxx_config_pmc(int cpu, int ri, struct pmc *pm)
420 {
421 	struct pmc_hw *phw;
422 
423 	PMCDBG3(MDP,CFG,1, "cpu=%d ri=%d pm=%p", cpu, ri, pm);
424 
425 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
426 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
427 	KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS,
428 	    ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
429 
430 	phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
431 
432 	KASSERT(pm == NULL || phw->phw_pmc == NULL,
433 	    ("[powerpc,%d] pm=%p phw->pm=%p hwpmc not unconfigured",
434 	    __LINE__, pm, phw->phw_pmc));
435 
436 	phw->phw_pmc = pm;
437 
438 	return 0;
439 }
440 
441 static int
442 mpc7xxx_start_pmc(int cpu, int ri)
443 {
444 	uint32_t config;
445         struct pmc *pm;
446         struct pmc_hw *phw;
447 	register_t pmc_mmcr;
448 
449 	phw    = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
450 	pm     = phw->phw_pmc;
451 	config = pm->pm_md.pm_powerpc.pm_powerpc_evsel & ~POWERPC_PMC_ENABLE;
452 
453 	/* Enable the PMC. */
454 	switch (ri) {
455 	case 0:
456 		pmc_mmcr = mfspr(SPR_MMCR0);
457 		pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config);
458 		mtspr(SPR_MMCR0, pmc_mmcr);
459 		break;
460 	case 1:
461 		pmc_mmcr = mfspr(SPR_MMCR0);
462 		pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config);
463 		mtspr(SPR_MMCR0, pmc_mmcr);
464 		break;
465 	case 2:
466 		pmc_mmcr = mfspr(SPR_MMCR1);
467 		pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config);
468 		mtspr(SPR_MMCR1, pmc_mmcr);
469 		break;
470 	case 3:
471 		pmc_mmcr = mfspr(SPR_MMCR0);
472 		pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config);
473 		mtspr(SPR_MMCR0, pmc_mmcr);
474 		break;
475 	case 4:
476 		pmc_mmcr = mfspr(SPR_MMCR1);
477 		pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config);
478 		mtspr(SPR_MMCR1, pmc_mmcr);
479 		break;
480 	case 5:
481 		pmc_mmcr = mfspr(SPR_MMCR1);
482 		pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config);
483 		mtspr(SPR_MMCR1, pmc_mmcr);
484 		break;
485 	default:
486 		break;
487 	}
488 
489 	/* The mask is inverted (enable is 1) compared to the flags in MMCR0, which
490 	 * are Freeze flags.
491 	 */
492 	config = ~pm->pm_md.pm_powerpc.pm_powerpc_evsel & POWERPC_PMC_ENABLE;
493 
494 	pmc_mmcr = mfspr(SPR_MMCR0);
495 	pmc_mmcr &= ~SPR_MMCR0_FC;
496 	pmc_mmcr |= config;
497 	mtspr(SPR_MMCR0, pmc_mmcr);
498 
499 	return 0;
500 }
501 
502 static int
503 mpc7xxx_stop_pmc(int cpu, int ri)
504 {
505         struct pmc *pm;
506         struct pmc_hw *phw;
507         register_t pmc_mmcr;
508 
509 	phw    = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
510 	pm     = phw->phw_pmc;
511 
512 	/*
513 	 * Disable the PMCs.
514 	 */
515 	switch (ri) {
516 	case 0:
517 		pmc_mmcr = mfspr(SPR_MMCR0);
518 		pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, 0);
519 		mtspr(SPR_MMCR0, pmc_mmcr);
520 		break;
521 	case 1:
522 		pmc_mmcr = mfspr(SPR_MMCR0);
523 		pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, 0);
524 		mtspr(SPR_MMCR0, pmc_mmcr);
525 		break;
526 	case 2:
527 		pmc_mmcr = mfspr(SPR_MMCR1);
528 		pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, 0);
529 		mtspr(SPR_MMCR1, pmc_mmcr);
530 		break;
531 	case 3:
532 		pmc_mmcr = mfspr(SPR_MMCR0);
533 		pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, 0);
534 		mtspr(SPR_MMCR0, pmc_mmcr);
535 		break;
536 	case 4:
537 		pmc_mmcr = mfspr(SPR_MMCR1);
538 		pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, 0);
539 		mtspr(SPR_MMCR1, pmc_mmcr);
540 		break;
541 	case 5:
542 		pmc_mmcr = mfspr(SPR_MMCR1);
543 		pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, 0);
544 		mtspr(SPR_MMCR1, pmc_mmcr);
545 		break;
546 	default:
547 		break;
548 	}
549 	return 0;
550 }
551 
552 static int
553 mpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu)
554 {
555 	int first_ri, i;
556 	struct pmc_cpu *pc;
557 	struct powerpc_cpu *pac;
558 	struct pmc_hw  *phw;
559 
560 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
561 	    ("[powerpc,%d] wrong cpu number %d", __LINE__, cpu));
562 	PMCDBG1(MDP,INI,1,"powerpc-init cpu=%d", cpu);
563 
564 	powerpc_pcpu[cpu] = pac = malloc(sizeof(struct powerpc_cpu), M_PMC,
565 	    M_WAITOK|M_ZERO);
566 	pac->pc_ppcpmcs = malloc(sizeof(struct pmc_hw) * MPC7XXX_MAX_PMCS,
567 	    M_PMC, M_WAITOK|M_ZERO);
568 	pac->pc_class = PMC_CLASS_PPC7450;
569 	pc = pmc_pcpu[cpu];
570 	first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC].pcd_ri;
571 	KASSERT(pc != NULL, ("[powerpc,%d] NULL per-cpu pointer", __LINE__));
572 
573 	for (i = 0, phw = pac->pc_ppcpmcs; i < MPC7XXX_MAX_PMCS; i++, phw++) {
574 		phw->phw_state    = PMC_PHW_FLAG_IS_ENABLED |
575 		    PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(i);
576 		phw->phw_pmc      = NULL;
577 		pc->pc_hwpmcs[i + first_ri] = phw;
578 	}
579 
580 	/* Clear the MMCRs, and set FC, to disable all PMCs. */
581 	mtspr(SPR_MMCR0, SPR_MMCR0_FC | SPR_MMCR0_PMXE |
582 	    SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE);
583 	mtspr(SPR_MMCR1, 0);
584 
585 	return 0;
586 }
587 
588 static int
589 mpc7xxx_pcpu_fini(struct pmc_mdep *md, int cpu)
590 {
591 	uint32_t mmcr0 = mfspr(SPR_MMCR0);
592 
593 	mtmsr(mfmsr() & ~PSL_PMM);
594 	mmcr0 |= SPR_MMCR0_FC;
595 	mtspr(SPR_MMCR0, mmcr0);
596 
597 	free(powerpc_pcpu[cpu]->pc_ppcpmcs, M_PMC);
598 	free(powerpc_pcpu[cpu], M_PMC);
599 
600 	return 0;
601 }
602 
603 static int
604 mpc7xxx_allocate_pmc(int cpu, int ri, struct pmc *pm,
605   const struct pmc_op_pmcallocate *a)
606 {
607 	enum pmc_event pe;
608 	uint32_t caps, config, counter;
609 	int i;
610 
611 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
612 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
613 	KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS,
614 	    ("[powerpc,%d] illegal row index %d", __LINE__, ri));
615 
616 	caps = a->pm_caps;
617 
618 	pe = a->pm_ev;
619 	for (i = 0; i < mpc7xxx_event_codes_size; i++) {
620 		if (mpc7xxx_event_codes[i].pe_ev == pe) {
621 			config = mpc7xxx_event_codes[i].pe_code;
622 			counter =  mpc7xxx_event_codes[i].pe_counter_mask;
623 			break;
624 		}
625 	}
626 	if (i == mpc7xxx_event_codes_size)
627 		return (EINVAL);
628 
629 	if ((counter & (1 << ri)) == 0)
630 		return (EINVAL);
631 
632 	if (caps & PMC_CAP_SYSTEM)
633 		config |= POWERPC_PMC_KERNEL_ENABLE;
634 	if (caps & PMC_CAP_USER)
635 		config |= POWERPC_PMC_USER_ENABLE;
636 	if ((caps & (PMC_CAP_USER | PMC_CAP_SYSTEM)) == 0)
637 		config |= POWERPC_PMC_ENABLE;
638 
639 	pm->pm_md.pm_powerpc.pm_powerpc_evsel = config;
640 
641 	PMCDBG2(MDP,ALL,2,"powerpc-allocate ri=%d -> config=0x%x", ri, config);
642 
643 	return 0;
644 }
645 
646 static int
647 mpc7xxx_release_pmc(int cpu, int ri, struct pmc *pmc)
648 {
649 	struct pmc_hw *phw;
650 
651 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
652 	    ("[powerpc,%d] illegal CPU value %d", __LINE__, cpu));
653 	KASSERT(ri >= 0 && ri < MPC7XXX_MAX_PMCS,
654 	    ("[powerpc,%d] illegal row-index %d", __LINE__, ri));
655 
656 	phw = &powerpc_pcpu[cpu]->pc_ppcpmcs[ri];
657 	KASSERT(phw->phw_pmc == NULL,
658 	    ("[powerpc,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc));
659 
660 	return 0;
661 }
662 
663 static int
664 mpc7xxx_intr(int cpu, struct trapframe *tf)
665 {
666 	int i, error, retval;
667 	uint32_t config;
668 	struct pmc *pm;
669 	struct powerpc_cpu *pac;
670 
671 	KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
672 	    ("[powerpc,%d] out of range CPU %d", __LINE__, cpu));
673 
674 	PMCDBG3(MDP,INT,1, "cpu=%d tf=%p um=%d", cpu, (void *) tf,
675 	    TRAPF_USERMODE(tf));
676 
677 	retval = 0;
678 
679 	pac = powerpc_pcpu[cpu];
680 
681 	config  = mfspr(SPR_MMCR0) & ~SPR_MMCR0_FC;
682 
683 	/*
684 	 * look for all PMCs that have interrupted:
685 	 * - look for a running, sampling PMC which has overflowed
686 	 *   and which has a valid 'struct pmc' association
687 	 *
688 	 * If found, we call a helper to process the interrupt.
689 	 */
690 
691 	for (i = 0; i < MPC7XXX_MAX_PMCS; i++) {
692 		if ((pm = pac->pc_ppcpmcs[i].phw_pmc) == NULL ||
693 		    !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) {
694 			continue;
695 		}
696 
697 		if (!MPC7XXX_PMC_HAS_OVERFLOWED(i))
698 			continue;
699 
700 		retval = 1;	/* Found an interrupting PMC. */
701 
702 		if (pm->pm_state != PMC_STATE_RUNNING)
703 			continue;
704 
705 		/* Stop the counter if logging fails. */
706 		error = pmc_process_interrupt(cpu, PMC_HR, pm, tf,
707 		    TRAPF_USERMODE(tf));
708 		if (error != 0)
709 			mpc7xxx_stop_pmc(cpu, i);
710 
711 		/* reload count. */
712 		mpc7xxx_write_pmc(cpu, i, pm->pm_sc.pm_reloadcount);
713 	}
714 
715 	atomic_add_int(retval ? &pmc_stats.pm_intr_processed :
716 	    &pmc_stats.pm_intr_ignored, 1);
717 
718 	/* Re-enable PERF exceptions. */
719 	if (retval)
720 		mtspr(SPR_MMCR0, config | SPR_MMCR0_PMXE);
721 
722 	return (retval);
723 }
724 
725 int
726 pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep)
727 {
728 	struct pmc_classdep *pcd;
729 
730 	pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450;
731 
732 	pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC];
733 	pcd->pcd_caps  = POWERPC_PMC_CAPS;
734 	pcd->pcd_class = PMC_CLASS_PPC7450;
735 	pcd->pcd_num   = MPC7XXX_MAX_PMCS;
736 	pcd->pcd_ri    = pmc_mdep->pmd_npmc;
737 	pcd->pcd_width = 32;	/* All PMCs, even in ppc970, are 32-bit */
738 
739 	pcd->pcd_allocate_pmc   = mpc7xxx_allocate_pmc;
740 	pcd->pcd_config_pmc     = mpc7xxx_config_pmc;
741 	pcd->pcd_pcpu_fini      = mpc7xxx_pcpu_fini;
742 	pcd->pcd_pcpu_init      = mpc7xxx_pcpu_init;
743 	pcd->pcd_describe       = powerpc_describe;
744 	pcd->pcd_get_config     = powerpc_get_config;
745 	pcd->pcd_read_pmc       = mpc7xxx_read_pmc;
746 	pcd->pcd_release_pmc    = mpc7xxx_release_pmc;
747 	pcd->pcd_start_pmc      = mpc7xxx_start_pmc;
748 	pcd->pcd_stop_pmc       = mpc7xxx_stop_pmc;
749  	pcd->pcd_write_pmc      = mpc7xxx_write_pmc;
750 
751 	pmc_mdep->pmd_npmc   += MPC7XXX_MAX_PMCS;
752 	pmc_mdep->pmd_intr   =  mpc7xxx_intr;
753 
754 	return (0);
755 }
756