xref: /freebsd/sys/dev/hwpmc/hwpmc_mpc7xxx.c (revision d0b2dbfa0ecf2bbc9709efc5e20baf8e4b44bbbf)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2011 Justin Hibbits
5  * Copyright (c) 2005, Joseph Koshy
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 #include <sys/cdefs.h>
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 PPC_SET_PMC1SEL(r, x)	((r & ~(SPR_MMCR0_74XX_PMC1SEL(0x3f))) | \
44 				SPR_MMCR0_74XX_PMC1SEL(x))
45 #define PPC_SET_PMC2SEL(r, x)	((r & ~(SPR_MMCR0_74XX_PMC2SEL(0x3f))) | \
46 				SPR_MMCR0_74XX_PMC2SEL(x))
47 #define PPC_SET_PMC3SEL(r, x)	((r & ~(SPR_MMCR1_PMC3SEL(0x1f))) | SPR_MMCR1_PMC3SEL(x))
48 #define PPC_SET_PMC4SEL(r, x)	((r & ~(SPR_MMCR1_PMC4SEL(0x1f))) | SPR_MMCR1_PMC4SEL(x))
49 #define PPC_SET_PMC5SEL(r, x)	((r & ~(SPR_MMCR1_PMC5SEL(0x1f))) | SPR_MMCR1_PMC5SEL(x))
50 #define PPC_SET_PMC6SEL(r, x)	((r & ~(SPR_MMCR1_74XX_PMC6SEL(0x3f))) | \
51 				SPR_MMCR1_74XX_PMC6SEL(x))
52 
53 /* Change this when we support more than just the 7450. */
54 #define MPC7XXX_MAX_PMCS	6
55 
56 /*
57  * Things to improve on this:
58  * - It stops (clears to 0) the PMC and resets it at every context switch
59  *   currently.
60  */
61 
62 /*
63  * This should work for every 32-bit PowerPC implementation I know of (G3 and G4
64  * specifically).
65  */
66 
67 #define PPC_PMC_MASK_ALL	0x3f
68 #define PMC_POWERPC_EVENT(id, mask, number) \
69 	{ .pe_event = PMC_EV_PPC7450_##id, .pe_flags = mask, .pe_code = number }
70 
71 static struct pmc_ppc_event mpc7xxx_event_codes[] = {
72 	PMC_POWERPC_EVENT(CYCLE,PPC_PMC_MASK_ALL, 1),
73 	PMC_POWERPC_EVENT(INSTR_COMPLETED, 0x0f, 2),
74 	PMC_POWERPC_EVENT(TLB_BIT_TRANSITIONS, 0x0f, 3),
75 	PMC_POWERPC_EVENT(INSTR_DISPATCHED, 0x0f, 4),
76 	PMC_POWERPC_EVENT(PMON_EXCEPT, 0x0f, 5),
77 	PMC_POWERPC_EVENT(PMON_SIG, 0x0f, 7),
78 	PMC_POWERPC_EVENT(VPU_INSTR_COMPLETED, 0x03, 8),
79 	PMC_POWERPC_EVENT(VFPU_INSTR_COMPLETED, 0x03, 9),
80 	PMC_POWERPC_EVENT(VIU1_INSTR_COMPLETED, 0x03, 10),
81 	PMC_POWERPC_EVENT(VIU2_INSTR_COMPLETED, 0x03, 11),
82 	PMC_POWERPC_EVENT(MTVSCR_INSTR_COMPLETED, 0x03, 12),
83 	PMC_POWERPC_EVENT(MTVRSAVE_INSTR_COMPLETED, 0x03, 13),
84 	PMC_POWERPC_EVENT(VPU_INSTR_WAIT_CYCLES, 0x03, 14),
85 	PMC_POWERPC_EVENT(VFPU_INSTR_WAIT_CYCLES, 0x03, 15),
86 	PMC_POWERPC_EVENT(VIU1_INSTR_WAIT_CYCLES, 0x03, 16),
87 	PMC_POWERPC_EVENT(VIU2_INSTR_WAIT_CYCLES, 0x03, 17),
88 	PMC_POWERPC_EVENT(MFVSCR_SYNC_CYCLES, 0x03, 18),
89 	PMC_POWERPC_EVENT(VSCR_SAT_SET, 0x03, 19),
90 	PMC_POWERPC_EVENT(STORE_INSTR_COMPLETED, 0x03, 20),
91 	PMC_POWERPC_EVENT(L1_INSTR_CACHE_MISSES, 0x03, 21),
92 	PMC_POWERPC_EVENT(L1_DATA_SNOOPS, 0x03, 22),
93 	PMC_POWERPC_EVENT(UNRESOLVED_BRANCHES, 0x01, 23),
94 	PMC_POWERPC_EVENT(SPEC_BUFFER_CYCLES, 0x01, 24),
95 	PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_CYCLES, 0x01, 25),
96 	PMC_POWERPC_EVENT(TRUE_BRANCH_TARGET_HITS, 0x01, 26),
97 	PMC_POWERPC_EVENT(BRANCH_LINK_STAC_PREDICTED, 0x01, 27),
98 	PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_DISPATCHES, 0x01, 28),
99 	PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_DISPATCHED, 0x01, 29),
100 	PMC_POWERPC_EVENT(THRESHOLD_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 30),
101 	PMC_POWERPC_EVENT(THRESHOLD_VEC_INSTR_QUEUE_ENTRIES_CYCLES, 0x01, 31),
102 	PMC_POWERPC_EVENT(CYCLES_NO_COMPLETED_INSTRS, 0x01, 32),
103 	PMC_POWERPC_EVENT(IU2_INSTR_COMPLETED, 0x01, 33),
104 	PMC_POWERPC_EVENT(BRANCHES_COMPLETED, 0x01, 34),
105 	PMC_POWERPC_EVENT(EIEIO_INSTR_COMPLETED, 0x01, 35),
106 	PMC_POWERPC_EVENT(MTSPR_INSTR_COMPLETED, 0x01, 36),
107 	PMC_POWERPC_EVENT(SC_INSTR_COMPLETED, 0x01, 37),
108 	PMC_POWERPC_EVENT(LS_LM_COMPLETED, 0x01, 38),
109 	PMC_POWERPC_EVENT(ITLB_HW_TABLE_SEARCH_CYCLES, 0x01, 39),
110 	PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x01, 40),
111 	PMC_POWERPC_EVENT(L1_INSTR_CACHE_ACCESSES, 0x01, 41),
112 	PMC_POWERPC_EVENT(INSTR_BKPT_MATCHES, 0x01, 42),
113 	PMC_POWERPC_EVENT(L1_DATA_CACHE_LOAD_MISS_CYCLES_OVER_THRESHOLD, 0x01, 43),
114 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_ON_MODIFIED, 0x01, 44),
115 	PMC_POWERPC_EVENT(LOAD_MISS_ALIAS, 0x01, 45),
116 	PMC_POWERPC_EVENT(LOAD_MISS_ALIAS_ON_TOUCH, 0x01, 46),
117 	PMC_POWERPC_EVENT(TOUCH_ALIAS, 0x01, 47),
118 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT_QUEUE, 0x01, 48),
119 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HIT_CASTOUT, 0x01, 49),
120 	PMC_POWERPC_EVENT(L1_DATA_SNOOP_HITS, 0x01, 50),
121 	PMC_POWERPC_EVENT(WRITE_THROUGH_STORES, 0x01, 51),
122 	PMC_POWERPC_EVENT(CACHE_INHIBITED_STORES, 0x01, 52),
123 	PMC_POWERPC_EVENT(L1_DATA_LOAD_HIT, 0x01, 53),
124 	PMC_POWERPC_EVENT(L1_DATA_TOUCH_HIT, 0x01, 54),
125 	PMC_POWERPC_EVENT(L1_DATA_STORE_HIT, 0x01, 55),
126 	PMC_POWERPC_EVENT(L1_DATA_TOTAL_HITS, 0x01, 56),
127 	PMC_POWERPC_EVENT(DST_INSTR_DISPATCHED, 0x01, 57),
128 	PMC_POWERPC_EVENT(REFRESHED_DSTS, 0x01, 58),
129 	PMC_POWERPC_EVENT(SUCCESSFUL_DST_TABLE_SEARCHES, 0x01, 59),
130 	PMC_POWERPC_EVENT(DSS_INSTR_COMPLETED, 0x01, 60),
131 	PMC_POWERPC_EVENT(DST_STREAM_0_CACHE_LINE_FETCHES, 0x01, 61),
132 	PMC_POWERPC_EVENT(VTQ_SUSPENDS_DUE_TO_CTX_CHANGE, 0x01, 62),
133 	PMC_POWERPC_EVENT(VTQ_LINE_FETCH_HIT, 0x01, 63),
134 	PMC_POWERPC_EVENT(VEC_LOAD_INSTR_COMPLETED, 0x01, 64),
135 	PMC_POWERPC_EVENT(FP_STORE_INSTR_COMPLETED_IN_LSU, 0x01, 65),
136 	PMC_POWERPC_EVENT(FPU_RENORMALIZATION, 0x01, 66),
137 	PMC_POWERPC_EVENT(FPU_DENORMALIZATION, 0x01, 67),
138 	PMC_POWERPC_EVENT(FP_STORE_CAUSES_STALL_IN_LSU, 0x01, 68),
139 	PMC_POWERPC_EVENT(LD_ST_TRUE_ALIAS_STALL, 0x01, 70),
140 	PMC_POWERPC_EVENT(LSU_INDEXED_ALIAS_STALL, 0x01, 71),
141 	PMC_POWERPC_EVENT(LSU_ALIAS_VS_FSQ_WB0_WB1, 0x01, 72),
142 	PMC_POWERPC_EVENT(LSU_ALIAS_VS_CSQ, 0x01, 73),
143 	PMC_POWERPC_EVENT(LSU_LOAD_HIT_LINE_ALIAS_VS_CSQ0, 0x01, 74),
144 	PMC_POWERPC_EVENT(LSU_LOAD_MISS_LINE_ALIAS_VS_CSQ0, 0x01, 75),
145 	PMC_POWERPC_EVENT(LSU_TOUCH_LINE_ALIAS_VS_FSQ_WB0_WB1, 0x01, 76),
146 	PMC_POWERPC_EVENT(LSU_TOUCH_ALIAS_VS_CSQ, 0x01, 77),
147 	PMC_POWERPC_EVENT(LSU_LMQ_FULL_STALL, 0x01, 78),
148 	PMC_POWERPC_EVENT(FP_LOAD_INSTR_COMPLETED_IN_LSU, 0x01, 79),
149 	PMC_POWERPC_EVENT(FP_LOAD_SINGLE_INSTR_COMPLETED_IN_LSU, 0x01, 80),
150 	PMC_POWERPC_EVENT(FP_LOAD_DOUBLE_COMPLETED_IN_LSU, 0x01, 81),
151 	PMC_POWERPC_EVENT(LSU_RA_LATCH_STALL, 0x01, 82),
152 	PMC_POWERPC_EVENT(LSU_LOAD_VS_STORE_QUEUE_ALIAS_STALL, 0x01, 83),
153 	PMC_POWERPC_EVENT(LSU_LMQ_INDEX_ALIAS, 0x01, 84),
154 	PMC_POWERPC_EVENT(LSU_STORE_QUEUE_INDEX_ALIAS, 0x01, 85),
155 	PMC_POWERPC_EVENT(LSU_CSQ_FORWARDING, 0x01, 86),
156 	PMC_POWERPC_EVENT(LSU_MISALIGNED_LOAD_FINISH, 0x01, 87),
157 	PMC_POWERPC_EVENT(LSU_MISALIGN_STORE_COMPLETED, 0x01, 88),
158 	PMC_POWERPC_EVENT(LSU_MISALIGN_STALL, 0x01, 89),
159 	PMC_POWERPC_EVENT(FP_ONE_QUARTER_FPSCR_RENAMES_BUSY, 0x01, 90),
160 	PMC_POWERPC_EVENT(FP_ONE_HALF_FPSCR_RENAMES_BUSY, 0x01, 91),
161 	PMC_POWERPC_EVENT(FP_THREE_QUARTERS_FPSCR_RENAMES_BUSY, 0x01, 92),
162 	PMC_POWERPC_EVENT(FP_ALL_FPSCR_RENAMES_BUSY, 0x01, 93),
163 	PMC_POWERPC_EVENT(FP_DENORMALIZED_RESULT, 0x01, 94),
164 	PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISSES, 0x02, 23),
165 	PMC_POWERPC_EVENT(DISPATCHES_TO_FPR_ISSUE_QUEUE, 0x02, 24),
166 	PMC_POWERPC_EVENT(LSU_INSTR_COMPLETED, 0x02, 25),
167 	PMC_POWERPC_EVENT(LOAD_INSTR_COMPLETED, 0x02, 26),
168 	PMC_POWERPC_EVENT(SS_SM_INSTR_COMPLETED, 0x02, 27),
169 	PMC_POWERPC_EVENT(TLBIE_INSTR_COMPLETED, 0x02, 28),
170 	PMC_POWERPC_EVENT(LWARX_INSTR_COMPLETED, 0x02, 29),
171 	PMC_POWERPC_EVENT(MFSPR_INSTR_COMPLETED, 0x02, 30),
172 	PMC_POWERPC_EVENT(REFETCH_SERIALIZATION, 0x02, 31),
173 	PMC_POWERPC_EVENT(COMPLETION_QUEUE_ENTRIES_OVER_THRESHOLD, 0x02, 32),
174 	PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x02, 33),
175 	PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x02, 34),
176 	PMC_POWERPC_EVENT(ITLB_NON_SPECULATIVE_MISSES, 0x02, 35),
177 	PMC_POWERPC_EVENT(CYCLES_WAITING_FROM_L1_INSTR_CACHE_MISS, 0x02, 36),
178 	PMC_POWERPC_EVENT(L1_DATA_LOAD_ACCESS_MISS, 0x02, 37),
179 	PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS, 0x02, 38),
180 	PMC_POWERPC_EVENT(L1_DATA_STORE_MISS, 0x02, 39),
181 	PMC_POWERPC_EVENT(L1_DATA_TOUCH_MISS_CYCLES, 0x02, 40),
182 	PMC_POWERPC_EVENT(L1_DATA_CYCLES_USED, 0x02, 41),
183 	PMC_POWERPC_EVENT(DST_STREAM_1_CACHE_LINE_FETCHES, 0x02, 42),
184 	PMC_POWERPC_EVENT(VTQ_STREAM_CANCELED_PREMATURELY, 0x02, 43),
185 	PMC_POWERPC_EVENT(VTQ_RESUMES_DUE_TO_CTX_CHANGE, 0x02, 44),
186 	PMC_POWERPC_EVENT(VTQ_LINE_FETCH_MISS, 0x02, 45),
187 	PMC_POWERPC_EVENT(VTQ_LINE_FETCH, 0x02, 46),
188 	PMC_POWERPC_EVENT(TLBIE_SNOOPS, 0x02, 47),
189 	PMC_POWERPC_EVENT(L1_INSTR_CACHE_RELOADS, 0x02, 48),
190 	PMC_POWERPC_EVENT(L1_DATA_CACHE_RELOADS, 0x02, 49),
191 	PMC_POWERPC_EVENT(L1_DATA_CACHE_CASTOUTS_TO_L2, 0x02, 50),
192 	PMC_POWERPC_EVENT(STORE_MERGE_GATHER, 0x02, 51),
193 	PMC_POWERPC_EVENT(CACHEABLE_STORE_MERGE_TO_32_BYTES, 0x02, 52),
194 	PMC_POWERPC_EVENT(DATA_BKPT_MATCHES, 0x02, 53),
195 	PMC_POWERPC_EVENT(FALL_THROUGH_BRANCHES_PROCESSED, 0x02, 54),
196 	PMC_POWERPC_EVENT(FIRST_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x02, 55),
197 	PMC_POWERPC_EVENT(SECOND_SPECULATION_BUFFER_ACTIVE, 0x02, 56),
198 	PMC_POWERPC_EVENT(BPU_STALL_ON_LR_DEPENDENCY, 0x02, 57),
199 	PMC_POWERPC_EVENT(BTIC_MISS, 0x02, 58),
200 	PMC_POWERPC_EVENT(BRANCH_LINK_STACK_CORRECTLY_RESOLVED, 0x02, 59),
201 	PMC_POWERPC_EVENT(FPR_ISSUE_STALLED, 0x02, 60),
202 	PMC_POWERPC_EVENT(SWITCHES_BETWEEN_PRIV_USER, 0x02, 61),
203 	PMC_POWERPC_EVENT(LSU_COMPLETES_FP_STORE_SINGLE, 0x02, 62),
204 	PMC_POWERPC_EVENT(CYCLES_TWO_INSTR_COMPLETED, 0x04, 8),
205 	PMC_POWERPC_EVENT(CYCLES_ONE_INSTR_DISPATCHED, 0x04, 9),
206 	PMC_POWERPC_EVENT(VR_ISSUE_QUEUE_DISPATCHES, 0x04, 10),
207 	PMC_POWERPC_EVENT(VR_STALLS, 0x04, 11),
208 	PMC_POWERPC_EVENT(GPR_RENAME_BUFFER_ENTRIES_OVER_THRESHOLD, 0x04, 12),
209 	PMC_POWERPC_EVENT(FPR_ISSUE_QUEUE_ENTRIES, 0x04, 13),
210 	PMC_POWERPC_EVENT(FPU_INSTR_COMPLETED, 0x04, 14),
211 	PMC_POWERPC_EVENT(STWCX_INSTR_COMPLETED, 0x04, 15),
212 	PMC_POWERPC_EVENT(LS_LM_INSTR_PIECES, 0x04, 16),
213 	PMC_POWERPC_EVENT(ITLB_HW_SEARCH_CYCLES_OVER_THRESHOLD, 0x04, 17),
214 	PMC_POWERPC_EVENT(DTLB_MISSES, 0x04, 18),
215 	PMC_POWERPC_EVENT(CANCELLED_L1_INSTR_CACHE_MISSES, 0x04, 19),
216 	PMC_POWERPC_EVENT(L1_DATA_CACHE_OP_HIT, 0x04, 20),
217 	PMC_POWERPC_EVENT(L1_DATA_LOAD_MISS_CYCLES, 0x04, 21),
218 	PMC_POWERPC_EVENT(L1_DATA_PUSHES, 0x04, 22),
219 	PMC_POWERPC_EVENT(L1_DATA_TOTAL_MISS, 0x04, 23),
220 	PMC_POWERPC_EVENT(VT2_FETCHES, 0x04, 24),
221 	PMC_POWERPC_EVENT(TAKEN_BRANCHES_PROCESSED, 0x04, 25),
222 	PMC_POWERPC_EVENT(BRANCH_FLUSHES, 0x04, 26),
223 	PMC_POWERPC_EVENT(SECOND_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x04, 27),
224 	PMC_POWERPC_EVENT(THIRD_SPECULATION_BUFFER_ACTIVE, 0x04, 28),
225 	PMC_POWERPC_EVENT(BRANCH_UNIT_STALL_ON_CTR_DEPENDENCY, 0x04, 29),
226 	PMC_POWERPC_EVENT(FAST_BTIC_HIT, 0x04, 30),
227 	PMC_POWERPC_EVENT(BRANCH_LINK_STACK_MISPREDICTED, 0x04, 31),
228 	PMC_POWERPC_EVENT(CYCLES_THREE_INSTR_COMPLETED, 0x08, 14),
229 	PMC_POWERPC_EVENT(CYCLES_NO_INSTR_DISPATCHED, 0x08, 15),
230 	PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_ENTRIES_OVER_THRESHOLD, 0x08, 16),
231 	PMC_POWERPC_EVENT(GPR_ISSUE_QUEUE_STALLED, 0x08, 17),
232 	PMC_POWERPC_EVENT(IU1_INSTR_COMPLETED, 0x08, 18),
233 	PMC_POWERPC_EVENT(DSSALL_INSTR_COMPLETED, 0x08, 19),
234 	PMC_POWERPC_EVENT(TLBSYNC_INSTR_COMPLETED, 0x08, 20),
235 	PMC_POWERPC_EVENT(SYNC_INSTR_COMPLETED, 0x08, 21),
236 	PMC_POWERPC_EVENT(SS_SM_INSTR_PIECES, 0x08, 22),
237 	PMC_POWERPC_EVENT(DTLB_HW_SEARCH_CYCLES, 0x08, 23),
238 	PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x08, 24),
239 	PMC_POWERPC_EVENT(SUCCESSFUL_STWCX, 0x08, 25),
240 	PMC_POWERPC_EVENT(DST_STREAM_3_CACHE_LINE_FETCHES, 0x08, 26),
241 	PMC_POWERPC_EVENT(THIRD_SPECULATIVE_BRANCH_BUFFER_RESOLVED_CORRECTLY, 0x08, 27),
242 	PMC_POWERPC_EVENT(MISPREDICTED_BRANCHES, 0x08, 28),
243 	PMC_POWERPC_EVENT(FOLDED_BRANCHES, 0x08, 29),
244 	PMC_POWERPC_EVENT(FP_STORE_DOUBLE_COMPLETES_IN_LSU, 0x08, 30),
245 	PMC_POWERPC_EVENT(L2_CACHE_HITS, 0x30, 2),
246 	PMC_POWERPC_EVENT(L3_CACHE_HITS, 0x30, 3),
247 	PMC_POWERPC_EVENT(L2_INSTR_CACHE_MISSES, 0x30, 4),
248 	PMC_POWERPC_EVENT(L3_INSTR_CACHE_MISSES, 0x30, 5),
249 	PMC_POWERPC_EVENT(L2_DATA_CACHE_MISSES, 0x30, 6),
250 	PMC_POWERPC_EVENT(L3_DATA_CACHE_MISSES, 0x30, 7),
251 	PMC_POWERPC_EVENT(L2_LOAD_HITS, 0x10, 8),
252 	PMC_POWERPC_EVENT(L2_STORE_HITS, 0x10, 9),
253 	PMC_POWERPC_EVENT(L3_LOAD_HITS, 0x10, 10),
254 	PMC_POWERPC_EVENT(L3_STORE_HITS, 0x10, 11),
255 	PMC_POWERPC_EVENT(L2_TOUCH_HITS, 0x30, 13),
256 	PMC_POWERPC_EVENT(L3_TOUCH_HITS, 0x30, 14),
257 	PMC_POWERPC_EVENT(SNOOP_RETRIES, 0x30, 15),
258 	PMC_POWERPC_EVENT(SNOOP_MODIFIED, 0x10, 16),
259 	PMC_POWERPC_EVENT(SNOOP_VALID, 0x10, 17),
260 	PMC_POWERPC_EVENT(INTERVENTION, 0x30, 18),
261 	PMC_POWERPC_EVENT(L2_CACHE_MISSES, 0x10, 19),
262 	PMC_POWERPC_EVENT(L3_CACHE_MISSES, 0x10, 20),
263 	PMC_POWERPC_EVENT(L2_CACHE_CASTOUTS, 0x20, 8),
264 	PMC_POWERPC_EVENT(L3_CACHE_CASTOUTS, 0x20, 9),
265 	PMC_POWERPC_EVENT(L2SQ_FULL_CYCLES, 0x20, 10),
266 	PMC_POWERPC_EVENT(L3SQ_FULL_CYCLES, 0x20, 11),
267 	PMC_POWERPC_EVENT(RAQ_FULL_CYCLES, 0x20, 16),
268 	PMC_POWERPC_EVENT(WAQ_FULL_CYCLES, 0x20, 17),
269 	PMC_POWERPC_EVENT(L1_EXTERNAL_INTERVENTIONS, 0x20, 19),
270 	PMC_POWERPC_EVENT(L2_EXTERNAL_INTERVENTIONS, 0x20, 20),
271 	PMC_POWERPC_EVENT(L3_EXTERNAL_INTERVENTIONS, 0x20, 21),
272 	PMC_POWERPC_EVENT(EXTERNAL_INTERVENTIONS, 0x20, 22),
273 	PMC_POWERPC_EVENT(EXTERNAL_PUSHES, 0x20, 23),
274 	PMC_POWERPC_EVENT(EXTERNAL_SNOOP_RETRY, 0x20, 24),
275 	PMC_POWERPC_EVENT(DTQ_FULL_CYCLES, 0x20, 25),
276 	PMC_POWERPC_EVENT(BUS_RETRY, 0x20, 26),
277 	PMC_POWERPC_EVENT(L2_VALID_REQUEST, 0x20, 27),
278 	PMC_POWERPC_EVENT(BORDQ_FULL, 0x20, 28),
279 	PMC_POWERPC_EVENT(BUS_TAS_FOR_READS, 0x20, 42),
280 	PMC_POWERPC_EVENT(BUS_TAS_FOR_WRITES, 0x20, 43),
281 	PMC_POWERPC_EVENT(BUS_READS_NOT_RETRIED, 0x20, 44),
282 	PMC_POWERPC_EVENT(BUS_WRITES_NOT_RETRIED, 0x20, 45),
283 	PMC_POWERPC_EVENT(BUS_READS_WRITES_NOT_RETRIED, 0x20, 46),
284 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_L1_RETRY, 0x20, 47),
285 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_PREVIOUS_ADJACENT, 0x20, 48),
286 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_COLLISION, 0x20, 49),
287 	PMC_POWERPC_EVENT(BUS_RETRY_DUE_TO_INTERVENTION_ORDERING, 0x20, 50),
288 	PMC_POWERPC_EVENT(SNOOP_REQUESTS, 0x20, 51),
289 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_REQUEST, 0x20, 52),
290 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD, 0x20, 53),
291 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_STORE, 0x20, 54),
292 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_INSTR_FETCH, 0x20, 55),
293 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_COLLISION_VS_LOAD_STORE_INSTR_FETCH, 0x20, 56),
294 	PMC_POWERPC_EVENT(PREFETCH_ENGINE_FULL, 0x20, 57)
295 };
296 static size_t mpc7xxx_event_codes_size = nitems(mpc7xxx_event_codes);
297 
298 static pmc_value_t
299 mpc7xxx_pmcn_read(unsigned int pmc)
300 {
301 	switch (pmc) {
302 	case 0:
303 		return (mfspr(SPR_PMC1_74XX));
304 	case 1:
305 		return (mfspr(SPR_PMC2_74XX));
306 	case 2:
307 		return (mfspr(SPR_PMC3_74XX));
308 	case 3:
309 		return (mfspr(SPR_PMC4_74XX));
310 	case 4:
311 		return (mfspr(SPR_PMC5_74XX));
312 	case 5:
313 		return (mfspr(SPR_PMC6_74XX));
314 	default:
315 		panic("Invalid PMC number: %d\n", pmc);
316 	}
317 }
318 
319 static void
320 mpc7xxx_pmcn_write(unsigned int pmc, uint32_t val)
321 {
322 	switch (pmc) {
323 	case 0:
324 		mtspr(SPR_PMC1_74XX, val);
325 		break;
326 	case 1:
327 		mtspr(SPR_PMC2_74XX, val);
328 		break;
329 	case 2:
330 		mtspr(SPR_PMC3_74XX, val);
331 		break;
332 	case 3:
333 		mtspr(SPR_PMC4_74XX, val);
334 		break;
335 	case 4:
336 		mtspr(SPR_PMC5_74XX, val);
337 		break;
338 	case 5:
339 		mtspr(SPR_PMC6_74XX, val);
340 		break;
341 	default:
342 		panic("Invalid PMC number: %d\n", pmc);
343 	}
344 }
345 
346 static void
347 mpc7xxx_set_pmc(int cpu, int ri, int config)
348 {
349 	register_t pmc_mmcr;
350 
351 	/* The mask is inverted (enable is 1) compared to the flags in
352 	 * MMCR0, which are Freeze flags.
353 	 */
354 	config &= ~POWERPC_PMC_ENABLE;
355 
356 	/* Enable/disable the PMC. */
357 	switch (ri) {
358 	case 0:
359 		pmc_mmcr = mfspr(SPR_MMCR0_74XX);
360 		pmc_mmcr = PPC_SET_PMC1SEL(pmc_mmcr, config);
361 		mtspr(SPR_MMCR0_74XX, pmc_mmcr);
362 		break;
363 	case 1:
364 		pmc_mmcr = mfspr(SPR_MMCR0_74XX);
365 		pmc_mmcr = PPC_SET_PMC2SEL(pmc_mmcr, config);
366 		mtspr(SPR_MMCR0_74XX, pmc_mmcr);
367 		break;
368 	case 2:
369 		pmc_mmcr = mfspr(SPR_MMCR1_74XX);
370 		pmc_mmcr = PPC_SET_PMC3SEL(pmc_mmcr, config);
371 		mtspr(SPR_MMCR1_74XX, pmc_mmcr);
372 		break;
373 	case 3:
374 		pmc_mmcr = mfspr(SPR_MMCR0_74XX);
375 		pmc_mmcr = PPC_SET_PMC4SEL(pmc_mmcr, config);
376 		mtspr(SPR_MMCR0_74XX, pmc_mmcr);
377 		break;
378 	case 4:
379 		pmc_mmcr = mfspr(SPR_MMCR1_74XX);
380 		pmc_mmcr = PPC_SET_PMC5SEL(pmc_mmcr, config);
381 		mtspr(SPR_MMCR1_74XX, pmc_mmcr);
382 		break;
383 	case 5:
384 		pmc_mmcr = mfspr(SPR_MMCR1_74XX);
385 		pmc_mmcr = PPC_SET_PMC6SEL(pmc_mmcr, config);
386 		mtspr(SPR_MMCR1_74XX, pmc_mmcr);
387 		break;
388 	}
389 
390 	if (config != PMCN_NONE) {
391 		pmc_mmcr = mfspr(SPR_MMCR0_74XX);
392 		pmc_mmcr &= ~SPR_MMCR0_FC;
393 		pmc_mmcr |= config;
394 		mtspr(SPR_MMCR0_74XX, pmc_mmcr);
395 	}
396 }
397 
398 static int
399 mpc7xxx_pcpu_init(struct pmc_mdep *md, int cpu)
400 {
401 	powerpc_pcpu_init(md, cpu);
402 
403 	/* Clear the MMCRs, and set FC, to disable all PMCs. */
404 	mtspr(SPR_MMCR0_74XX, SPR_MMCR0_FC | SPR_MMCR0_PMXE |
405 	    SPR_MMCR0_FCECE | SPR_MMCR0_PMC1CE | SPR_MMCR0_PMCNCE);
406 	mtspr(SPR_MMCR1_74XX, 0);
407 
408 	return (0);
409 }
410 
411 static int
412 mpc7xxx_pcpu_fini(struct pmc_mdep *md, int cpu)
413 {
414 	uint32_t mmcr0 = mfspr(SPR_MMCR0_74XX);
415 
416 	mtmsr(mfmsr() & ~PSL_PMM);
417 	mmcr0 |= SPR_MMCR0_FC;
418 	mtspr(SPR_MMCR0_74XX, mmcr0);
419 
420 	return (powerpc_pcpu_fini(md, cpu));
421 }
422 
423 static void
424 mpc7xxx_resume_pmc(bool ie)
425 {
426 	/* Re-enable PERF exceptions. */
427 	if (ie)
428 		mtspr(SPR_MMCR0_74XX,
429 		    (mfspr(SPR_MMCR0_74XX) & ~SPR_MMCR0_FC) | SPR_MMCR0_PMXE);
430 }
431 
432 int
433 pmc_mpc7xxx_initialize(struct pmc_mdep *pmc_mdep)
434 {
435 	struct pmc_classdep *pcd;
436 
437 	pmc_mdep->pmd_cputype = PMC_CPU_PPC_7450;
438 
439 	pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_POWERPC];
440 	pcd->pcd_caps  = POWERPC_PMC_CAPS;
441 	pcd->pcd_class = PMC_CLASS_PPC7450;
442 	pcd->pcd_num   = MPC7XXX_MAX_PMCS;
443 	pcd->pcd_ri    = pmc_mdep->pmd_npmc;
444 	pcd->pcd_width = 32;	/* All PMCs, even in ppc970, are 32-bit */
445 
446 	pcd->pcd_allocate_pmc   = powerpc_allocate_pmc;
447 	pcd->pcd_config_pmc     = powerpc_config_pmc;
448 	pcd->pcd_pcpu_fini      = mpc7xxx_pcpu_fini;
449 	pcd->pcd_pcpu_init      = mpc7xxx_pcpu_init;
450 	pcd->pcd_describe       = powerpc_describe;
451 	pcd->pcd_get_config     = powerpc_get_config;
452 	pcd->pcd_read_pmc       = powerpc_read_pmc;
453 	pcd->pcd_release_pmc    = powerpc_release_pmc;
454 	pcd->pcd_start_pmc      = powerpc_start_pmc;
455 	pcd->pcd_stop_pmc       = powerpc_stop_pmc;
456 	pcd->pcd_write_pmc      = powerpc_write_pmc;
457 
458 	pmc_mdep->pmd_npmc   += MPC7XXX_MAX_PMCS;
459 	pmc_mdep->pmd_intr   =  powerpc_pmc_intr;
460 
461 	ppc_event_codes = mpc7xxx_event_codes;
462 	ppc_event_codes_size = mpc7xxx_event_codes_size;
463 	ppc_event_first = PMC_EV_PPC7450_FIRST;
464 	ppc_event_last = PMC_EV_PPC7450_LAST;
465 	ppc_max_pmcs = MPC7XXX_MAX_PMCS;
466 	ppc_class = pcd->pcd_class;
467 
468 	powerpc_set_pmc = mpc7xxx_set_pmc;
469 	powerpc_pmcn_read = mpc7xxx_pmcn_read;
470 	powerpc_pmcn_write = mpc7xxx_pmcn_write;
471 	powerpc_resume_pmc = mpc7xxx_resume_pmc;
472 
473 	return (0);
474 }
475