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