Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/pcbe/p4_pcbe.c
+++ new/usr/src/uts/intel/pcbe/p4_pcbe.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /*
26 26 * This file contains preset event names from the Performance Application
27 27 * Programming Interface v3.5 which included the following notice:
28 28 *
29 29 * Copyright (c) 2005,6
30 30 * Innovative Computing Labs
31 31 * Computer Science Department,
32 32 * University of Tennessee,
33 33 * Knoxville, TN.
34 34 * All Rights Reserved.
35 35 *
36 36 *
37 37 * Redistribution and use in source and binary forms, with or without
38 38 * modification, are permitted provided that the following conditions are met:
39 39 *
40 40 * * Redistributions of source code must retain the above copyright notice,
41 41 * this list of conditions and the following disclaimer.
42 42 * * Redistributions in binary form must reproduce the above copyright
43 43 * notice, this list of conditions and the following disclaimer in the
44 44 * documentation and/or other materials provided with the distribution.
45 45 * * Neither the name of the University of Tennessee nor the names of its
46 46 * contributors may be used to endorse or promote products derived from
47 47 * this software without specific prior written permission.
48 48 *
49 49 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
50 50 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
53 53 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
54 54 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
55 55 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
56 56 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
57 57 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
58 58 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
59 59 * POSSIBILITY OF SUCH DAMAGE.
60 60 *
61 61 *
62 62 * This open source software license conforms to the BSD License template.
63 63 */
64 64
65 65 /*
66 66 * Performance Counter Back-End for Pentium 4.
67 67 */
68 68
69 69 #include <sys/cpuvar.h>
70 70 #include <sys/param.h>
71 71 #include <sys/cpc_impl.h>
72 72 #include <sys/cpc_pcbe.h>
73 73 #include <sys/inttypes.h>
74 74 #include <sys/errno.h>
75 75 #include <sys/systm.h>
76 76 #include <sys/archsystm.h>
77 77 #include <sys/x86_archext.h>
78 78 #include <sys/modctl.h>
79 79 #include <sys/sdt.h>
80 80 #include <sys/cred.h>
81 81 #include <sys/policy.h>
82 82 #include <sys/privregs.h>
83 83
84 84 static int p4_pcbe_init(void);
85 85 static uint_t p4_pcbe_ncounters(void);
86 86 static const char *p4_pcbe_impl_name(void);
87 87 static const char *p4_pcbe_cpuref(void);
88 88 static char *p4_pcbe_list_events(uint_t picnum);
89 89 static char *p4_pcbe_list_attrs(void);
90 90 static uint64_t p4_pcbe_event_coverage(char *event);
91 91 static uint64_t p4_pcbe_overflow_bitmap(void);
92 92 static int p4_pcbe_configure(uint_t picnum, char *event, uint64_t preset,
93 93 uint32_t flags, uint_t nattrs, kcpc_attr_t *attrs, void **data,
94 94 void *token);
95 95 static void p4_pcbe_program(void *token);
96 96 static void p4_pcbe_allstop(void);
97 97 static void p4_pcbe_sample(void *token);
98 98 static void p4_pcbe_free(void *config);
99 99
100 100 extern int cpuid_get_clogid(cpu_t *);
101 101
102 102 static pcbe_ops_t p4_pcbe_ops = {
103 103 PCBE_VER_1,
104 104 CPC_CAP_OVERFLOW_INTERRUPT | CPC_CAP_OVERFLOW_PRECISE,
105 105 p4_pcbe_ncounters,
106 106 p4_pcbe_impl_name,
107 107 p4_pcbe_cpuref,
108 108 p4_pcbe_list_events,
109 109 p4_pcbe_list_attrs,
110 110 p4_pcbe_event_coverage,
111 111 p4_pcbe_overflow_bitmap,
112 112 p4_pcbe_configure,
113 113 p4_pcbe_program,
114 114 p4_pcbe_allstop,
115 115 p4_pcbe_sample,
116 116 p4_pcbe_free
117 117 };
118 118
119 119 /*
120 120 * P4 Configuration Flags.
121 121 */
122 122 #define P4_THIS_USR 0x1 /* HTT: Measure usr events on this logical CPU */
123 123 #define P4_THIS_SYS 0x2 /* HTT: Measure os events on this logical CPU */
124 124 #define P4_SIBLING_USR 0x4 /* HTT: Measure os events on other logical CPU */
125 125 #define P4_SIBLING_SYS 0x8 /* HTT: Measure usr events on other logical CPU */
126 126 #define P4_PMI 0x10 /* HTT: Set PMI bit for local logical CPU */
127 127
128 128 typedef struct _p4_pcbe_config {
129 129 uint8_t p4_flags;
130 130 uint8_t p4_picno; /* From 0 to 18 */
131 131 uint8_t p4_escr_ndx; /* Which ESCR to use */
132 132 uint32_t p4_escr; /* Value to program in selected ESCR */
133 133 uint32_t p4_cccr; /* Value to program in counter's CCCR */
134 134 uint64_t p4_rawpic;
135 135 } p4_pcbe_config_t;
136 136
137 137 typedef uint32_t cntr_map_t;
138 138
139 139 typedef struct _p4_escr {
140 140 int pe_num;
141 141 uint32_t pe_addr;
142 142 uint32_t pe_map; /* bitmap of counters; bit 1 means ctr 0 */
143 143 } p4_escr_t;
144 144
145 145 #define MASK40 UINT64_C(0xffffffffff)
146 146
147 147 /*
148 148 * CCCR field definitions.
149 149 *
150 150 * Note that the Intel Developer's Manual states that the reserved field at
151 151 * bit location 16 and 17 must be set to 11. (??)
152 152 */
153 153 #define CCCR_ENABLE_SHIFT 12
154 154 #define CCCR_ESCR_SEL_SHIFT 13
155 155 #define CCCR_ACTV_THR_SHIFT 16
156 156 #define CCCR_COMPARE_SHIFT 18
157 157 #define CCCR_COMPLEMENT_SHIFT 19
158 158 #define CCCR_THRESHOLD_SHIFT 20
159 159 #define CCCR_EDGE_SHIFT 24
160 160 #define CCCR_OVF_PMI_SHIFT 26
161 161 #define CCCR_OVF_PMI_T0_SHIFT 26
162 162 #define CCCR_OVF_PMI_T1_SHIFT 27
163 163 #define CCCR_OVF_SHIFT 31
164 164 #define CCCR_ACTV_THR_MASK 0x3
165 165 #define CCCR_THRESHOLD_MAX 0xF
166 166 #define CCCR_ENABLE (1U << CCCR_ENABLE_SHIFT)
167 167 #define CCCR_COMPARE (1U << CCCR_COMPARE_SHIFT)
168 168 #define CCCR_COMPLEMENT (1U << CCCR_COMPLEMENT_SHIFT)
169 169 #define CCCR_EDGE (1U << CCCR_EDGE_SHIFT)
170 170 #define CCCR_OVF_PMI (1U << CCCR_OVF_PMI_SHIFT)
171 171 #define CCCR_OVF_PMI_T0 (1U << CCCR_OVF_PMI_T0_SHIFT)
172 172 #define CCCR_OVF_PMI_T1 (1U << CCCR_OVF_PMI_T1_SHIFT)
173 173 #define CCCR_INIT CCCR_ENABLE
174 174 #define CCCR_OVF (1U << CCCR_OVF_SHIFT)
175 175
176 176 #define ESCR_EVSEL_SHIFT 25
177 177 #define ESCR_EVMASK_SHIFT 9
178 178 #define ESCR_TAG_VALUE_SHIFT 5
179 179 #define ESCR_TAG_VALUE_MAX 0xF
180 180 #define ESCR_TAG_ENABLE_SHIFT 4
181 181 #define ESCR_USR_SHIFT 2
182 182 #define ESCR_OS_SHIFT 3
183 183 #define ESCR_USR (1U << ESCR_USR_SHIFT)
184 184 #define ESCR_OS (1U << ESCR_OS_SHIFT)
185 185 #define ESCR_TAG_ENABLE (1U << ESCR_TAG_ENABLE_SHIFT)
186 186
187 187 /*
188 188 * HyperThreaded ESCR fields.
189 189 */
190 190 #define ESCR_T0_OS_SHIFT 3
191 191 #define ESCR_T0_USR_SHIFT 2
192 192 #define ESCR_T1_OS_SHIFT 1
193 193 #define ESCR_T1_USR_SHIFT 0
194 194 #define ESCR_T0_OS (1U << ESCR_T0_OS_SHIFT)
195 195 #define ESCR_T0_USR (1U << ESCR_T0_USR_SHIFT)
196 196 #define ESCR_T1_OS (1U << ESCR_T1_OS_SHIFT)
197 197 #define ESCR_T1_USR (1U << ESCR_T1_USR_SHIFT)
198 198
199 199 /*
200 200 * ESCRs are grouped by counter; each group of ESCRs is associated with a
201 201 * distinct group of counters. Use these macros to fill in the table below.
202 202 */
203 203 #define BPU0_map (0x1 | 0x2) /* Counters 0 and 1 */
204 204 #define BPU2_map (0x4 | 0x8) /* Counters 2 and 3 */
205 205 #define MS0_map (0x10 | 0x20) /* Counters 4 and 5 */
206 206 #define MS2_map (0x40 | 0x80) /* Counters 6 and 7 */
207 207 #define FLAME0_map (0x100 | 0x200) /* Counters 8 and 9 */
208 208 #define FLAME2_map (0x400 | 0x800) /* Counters 10 and 11 */
209 209 #define IQ0_map (0x1000 | 0x2000 | 0x10000) /* Counters 12, 13, 16 */
210 210 #define IQ2_map (0x4000 | 0x8000 | 0x20000) /* Counters 14, 15, 17 */
211 211
212 212 /*
213 213 * Table describing the 45 Event Selection and Control Registers (ESCRs).
214 214 */
215 215 const p4_escr_t p4_escrs[] = {
216 216 #define BPU0 (1)
217 217 { 0, 0x3B2, BPU0_map }, /* 0 */
218 218 #define IS0 (1ULL << 1)
219 219 { 1, 0x3B4, BPU0_map }, /* 1 */
220 220 #define MOB0 (1ULL << 2)
221 221 { 2, 0x3AA, BPU0_map }, /* 2 */
222 222 #define ITLB0 (1ULL << 3)
223 223 { 3, 0x3B6, BPU0_map }, /* 3 */
224 224 #define PMH0 (1ULL << 4)
225 225 { 4, 0x3AC, BPU0_map }, /* 4 */
226 226 #define IX0 (1ULL << 5)
227 227 { 5, 0x3C8, BPU0_map }, /* 5 */
228 228 #define FSB0 (1ULL << 6)
229 229 { 6, 0x3A2, BPU0_map }, /* 6 */
230 230 #define BSU0 (1ULL << 7)
231 231 { 7, 0x3A0, BPU0_map }, /* 7 */
232 232 #define BPU1 (1ULL << 8)
233 233 { 0, 0x3B3, BPU2_map }, /* 8 */
234 234 #define IS1 (1ULL << 9)
235 235 { 1, 0x3B5, BPU2_map }, /* 9 */
236 236 #define MOB1 (1ULL << 10)
237 237 { 2, 0x3AB, BPU2_map }, /* 10 */
238 238 #define ITLB1 (1ULL << 11)
239 239 { 3, 0x3B7, BPU2_map }, /* 11 */
240 240 #define PMH1 (1ULL << 12)
241 241 { 4, 0x3AD, BPU2_map }, /* 12 */
242 242 #define IX1 (1ULL << 13)
243 243 { 5, 0x3C9, BPU2_map }, /* 13 */
244 244 #define FSB1 (1ULL << 14)
245 245 { 6, 0x3A3, BPU2_map }, /* 14 */
246 246 #define BSU1 (1ULL << 15)
247 247 { 7, 0x3A1, BPU2_map }, /* 15 */
248 248 #define MS0 (1ULL << 16)
249 249 { 0, 0x3C0, MS0_map }, /* 16 */
250 250 #define TC0 (1ULL << 17)
251 251 { 1, 0x3C4, MS0_map }, /* 17 */
252 252 #define TBPU0 (1ULL << 18)
253 253 { 2, 0x3C2, MS0_map }, /* 18 */
254 254 #define MS1 (1ULL << 19)
255 255 { 0, 0x3C1, MS2_map }, /* 19 */
256 256 #define TC1 (1ULL << 20)
257 257 { 1, 0x3C5, MS2_map }, /* 20 */
258 258 #define TBPU1 (1ULL << 21)
259 259 { 2, 0x3C3, MS2_map }, /* 21 */
260 260 #define FLAME0 (1ULL << 22)
261 261 { 0, 0x3A6, FLAME0_map }, /* 22 */
262 262 #define FIRM0 (1ULL << 23)
263 263 { 1, 0x3A4, FLAME0_map }, /* 23 */
264 264 #define SAAT0 (1ULL << 24)
265 265 { 2, 0x3AE, FLAME0_map }, /* 24 */
266 266 #define U2L0 (1ULL << 25)
267 267 { 3, 0x3B0, FLAME0_map }, /* 25 */
268 268 #define DAC0 (1ULL << 26)
269 269 { 5, 0x3A8, FLAME0_map }, /* 26 */
270 270 #define FLAME1 (1ULL << 27)
271 271 { 0, 0x3A7, FLAME2_map }, /* 27 */
272 272 #define FIRM1 (1ULL << 28)
273 273 { 1, 0x3A5, FLAME2_map }, /* 28 */
274 274 #define SAAT1 (1ULL << 29)
275 275 { 2, 0x3AF, FLAME2_map }, /* 29 */
276 276 #define U2L1 (1ULL << 30)
277 277 { 3, 0x3B1, FLAME2_map }, /* 30 */
278 278 #define DAC1 (1ULL << 31)
279 279 { 5, 0x3A9, FLAME2_map }, /* 31 */
280 280 #define IQ0 (1ULL << 32)
281 281 { 0, 0x3BA, IQ0_map }, /* 32 */
282 282 #define ALF0 (1ULL << 33)
283 283 { 1, 0x3CA, IQ0_map }, /* 33 */
284 284 #define RAT0 (1ULL << 34)
285 285 { 2, 0x3BC, IQ0_map }, /* 34 */
286 286 #define SSU0 (1ULL << 35)
287 287 { 3, 0x3BE, IQ0_map }, /* 35 */
288 288 #define CRU0 (1ULL << 36)
289 289 { 4, 0x3B8, IQ0_map }, /* 36 */
290 290 #define CRU2 (1ULL << 37)
291 291 { 5, 0x3CC, IQ0_map }, /* 37 */
292 292 #define CRU4 (1ULL << 38)
293 293 { 6, 0x3E0, IQ0_map }, /* 38 */
294 294 #define IQ1 (1ULL << 39)
295 295 { 0, 0x3BB, IQ2_map }, /* 39 */
296 296 #define ALF1 (1ULL << 40)
297 297 { 1, 0x3CB, IQ2_map }, /* 40 */
298 298 #define RAT1 (1ULL << 41)
299 299 { 2, 0x3BD, IQ2_map }, /* 41 */
300 300 #define CRU1 (1ULL << 42)
301 301 { 4, 0x3B9, IQ2_map }, /* 42 */
302 302 #define CRU3 (1ULL << 43)
303 303 { 5, 0x3CD, IQ2_map }, /* 43 */
304 304 #define CRU5 (1ULL << 44)
305 305 { 6, 0x3E1, IQ2_map } /* 44 */
306 306 };
307 307
308 308 #define ESCR_MAX_INDEX 44
309 309
310 310 typedef struct _p4_ctr {
311 311 uint32_t pc_caddr; /* counter MSR address */
312 312 uint32_t pc_ctladdr; /* counter's CCCR MSR address */
313 313 uint64_t pc_map; /* bitmap of ESCRs controlling ctr */
314 314 } p4_ctr_t;
315 315
316 316 const p4_ctr_t p4_ctrs[18] = {
317 317 { /* BPU_COUNTER0 */ 0x300, 0x360, BSU0|FSB0|MOB0|PMH0|BPU0|IS0|ITLB0|IX0},
318 318 { /* BPU_COUNTER1 */ 0x301, 0x361, BSU0|FSB0|MOB0|PMH0|BPU0|IS0|ITLB0|IX0},
319 319 { /* BPU_COUNTER2 */ 0x302, 0x362, BSU1|FSB1|MOB1|PMH1|BPU1|IS1|ITLB1|IX1},
320 320 { /* BPU_COUNTER3 */ 0x303, 0x363, BSU1|FSB1|MOB1|PMH1|BPU1|IS1|ITLB1|IX1},
321 321 { /* MS_COUNTER0 */ 0x304, 0x364, MS0|TBPU0|TC0 },
322 322 { /* MS_COUNTER1 */ 0x305, 0x365, MS0|TBPU0|TC0 },
323 323 { /* MS_COUNTER2 */ 0x306, 0x366, MS1|TBPU1|TC1 },
324 324 { /* MS_COUNTER3 */ 0x307, 0x367, MS1|TBPU1|TC1 },
325 325 { /* FLAME_COUNTER0 */ 0x308, 0x368, FIRM0|FLAME0|DAC0|SAAT0|U2L0 },
326 326 { /* FLAME_COUNTER1 */ 0x309, 0x369, FIRM0|FLAME0|DAC0|SAAT0|U2L0 },
327 327 { /* FLAME_COUNTER2 */ 0x30A, 0x36A, FIRM1|FLAME1|DAC1|SAAT1|U2L1 },
328 328 { /* FLAME_COUNTER3 */ 0x30B, 0x36B, FIRM1|FLAME1|DAC1|SAAT1|U2L1 },
329 329 { /* IQ_COUNTER0 */ 0x30C, 0x36C, CRU0|CRU2|CRU4|IQ0|RAT0|SSU0|ALF0 },
330 330 { /* IQ_COUNTER1 */ 0x30D, 0x36D, CRU0|CRU2|CRU4|IQ0|RAT0|SSU0|ALF0 },
331 331 { /* IQ_COUNTER2 */ 0x30E, 0x36E, CRU1|CRU3|CRU5|IQ1|RAT1|ALF1 },
332 332 { /* IQ_COUNTER3 */ 0x30F, 0x36F, CRU1|CRU3|CRU5|IQ1|RAT1|ALF1 },
333 333 { /* IQ_COUNTER4 */ 0x310, 0x370, CRU0|CRU2|CRU4|IQ0|RAT0|SSU0|ALF0 },
334 334 { /* IQ_COUNTER5 */ 0x311, 0x371, CRU1|CRU3|CRU5|IQ1|RAT1|ALF1 }
335 335 };
336 336
337 337 typedef struct _p4_event {
338 338 char *pe_name; /* Name of event according to docs */
339 339 uint64_t pe_escr_map; /* Bitmap of ESCRs capable of event */
340 340 uint32_t pe_escr_mask; /* permissible ESCR event mask */
341 341 uint8_t pe_ev; /* ESCR event select value */
342 342 uint16_t pe_cccr; /* CCCR select value */
343 343 uint32_t pe_ctr_mask; /* Bitmap of capable counters */
344 344 } p4_event_t;
345 345
346 346 typedef struct _p4_generic_event {
347 347 char *name;
348 348 char *event;
349 349 uint16_t emask;
350 350 uint32_t ctr_mask;
351 351 } p4_generic_event_t;
352 352
353 353 #define C(n) (1 << n)
354 354 #define GEN_EVT_END { NULL, NULL, 0x0, 0x0 }
355 355
356 356 p4_event_t p4_events[] = {
357 357 { "branch_retired", CRU2|CRU3, 0xF, 0x6, 0x5, C(12)|C(13)|C(14)|C(15)|C(16) },
358 358 { "mispred_branch_retired", CRU0|CRU1, 0x1, 0x3, 0x4,
359 359 C(12)|C(13)|C(14)|C(15)|C(16) },
360 360 { "TC_deliver_mode", TC0|TC1, 0xFF, 0x1, 0x1, C(4)|C(5)|C(6)|C(7) },
361 361 { "BPU_fetch_request", BPU0|BPU1, 0x1, 0x3, 0x0, C(0)|C(1)|C(2)|C(3) },
362 362 { "ITLB_reference", ITLB0|ITLB1, 0x7, 0x18, 0x3, C(0)|C(1)|C(2)|C(3) },
363 363 { "memory_cancel", DAC0|DAC1, 0x6, 0x2, 0x5, C(8)|C(9)|C(10)|C(11) },
364 364 { "memory_complete", SAAT0|SAAT1, 0x3, 0x8, 0x2, C(8)|C(9)|C(10)|C(11) },
365 365 { "load_port_replay", SAAT0|SAAT1, 0x1, 0x4, 0x2, C(8)|C(9)|C(10)|C(11) },
366 366 { "store_port_replay", SAAT0|SAAT1, 0x1, 0x5, 0x2, C(8)|C(9)|C(10)|C(11) },
367 367 { "MOB_load_replay", MOB0|MOB1, 0x35, 0x3, 0x2, C(0)|C(1)|C(2)|C(3) },
368 368 { "page_walk_type", PMH0|PMH1, 0x3, 0x1, 0x4, C(0)|C(1)|C(2)|C(3) },
369 369 { "BSQ_cache_reference", BSU0|BSU1, 0x73F, 0xC, 0x7, C(0)|C(1)|C(2)|C(3) },
370 370 { "IOQ_allocation", FSB0, 0xEFFF, 0x3, 0x6, C(0)|C(1) },
371 371 { "IOQ_active_entries", FSB1, 0xEFFF, 0x1A, 0x6, C(2)|C(3) },
372 372 { "FSB_data_activity", FSB0|FSB1, 0x3F, 0x17, 0x6, C(0)|C(1)|C(2)|C(3) },
373 373 { "BSQ_allocation", BSU0, 0x3FEF, 0x5, 0x7, C(0)|C(1) },
374 374 { "bsq_active_entries", BSU1, 0x3FEF, 0x6, 0x7, C(2)|C(3) },
375 375 { "x87_assist", CRU2|CRU3, 0x1F, 0x3, 0x5, C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
376 376 { "SSE_input_assist", FIRM0|FIRM1, 0x8000, 0x34, 0x1, C(8)|C(9)|C(10)|C(11) },
377 377 { "packed_SP_uop", FIRM0|FIRM1, 0x8000, 0x8, 0x1, C(8)|C(9)|C(10)|C(11) },
378 378 { "packed_DP_uop", FIRM0|FIRM1, 0x8000, 0xC, 0x1, C(8)|C(9)|C(10)|C(11) },
379 379 { "scalar_SP_uop", FIRM0|FIRM1, 0x8000, 0xA, 0x1, C(8)|C(9)|C(10)|C(11) },
380 380 { "scalar_DP_uop", FIRM0|FIRM1, 0x8000, 0xE, 0x1, C(8)|C(9)|C(10)|C(11) },
381 381 { "64bit_MMX_uop", FIRM0|FIRM1, 0x8000, 0x2, 0x1, C(8)|C(9)|C(10)|C(11) },
382 382 { "128bit_MMX_uop", FIRM0|FIRM1, 0x8000, 0x1A, 0x1, C(8)|C(9)|C(10)|C(11) },
383 383 { "x87_FP_uop", FIRM0|FIRM1, 0x8000, 0x4, 0x1, C(8)|C(9)|C(10)|C(11) },
384 384 { "x87_SIMD_moves_uop", FIRM0|FIRM1, 0x18, 0x2E, 0x1, C(8)|C(9)|C(10)|C(11) },
385 385 { "machine_clear", CRU2|CRU3, 0xD, 0x2, 0x5,
386 386 C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
387 387 { "global_power_events", FSB0|FSB1, 0x1, 0x13, 0x6, C(0)|C(1)|C(2)|C(3) },
388 388 { "tc_ms_xfer", MS0|MS1, 0x1, 0x5, 0x0, C(4)|C(5)|C(6)|C(7) },
389 389 { "uop_queue_writes", MS0|MS1, 0x7, 0x9, 0x0, C(4)|C(5)|C(6)|C(7) },
390 390 { "front_end_event", CRU2|CRU3, 0x3, 0x8, 0x5,
391 391 C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
392 392 { "execution_event", CRU2|CRU3, 0xFF, 0xC, 0x5,
393 393 C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
394 394 { "replay_event", CRU2|CRU3, 0x3, 0x9, 0x5,
395 395 C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
396 396 { "instr_retired", CRU0|CRU1, 0xF, 0x2, 0x4,
397 397 C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
398 398 { "uops_retired", CRU0|CRU1, 0x3, 0x1, 0x4,
399 399 C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
400 400 { "uop_type", RAT0|RAT1, 0x3, 0x2, 0x2, C(12)|C(13)|C(14)|C(15)|C(16)|C(17)},
401 401 { "retired_mispred_branch_type", TBPU0|TBPU1, 0x1F, 0x5, 0x2,
402 402 C(4)|C(5)|C(6)|C(7)},
403 403 { "retired_branch_type", TBPU0|TBPU1, 0x1F, 0x4, 0x2, C(4)|C(5)|C(6)|C(7) },
404 404 { NULL, 0, 0, 0, 0 }
405 405 };
406 406
407 407 static p4_generic_event_t p4_generic_events[] = {
408 408 { "PAPI_br_msp", "branch_retired", 0xa, C(12)|C(13)|C(14)|C(15)|C(16) },
409 409 { "PAPI_br_ins", "branch_retired", 0xf, C(12)|C(13)|C(14)|C(15)|C(16) },
410 410 { "PAPI_br_tkn", "branch_retired", 0xc, C(12)|C(13)|C(14)|C(15)|C(16) },
411 411 { "PAPI_br_ntk", "branch_retired", 0x3, C(12)|C(13)|C(14)|C(15)|C(16) },
412 412 { "PAPI_br_prc", "branch_retired", 0x5, C(12)|C(13)|C(14)|C(15)|C(16) },
413 413 { "PAPI_tot_ins", "instr_retired", 0x3, C(12)|C(13)|C(14)|C(15)|C(16)|C(17) },
414 414 { "PAPI_tot_cyc", "global_power_events", 0x1, C(0)|C(1)|C(2)|C(3) },
415 415 { "PAPI_tlb_dm", "page_walk_type", 0x1, C(0)|C(1)|C(2)|C(3) },
416 416 { "PAPI_tlb_im", "page_walk_type", 0x2, C(0)|C(1)|C(2)|C(3) },
417 417 { "PAPI_tlb_tm", "page_walk_type", 0x3, C(0)|C(1)|C(2)|C(3) },
418 418 { "PAPI_l1_icm", "BPU_fetch_request", 0x1, C(0)|C(1)|C(2)|C(3) },
419 419 { "PAPI_l2_ldm", "BSQ_cache_reference", 0x100, C(0)|C(1)|C(2)|C(3) },
420 420 { "PAPI_l2_stm", "BSQ_cache_reference", 0x400, C(0)|C(1)|C(2)|C(3) },
421 421 { "PAPI_l2_tcm", "BSQ_cache_reference", 0x500, C(0)|C(1)|C(2)|C(3) },
422 422 GEN_EVT_END
423 423 };
424 424
425 425 /*
426 426 * Indicates whether the "rdpmc" instruction is available on this processor.
427 427 */
428 428 static int p4_rdpmc_avail = 0;
429 429
430 430 static const uint64_t p4_cccrstop = 0;
431 431
432 432 static char *p4_eventlist[18];
433 433
434 434 /*
435 435 * If set, this processor has HyperThreading.
436 436 */
437 437 static int p4_htt = 0;
438 438
439 439 #define P4_FAMILY 0xF
440 440
441 441 static int
442 442 p4_pcbe_init(void)
443 443 {
444 444 int i;
445 445 size_t size;
446 446 p4_event_t *ev;
447 447 p4_generic_event_t *gevp;
448 448
449 449 /*
450 450 * If we're not running on a P4, refuse to load.
451 451 */
452 452 if (cpuid_getvendor(CPU) != X86_VENDOR_Intel ||
453 453 cpuid_getfamily(CPU) != P4_FAMILY)
454 454 return (-1);
455 455
456 456 /*
457 457 * Set up the event lists for each counter.
458 458 *
459 459 * First pass calculates the size of the event list, and the second
460 460 * pass copies each event name into the event list.
461 461 */
462 462 for (i = 0; i < 18; i++) {
463 463 size = 0;
464 464
465 465 for (ev = p4_events; ev->pe_name != NULL; ev++) {
466 466 if (ev->pe_ctr_mask & C(i))
467 467 size += strlen(ev->pe_name) + 1;
468 468 }
469 469
470 470 for (gevp = p4_generic_events; gevp->name != NULL; gevp++) {
471 471 if (gevp->ctr_mask & C(i))
472 472 size += strlen(gevp->name) + 1;
473 473 }
474 474
475 475 /*
476 476 * We use 'size + 1' here to ensure room for the final
477 477 * strcat when it terminates the string.
478 478 */
479 479 p4_eventlist[i] = (char *)kmem_alloc(size + 1, KM_SLEEP);
480 480 *p4_eventlist[i] = '\0';
481 481
482 482 for (ev = p4_events; ev->pe_name != NULL; ev++) {
483 483 if (ev->pe_ctr_mask & C(i)) {
484 484 (void) strcat(p4_eventlist[i], ev->pe_name);
485 485 (void) strcat(p4_eventlist[i], ",");
486 486 }
487 487 }
488 488
489 489 for (gevp = p4_generic_events; gevp->name != NULL; gevp++) {
490 490 if (gevp->ctr_mask & C(i)) {
491 491 (void) strcat(p4_eventlist[i], gevp->name);
492 492 (void) strcat(p4_eventlist[i], ",");
493 493 }
494 494 }
495 495
496 496 /*
497 497 * Remove trailing ','
498 498 */
499 499 p4_eventlist[i][size - 1] = '\0';
500 500 }
501 501
502 502 if (is_x86_feature(x86_featureset, X86FSET_MMX))
503 503 p4_rdpmc_avail = 1;
504 504 /*
505 505 * The X86_HTT flag may disappear soon, so we'll isolate the impact of
506 506 * its demise to the following if().
507 507 */
508 508 if (is_x86_feature(x86_featureset, X86FSET_HTT))
509 509 p4_htt = 1;
510 510
511 511 return (0);
512 512 }
513 513
514 514 static uint_t
515 515 p4_pcbe_ncounters(void)
516 516 {
517 517 return (18);
518 518 }
519 519
520 520 static const char *
521 521 p4_pcbe_impl_name(void)
522 522 {
523 523 if (p4_htt)
524 524 return (PCBE_IMPL_NAME_P4HT);
525 525 return ("Pentium 4");
526 526 }
527 527
528 528 static const char *
529 529 p4_pcbe_cpuref(void)
530 530 {
531 531 return ("See Appendix A.1 of the \"IA-32 Intel Architecture Software " \
532 532 "Developer's Manual Volume 3: System Programming Guide,\" " \
533 533 "Order # 245472-012, 2003");
534 534 }
535 535
536 536 static char *
537 537 p4_pcbe_list_events(uint_t picnum)
538 538 {
539 539 ASSERT(picnum >= 0 && picnum < 18);
540 540
541 541 return (p4_eventlist[picnum]);
542 542 }
543 543
544 544 #define P4_ATTRS "emask,tag,compare,complement,threshold,edge"
545 545
546 546 static char *
547 547 p4_pcbe_list_attrs(void)
548 548 {
549 549 if (p4_htt)
550 550 return (P4_ATTRS ",active_thread,count_sibling_usr,"
551 551 "count_sibling_sys");
552 552 return (P4_ATTRS);
553 553 }
554 554
555 555 static p4_generic_event_t *
556 556 find_generic_event(char *name)
557 557 {
558 558 p4_generic_event_t *gevp;
559 559
560 560 for (gevp = p4_generic_events; gevp->name != NULL; gevp++)
561 561 if (strcmp(name, gevp->name) == 0)
562 562 return (gevp);
563 563
564 564 return (NULL);
565 565 }
566 566
567 567 static p4_event_t *
568 568 find_event(char *name)
569 569 {
570 570 p4_event_t *evp;
571 571
572 572 for (evp = p4_events; evp->pe_name != NULL; evp++)
573 573 if (strcmp(name, evp->pe_name) == 0)
574 574 return (evp);
575 575
576 576 return (NULL);
577 577 }
578 578
579 579 static uint64_t
580 580 p4_pcbe_event_coverage(char *event)
581 581 {
582 582 p4_event_t *ev;
583 583 p4_generic_event_t *gevp;
584 584
585 585 if ((ev = find_event(event)) == NULL) {
586 586 if ((gevp = find_generic_event(event)) != NULL)
587 587 return (gevp->ctr_mask);
588 588 else
589 589 return (0);
590 590 }
591 591
592 592 return (ev->pe_ctr_mask);
593 593 }
594 594
595 595 static uint64_t
596 596 p4_pcbe_overflow_bitmap(void)
597 597 {
598 598 extern int kcpc_hw_overflow_intr_installed;
599 599 uint64_t ret = 0;
600 600 int i;
601 601
602 602 /*
603 603 * The CCCR's OVF bit indicates that the corresponding counter has
604 604 * overflowed. It must be explicitly cleared by software, so it is
605 605 * safe to read the CCCR values here.
606 606 */
607 607 for (i = 0; i < 18; i++) {
608 608 if (rdmsr(p4_ctrs[i].pc_ctladdr) & CCCR_OVF)
609 609 ret |= (1 << i);
610 610 }
611 611
612 612 /*
613 613 * Pentium 4 and Xeon turn off the CPC interrupt mask bit in the LVT at
614 614 * every overflow. Turn it back on here.
615 615 */
616 616 ASSERT(kcpc_hw_overflow_intr_installed);
617 617 (*kcpc_hw_enable_cpc_intr)();
618 618
619 619 return (ret);
620 620 }
621 621
622 622 static int
623 623 p4_escr_inuse(p4_pcbe_config_t **cfgs, int escr_ndx)
624 624 {
625 625 int i;
626 626
627 627 for (i = 0; i < 18; i++) {
628 628 if (cfgs[i] == NULL)
629 629 continue;
630 630 if (cfgs[i]->p4_escr_ndx == escr_ndx)
631 631 return (1);
632 632 }
633 633
634 634 return (0);
635 635 }
636 636
637 637 static void
638 638 build_cfgs(p4_pcbe_config_t *cfgs[18], uint64_t *data[18], void *token)
639 639 {
640 640 p4_pcbe_config_t *cfg = NULL;
641 641 uint64_t *daddr;
642 642
643 643 bzero(cfgs, 18 * sizeof (p4_pcbe_config_t *));
644 644
645 645 do {
646 646 cfg = (p4_pcbe_config_t *)kcpc_next_config(token, cfg, &daddr);
647 647
648 648 if (cfg != NULL) {
649 649 ASSERT(cfg->p4_picno < 18);
650 650 cfgs[cfg->p4_picno] = cfg;
651 651 if (data != NULL) {
652 652 ASSERT(daddr != NULL);
653 653 data[cfg->p4_picno] = daddr;
654 654 }
655 655 }
656 656 } while (cfg != NULL);
657 657 }
658 658
659 659 /*
660 660 * Programming a counter:
661 661 *
662 662 * Select event.
663 663 * Choose an ESCR capable of counting that event.
664 664 * Set up the ESCR with the desired parameters (usr, sys, tag).
665 665 * Set up the CCCR to point to the selected ESCR.
666 666 * Set the CCCR parameters (overflow, cascade, edge, etc).
667 667 */
668 668 static int
669 669 p4_pcbe_configure(uint_t picnum, char *eventname, uint64_t preset,
670 670 uint32_t flags, uint_t nattrs, kcpc_attr_t *attrs, void **data,
671 671 void *token)
672 672 {
673 673 p4_pcbe_config_t *cfgs[18];
674 674 p4_pcbe_config_t *cfg;
675 675 p4_event_t *ev;
676 676 p4_generic_event_t *gevp;
677 677 int escr_ndx;
678 678 int i;
679 679 uint16_t emask = 0;
680 680 uint8_t tag;
681 681 int use_tag = 0;
682 682 int active_thread = 0x3; /* default is "any" */
683 683 int compare = 0;
684 684 int complement = 0;
685 685 int threshold = 0;
686 686 int edge = 0;
687 687 int sibling_usr = 0; /* count usr on other cpu */
688 688 int sibling_sys = 0; /* count sys on other cpu */
689 689 int invalid_attr = 0;
690 690
691 691 /*
692 692 * If we've been handed an existing configuration, we need only preset
693 693 * the counter value.
694 694 */
695 695 if (*data != NULL) {
696 696 cfg = *data;
697 697 cfg->p4_rawpic = preset & MASK40;
698 698 return (0);
699 699 }
700 700
701 701 if (picnum < 0 || picnum >= 18)
702 702 return (CPC_INVALID_PICNUM);
703 703
704 704 if ((ev = find_event(eventname)) == NULL) {
705 705 if ((gevp = find_generic_event(eventname)) != NULL) {
706 706 ev = find_event(gevp->event);
707 707 ASSERT(ev != NULL);
708 708
709 709 /*
710 710 * For generic events a HTT processor is only allowed
711 711 * to specify the 'active_thread', 'count_sibling_usr'
712 712 * and 'count_sibling_sys' attributes.
713 713 */
714 714 if (p4_htt)
715 715 for (i = 0; i < nattrs; i++)
716 716 if (strstr(P4_ATTRS,
717 717 attrs[i].ka_name) != NULL)
718 718 invalid_attr = 1;
719 719
720 720 if ((p4_htt && invalid_attr) ||
721 721 (!p4_htt && nattrs > 0))
722 722 return (CPC_ATTRIBUTE_OUT_OF_RANGE);
723 723
724 724 emask = gevp->emask;
725 725 } else {
726 726 return (CPC_INVALID_EVENT);
727 727 }
728 728 }
729 729
730 730 build_cfgs(cfgs, NULL, token);
731 731
732 732 /*
733 733 * Find an ESCR capable of counting this event.
734 734 */
735 735 for (escr_ndx = 0; escr_ndx < ESCR_MAX_INDEX; escr_ndx++) {
736 736 if ((ev->pe_escr_map & (1ULL << escr_ndx)) &&
737 737 p4_escr_inuse(cfgs, escr_ndx) == 0)
738 738 break;
739 739 }
740 740
741 741 /*
742 742 * All ESCRs capable of counting this event are already being
743 743 * used.
744 744 */
745 745 if (escr_ndx == ESCR_MAX_INDEX)
746 746 return (CPC_RESOURCE_UNAVAIL);
747 747
748 748 /*
749 749 * At this point, ev points to the desired event and escr is the index
750 750 * of a capable and available ESCR.
751 751 *
752 752 * Now process and verify the attributes.
753 753 */
754 754 for (i = 0; i < nattrs; i++) {
755 755 if (strcmp("emask", attrs[i].ka_name) == 0) {
756 756 if ((attrs[i].ka_val | ev->pe_escr_mask)
757 757 != ev->pe_escr_mask)
758 758 return (CPC_ATTRIBUTE_OUT_OF_RANGE);
759 759 emask = attrs[i].ka_val;
760 760 continue;
761 761 } else if (strcmp("tag", attrs[i].ka_name) == 0) {
762 762 if (attrs[i].ka_val > ESCR_TAG_VALUE_MAX)
763 763 return (CPC_ATTRIBUTE_OUT_OF_RANGE);
764 764 tag = attrs[i].ka_val;
765 765 use_tag = 1;
766 766 continue;
767 767 } else if (strcmp("compare", attrs[i].ka_name) == 0) {
768 768 if (attrs[i].ka_val != 0)
769 769 compare = 1;
770 770 continue;
771 771 } else if (strcmp("complement", attrs[i].ka_name) == 0) {
772 772 if (attrs[i].ka_val != 0)
773 773 complement = 1;
774 774 continue;
775 775 } else if (strcmp("threshold", attrs[i].ka_name) == 0) {
776 776 if (attrs[i].ka_val > CCCR_THRESHOLD_MAX)
777 777 return (CPC_ATTRIBUTE_OUT_OF_RANGE);
778 778 threshold = attrs[i].ka_val;
779 779 continue;
780 780 } else if (strcmp("edge", attrs[i].ka_name) == 0) {
781 781 if (attrs[i].ka_val != 0)
782 782 edge = 1;
783 783 continue;
784 784 }
785 785
786 786 /*
787 787 * The remaining attributes are valid only on HyperThreaded P4s
788 788 * for processes with the "cpc_cpu" privilege.
789 789 */
790 790 if (p4_htt == 0)
791 791 return (CPC_INVALID_ATTRIBUTE);
792 792
793 793 if (secpolicy_cpc_cpu(crgetcred()) != 0)
794 794 return (CPC_ATTR_REQUIRES_PRIVILEGE);
795 795
796 796 if (strcmp("active_thread", attrs[i].ka_name) == 0) {
797 797 if ((attrs[i].ka_val | CCCR_ACTV_THR_MASK) !=
798 798 CCCR_ACTV_THR_MASK)
799 799 return (CPC_ATTRIBUTE_OUT_OF_RANGE);
800 800 active_thread = (int)attrs[i].ka_val;
801 801 } else if (strcmp("count_sibling_usr", attrs[i].ka_name) == 0) {
802 802 if (attrs[i].ka_val != 0)
803 803 sibling_usr = 1;
804 804 } else if (strcmp("count_sibling_sys", attrs[i].ka_name) == 0) {
805 805 if (attrs[i].ka_val != 0)
806 806 sibling_sys = 1;
807 807 } else
808 808 return (CPC_INVALID_ATTRIBUTE);
809 809 }
810 810
811 811 /*
812 812 * Make sure the counter can count this event
813 813 */
814 814 if ((ev->pe_ctr_mask & C(picnum)) == 0)
815 815 return (CPC_PIC_NOT_CAPABLE);
816 816
817 817 /*
818 818 * Find an ESCR that lines up with the event _and_ the counter.
819 819 */
820 820 for (escr_ndx = 0; escr_ndx < ESCR_MAX_INDEX; escr_ndx++) {
821 821 if ((ev->pe_escr_map & (1ULL << escr_ndx)) &&
822 822 (p4_escrs[escr_ndx].pe_map & (1 << picnum)) &&
823 823 p4_escr_inuse(cfgs, escr_ndx) == 0)
824 824 break;
825 825 }
826 826 if (escr_ndx == ESCR_MAX_INDEX)
827 827 return (CPC_RESOURCE_UNAVAIL);
828 828
829 829 cfg = (p4_pcbe_config_t *)kmem_alloc(sizeof (p4_pcbe_config_t),
830 830 KM_SLEEP);
831 831
832 832 cfg->p4_flags = 0;
833 833 cfg->p4_picno = picnum;
834 834 cfg->p4_escr_ndx = escr_ndx;
835 835 cfg->p4_escr = (ev->pe_ev << ESCR_EVSEL_SHIFT) |
836 836 (emask << ESCR_EVMASK_SHIFT);
837 837
838 838 if (use_tag == 1) {
839 839 cfg->p4_escr |= tag << ESCR_TAG_VALUE_SHIFT;
840 840 cfg->p4_escr |= ESCR_TAG_ENABLE;
841 841 }
842 842
843 843 if (p4_htt) {
844 844 /*
845 845 * This is a HyperThreaded P4. Since we don't know which
846 846 * logical CPU this configuration will eventually be programmed
847 847 * on, we can't yet decide which fields of the ESCR to select.
848 848 *
849 849 * Record the necessary information in the flags for later.
850 850 */
851 851 if (flags & CPC_COUNT_USER)
852 852 cfg->p4_flags |= P4_THIS_USR;
853 853 if (flags & CPC_COUNT_SYSTEM)
854 854 cfg->p4_flags |= P4_THIS_SYS;
855 855 if (p4_htt && sibling_usr)
856 856 cfg->p4_flags |= P4_SIBLING_USR;
857 857 if (p4_htt && sibling_sys)
858 858 cfg->p4_flags |= P4_SIBLING_SYS;
859 859 } else {
860 860 /*
861 861 * This is not HyperThreaded, so we can determine the exact
862 862 * ESCR value necessary now.
863 863 */
864 864 if (flags & CPC_COUNT_USER)
865 865 cfg->p4_escr |= ESCR_USR;
866 866 if (flags & CPC_COUNT_SYSTEM)
867 867 cfg->p4_escr |= ESCR_OS;
868 868 }
869 869
870 870 cfg->p4_rawpic = preset & MASK40;
871 871
872 872 /*
873 873 * Even on non-HT P4s, Intel states the active_thread field (marked as
874 874 * "reserved" for the non-HT chips) must be set to all 1s.
875 875 */
876 876 cfg->p4_cccr = CCCR_INIT | (active_thread << CCCR_ACTV_THR_SHIFT);
877 877 if (compare)
878 878 cfg->p4_cccr |= CCCR_COMPARE;
879 879 if (complement)
880 880 cfg->p4_cccr |= CCCR_COMPLEMENT;
881 881 cfg->p4_cccr |= threshold << CCCR_THRESHOLD_SHIFT;
882 882 if (edge)
883 883 cfg->p4_cccr |= CCCR_EDGE;
884 884 cfg->p4_cccr |= p4_escrs[cfg->p4_escr_ndx].pe_num
885 885 << CCCR_ESCR_SEL_SHIFT;
886 886 if (flags & CPC_OVF_NOTIFY_EMT) {
887 887 if (p4_htt)
888 888 cfg->p4_flags |= P4_PMI;
889 889 else {
890 890 /*
891 891 * If the user has asked for notification of overflows,
892 892 * we automatically program the hardware to generate an
893 893 * interrupt on overflow.
894 894 *
895 895 * This can only be programmed now if this P4 doesn't
896 896 * have HyperThreading. If it does, we must wait until
897 897 * we know which logical CPU we'll be programming.
898 898 */
899 899 cfg->p4_cccr |= CCCR_OVF_PMI;
900 900 }
901 901 }
902 902
903 903 *data = cfg;
904 904
905 905 return (0);
906 906 }
907 907
908 908 static void
909 909 p4_pcbe_program(void *token)
910 910 {
911 911 int i;
912 912 uint64_t cccr;
913 913 p4_pcbe_config_t *cfgs[18];
914 914
915 915 p4_pcbe_allstop();
916 916
917 917 build_cfgs(cfgs, NULL, token);
918 918
919 919 if (p4_rdpmc_avail) {
920 920 ulong_t curcr4 = getcr4();
921 921 if (kcpc_allow_nonpriv(token))
922 922 setcr4(curcr4 | CR4_PCE);
923 923 else
924 924 setcr4(curcr4 & ~CR4_PCE);
925 925 }
926 926
927 927 /*
928 928 * Ideally we would start all counters with a single operation, but in
929 929 * P4 each counter is enabled individually via its CCCR. To minimize the
930 930 * probe effect of enabling the counters, we do it in two passes: the
931 931 * first programs the counter and ESCR, and the second programs the
932 932 * CCCR (and thus enables the counter).
933 933 */
934 934 if (p4_htt) {
935 935 int lid = cpuid_get_clogid(CPU); /* Logical ID of CPU */
936 936
937 937 for (i = 0; i < 18; i++) {
938 938 uint64_t escr;
939 939
940 940 if (cfgs[i] == NULL)
941 941 continue;
942 942 escr = (uint64_t)cfgs[i]->p4_escr;
943 943
944 944 if (cfgs[i]->p4_flags & P4_THIS_USR)
945 945 escr |= (lid == 0) ? ESCR_T0_USR : ESCR_T1_USR;
946 946 if (cfgs[i]->p4_flags & P4_THIS_SYS)
947 947 escr |= (lid == 0) ? ESCR_T0_OS : ESCR_T1_OS;
948 948 if (cfgs[i]->p4_flags & P4_SIBLING_USR)
949 949 escr |= (lid == 0) ? ESCR_T1_USR : ESCR_T0_USR;
950 950 if (cfgs[i]->p4_flags & P4_SIBLING_SYS)
951 951 escr |= (lid == 0) ? ESCR_T1_OS : ESCR_T0_OS;
952 952
953 953 wrmsr(p4_ctrs[i].pc_caddr, cfgs[i]->p4_rawpic);
954 954 wrmsr(p4_escrs[cfgs[i]->p4_escr_ndx].pe_addr, escr);
955 955 }
956 956
957 957 for (i = 0; i < 18; i++) {
958 958 if (cfgs[i] == NULL)
959 959 continue;
960 960 cccr = (uint64_t)cfgs[i]->p4_cccr;
961 961 /*
962 962 * We always target the overflow interrupt at the
963 963 * logical CPU which is doing the counting.
964 964 */
965 965 if (cfgs[i]->p4_flags & P4_PMI)
966 966 cccr |= (lid == 0) ?
967 967 CCCR_OVF_PMI_T0 : CCCR_OVF_PMI_T1;
968 968 wrmsr(p4_ctrs[i].pc_ctladdr, cccr);
969 969 }
970 970 } else {
971 971 for (i = 0; i < 18; i++) {
972 972 if (cfgs[i] == NULL)
973 973 continue;
974 974 wrmsr(p4_ctrs[i].pc_caddr, cfgs[i]->p4_rawpic);
975 975 wrmsr(p4_escrs[cfgs[i]->p4_escr_ndx].pe_addr,
976 976 (uint64_t)cfgs[i]->p4_escr);
977 977 }
978 978
979 979 for (i = 0; i < 18; i++) {
980 980 if (cfgs[i] == NULL)
981 981 continue;
982 982 wrmsr(p4_ctrs[i].pc_ctladdr,
983 983 (uint64_t)cfgs[i]->p4_cccr);
984 984 }
985 985 }
986 986 }
987 987
988 988 static void
989 989 p4_pcbe_allstop(void)
990 990 {
991 991 int i;
992 992
993 993 for (i = 0; i < 18; i++)
994 994 wrmsr(p4_ctrs[i].pc_ctladdr, 0ULL);
995 995
996 996 setcr4(getcr4() & ~CR4_PCE);
997 997 }
998 998
999 999
1000 1000 static void
1001 1001 p4_pcbe_sample(void *token)
1002 1002 {
1003 1003 p4_pcbe_config_t *cfgs[18];
1004 1004 uint64_t *addrs[18];
1005 1005 uint64_t curpic[18];
1006 1006 int64_t diff;
1007 1007 int i;
1008 1008
1009 1009 for (i = 0; i < 18; i++)
1010 1010 curpic[i] = rdmsr(p4_ctrs[i].pc_caddr);
1011 1011
1012 1012 build_cfgs(cfgs, addrs, token);
1013 1013
1014 1014 for (i = 0; i < 18; i++) {
1015 1015 if (cfgs[i] == NULL)
1016 1016 continue;
1017 1017 diff = curpic[i] - cfgs[i]->p4_rawpic;
1018 1018 if (diff < 0)
1019 1019 diff += (1ll << 40);
1020 1020 *addrs[i] += diff;
1021 1021 DTRACE_PROBE4(p4__pcbe__sample, int, i, uint64_t, *addrs[i],
1022 1022 uint64_t, curpic[i], uint64_t, cfgs[i]->p4_rawpic);
1023 1023 cfgs[i]->p4_rawpic = *addrs[i] & MASK40;
1024 1024 }
1025 1025 }
1026 1026
1027 1027 static void
1028 1028 p4_pcbe_free(void *config)
1029 1029 {
1030 1030 kmem_free(config, sizeof (p4_pcbe_config_t));
↓ open down ↓ |
1030 lines elided |
↑ open up ↑ |
1031 1031 }
1032 1032
1033 1033 static struct modlpcbe modlpcbe = {
1034 1034 &mod_pcbeops,
1035 1035 "Pentium 4 Performance Counters",
1036 1036 &p4_pcbe_ops
1037 1037 };
1038 1038
1039 1039 static struct modlinkage modl = {
1040 1040 MODREV_1,
1041 - &modlpcbe,
1041 + { &modlpcbe, NULL }
1042 1042 };
1043 1043
1044 1044 int
1045 1045 _init(void)
1046 1046 {
1047 1047 if (p4_pcbe_init() != 0)
1048 1048 return (ENOTSUP);
1049 1049 return (mod_install(&modl));
1050 1050 }
1051 1051
1052 1052 int
1053 1053 _fini(void)
1054 1054 {
1055 1055 return (mod_remove(&modl));
1056 1056 }
1057 1057
1058 1058 int
1059 1059 _info(struct modinfo *mi)
1060 1060 {
1061 1061 return (mod_info(&modl, mi));
1062 1062 }
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX