4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
35 #include <libdevinfo.h>
38 #include "libcpc_impl.h"
41 * Configuration data for UltraSPARC performance counters.
43 * Definitions taken from [1], [2], [3] [4] and [5]. See the references to
44 * understand what any of these settings actually means.
46 * Note that in the current draft of [2], there is some re-use
47 * of existing bit assignments in the various fields of the %pcr
48 * register - this may change before FCS.
50 * The following are the Internal Documents. Customers need to be
51 * told about the Public docs in cpc_getcpuref().
52 * [1] "UltraSPARC I & II User's Manual," January 1997.
53 * [2] "UltraSPARC-III Programmer's Reference Manual," April 1999.
54 * [3] "Cheetah+ Programmer's Reference Manual," November 2000.
55 * [4] "UltraSPARC-IIIi Programmer's Reference Manual," November 2000.
56 * [5] "UltraSPARC-IV+ Programmer's Reference Manual," October 2004.
59 #define V_US12 (1u << 0) /* specific to UltraSPARC 1 and 2 */
60 #define V_US3 (1u << 1) /* specific to UltraSPARC 3 */
61 #define V_US3_PLUS (1u << 2) /* specific to UltraSPARC 3 PLUS */
62 #define V_US3_I (1u << 3) /* specific to UltraSPARC-IIIi */
63 #define V_US4_PLUS (1u << 4) /* specific to UltraSPARC-IV+ */
64 #define V_END (1u << 31)
67 * map from "cpu version" to flag bits
69 static const uint_t cpuvermap
[] = {
70 V_US12
, /* CPC_ULTRA1 */
71 V_US12
, /* CPC_ULTRA2 */
72 V_US3
, /* CPC_ULTRA3 */
73 V_US3_PLUS
, /* CPC_ULTRA3_PLUS */
74 V_US3_I
, /* CPC_ULTRA3I */
75 V_US4_PLUS
/* CPC_ULTRA4_PLUS */
85 * Definitions for counter 0
88 #define USall_EVENTS_0(v) \
89 {v, 0x0, "Cycle_cnt"}, \
90 {v, 0x1, "Instr_cnt"}, \
91 {v, 0x2, "Dispatch0_IC_miss"}, \
96 {v, 0xe, "EC_snoop_inv"}
98 static const struct nametable US12_names0
[] = {
99 USall_EVENTS_0(V_US12
),
100 {V_US12
, 0x3, "Dispatch0_storeBuf"},
101 {V_US12
, 0xb, "Load_use"},
102 {V_US12
, 0xd, "EC_write_hit_RDO"},
103 {V_US12
, 0xf, "EC_rd_hit"},
107 #define US3all_EVENTS_0(v) \
108 {v, 0x3, "Dispatch0_br_target"}, \
109 {v, 0x4, "Dispatch0_2nd_br"}, \
110 {v, 0x5, "Rstall_storeQ"}, \
111 {v, 0x6, "Rstall_IU_use"}, \
112 {v, 0xd, "EC_write_hit_RTO"}, \
113 {v, 0xf, "EC_rd_miss"}, \
114 {v, 0x10, "PC_port0_rd"}, \
115 {v, 0x11, "SI_snoop"}, \
116 {v, 0x12, "SI_ciq_flow"}, \
117 {v, 0x13, "SI_owned"}, \
118 {v, 0x14, "SW_count_0"}, \
119 {v, 0x15, "IU_Stat_Br_miss_taken"}, \
120 {v, 0x16, "IU_Stat_Br_count_taken"}, \
121 {v, 0x17, "Dispatch_rs_mispred"}, \
122 {v, 0x18, "FA_pipe_completion"}
124 #define US3_MC_EVENTS_0(v) \
125 {v, 0x20, "MC_reads_0"}, \
126 {v, 0x21, "MC_reads_1"}, \
127 {v, 0x22, "MC_reads_2"}, \
128 {v, 0x23, "MC_reads_3"}, \
129 {v, 0x24, "MC_stalls_0"}, \
130 {v, 0x25, "MC_stalls_2"}
132 #define US3_I_MC_EVENTS_0(v) \
133 {v, 0x20, "MC_read_dispatched"}, \
134 {v, 0x21, "MC_write_dispatched"}, \
135 {v, 0x22, "MC_read_returned_to_JBU"}, \
136 {v, 0x23, "MC_msl_busy_stall"}, \
137 {v, 0x24, "MC_mdb_overflow_stall"}, \
138 {v, 0x25, "MC_miu_spec_request"}
140 static const struct nametable US3_names0
[] = {
141 USall_EVENTS_0(V_US3
),
142 US3all_EVENTS_0(V_US3
),
143 US3_MC_EVENTS_0(V_US3
),
147 static const struct nametable US4_PLUS_names0
[] = {
148 {V_US4_PLUS
, 0x0, "Cycle_cnt"},
149 {V_US4_PLUS
, 0x1, "Instr_cnt"},
150 {V_US4_PLUS
, 0x2, "Dispatch0_IC_miss"},
151 {V_US4_PLUS
, 0x3, "IU_stat_jmp_correct_pred"},
152 {V_US4_PLUS
, 0x4, "Dispatch0_2nd_br"},
153 {V_US4_PLUS
, 0x5, "Rstall_storeQ"},
154 {V_US4_PLUS
, 0x6, "Rstall_IU_use"},
155 {V_US4_PLUS
, 0x7, "IU_stat_ret_correct_pred"},
156 {V_US4_PLUS
, 0x8, "IC_ref"},
157 {V_US4_PLUS
, 0x9, "DC_rd"},
158 {V_US4_PLUS
, 0xa, "Rstall_FP_use"},
159 {V_US4_PLUS
, 0xb, "SW_pf_instr"},
160 {V_US4_PLUS
, 0xc, "L2_ref"},
161 {V_US4_PLUS
, 0xd, "L2_write_hit_RTO"},
162 {V_US4_PLUS
, 0xe, "L2_snoop_inv_sh"},
163 {V_US4_PLUS
, 0xf, "L2_rd_miss"},
164 {V_US4_PLUS
, 0x10, "PC_rd"},
165 {V_US4_PLUS
, 0x11, "SI_snoop_sh"},
166 {V_US4_PLUS
, 0x12, "SI_ciq_flow_sh"},
167 {V_US4_PLUS
, 0x13, "Re_DC_miss"},
168 {V_US4_PLUS
, 0x14, "SW_count_NOP"},
169 {V_US4_PLUS
, 0x15, "IU_stat_br_miss_taken"},
170 {V_US4_PLUS
, 0x16, "IU_stat_br_count_untaken"},
171 {V_US4_PLUS
, 0x17, "HW_pf_exec"},
172 {V_US4_PLUS
, 0x18, "FA_pipe_completion"},
173 {V_US4_PLUS
, 0x19, "SSM_L3_wb_remote"},
174 {V_US4_PLUS
, 0x1a, "SSM_L3_miss_local"},
175 {V_US4_PLUS
, 0x1b, "SSM_L3_miss_mtag_remote"},
176 {V_US4_PLUS
, 0x1c, "SW_pf_str_trapped"},
177 {V_US4_PLUS
, 0x1d, "SW_pf_PC_installed"},
178 {V_US4_PLUS
, 0x1e, "IPB_to_IC_fill"},
179 {V_US4_PLUS
, 0x1f, "L2_write_miss"},
180 {V_US4_PLUS
, 0x20, "MC_reads_0_sh"},
181 {V_US4_PLUS
, 0x21, "MC_reads_1_sh"},
182 {V_US4_PLUS
, 0x22, "MC_reads_2_sh"},
183 {V_US4_PLUS
, 0x23, "MC_reads_3_sh"},
184 {V_US4_PLUS
, 0x24, "MC_stalls_0_sh"},
185 {V_US4_PLUS
, 0x25, "MC_stalls_2_sh"},
186 {V_US4_PLUS
, 0x26, "L2_hit_other_half"},
187 {V_US4_PLUS
, 0x28, "L3_rd_miss"},
188 {V_US4_PLUS
, 0x29, "Re_L2_miss"},
189 {V_US4_PLUS
, 0x2a, "IC_miss_cancelled"},
190 {V_US4_PLUS
, 0x2b, "DC_wr_miss"},
191 {V_US4_PLUS
, 0x2c, "L3_hit_I_state_sh"},
192 {V_US4_PLUS
, 0x2d, "SI_RTS_src_data"},
193 {V_US4_PLUS
, 0x2e, "L2_IC_miss"},
194 {V_US4_PLUS
, 0x2f, "SSM_new_transaction_sh"},
195 {V_US4_PLUS
, 0x30, "L2_SW_pf_miss"},
196 {V_US4_PLUS
, 0x31, "L2_wb"},
197 {V_US4_PLUS
, 0x32, "L2_wb_sh"},
198 {V_US4_PLUS
, 0x33, "L2_snoop_cb_sh"},
202 static const struct nametable US3_PLUS_names0
[] = {
203 USall_EVENTS_0(V_US3_PLUS
),
204 US3all_EVENTS_0(V_US3_PLUS
),
205 US3_MC_EVENTS_0(V_US3_PLUS
),
206 {V_US3_PLUS
, 0x19, "EC_wb_remote"},
207 {V_US3_PLUS
, 0x1a, "EC_miss_local"},
208 {V_US3_PLUS
, 0x1b, "EC_miss_mtag_remote"},
212 static const struct nametable US3_I_names0
[] = {
213 USall_EVENTS_0(V_US3_I
),
214 US3all_EVENTS_0(V_US3_I
),
215 US3_I_MC_EVENTS_0(V_US3_I
),
216 {V_US3_PLUS
, 0x19, "EC_wb_remote"},
217 {V_US3_PLUS
, 0x1a, "EC_miss_local"},
218 {V_US3_PLUS
, 0x1b, "EC_miss_mtag_remote"},
222 #undef USall_EVENTS_0
223 #undef US3all_EVENTS_0
225 #define USall_EVENTS_1(v) \
226 {v, 0x0, "Cycle_cnt"}, \
227 {v, 0x1, "Instr_cnt"}, \
228 {v, 0x2, "Dispatch0_mispred"}, \
230 {v, 0xe, "EC_snoop_cb"}
232 static const struct nametable US12_names1
[] = {
233 USall_EVENTS_1(V_US12
),
234 {V_US12
, 0x3, "Dispatch0_FP_use"},
235 {V_US12
, 0x8, "IC_hit"},
236 {V_US12
, 0x9, "DC_rd_hit"},
237 {V_US12
, 0xa, "DC_wr_hit"},
238 {V_US12
, 0xb, "Load_use_RAW"},
239 {V_US12
, 0xc, "EC_hit"},
240 {V_US12
, 0xf, "EC_ic_hit"},
244 #define US3all_EVENTS_1(v) \
245 {v, 0x3, "IC_miss_cancelled"}, \
246 {v, 0x5, "Re_FPU_bypass"}, \
247 {v, 0x6, "Re_DC_miss"}, \
248 {v, 0x7, "Re_EC_miss"}, \
249 {v, 0x8, "IC_miss"}, \
250 {v, 0x9, "DC_rd_miss"}, \
251 {v, 0xa, "DC_wr_miss"}, \
252 {v, 0xb, "Rstall_FP_use"}, \
253 {v, 0xc, "EC_misses"}, \
254 {v, 0xf, "EC_ic_miss"}, \
255 {v, 0x10, "Re_PC_miss"}, \
256 {v, 0x11, "ITLB_miss"}, \
257 {v, 0x12, "DTLB_miss"}, \
258 {v, 0x13, "WC_miss"}, \
259 {v, 0x14, "WC_snoop_cb"}, \
260 {v, 0x15, "WC_scrubbed"}, \
261 {v, 0x16, "WC_wb_wo_read"}, \
262 {v, 0x18, "PC_soft_hit"}, \
263 {v, 0x19, "PC_snoop_inv"}, \
264 {v, 0x1a, "PC_hard_hit"}, \
265 {v, 0x1b, "PC_port1_rd"}, \
266 {v, 0x1c, "SW_count_1"}, \
267 {v, 0x1d, "IU_Stat_Br_miss_untaken"}, \
268 {v, 0x1e, "IU_Stat_Br_count_untaken"}, \
269 {v, 0x1f, "PC_MS_misses"}, \
270 {v, 0x26, "Re_RAW_miss"}, \
271 {v, 0x27, "FM_pipe_completion"}
273 #define US3_MC_EVENTS_1(v) \
274 {v, 0x20, "MC_writes_0"}, \
275 {v, 0x21, "MC_writes_1"}, \
276 {v, 0x22, "MC_writes_2"}, \
277 {v, 0x23, "MC_writes_3"}, \
278 {v, 0x24, "MC_stalls_1"}, \
279 {v, 0x25, "MC_stalls_3"}
281 #define US3_I_MC_EVENTS_1(v) \
282 {v, 0x20, "MC_open_bank_cmds"}, \
283 {v, 0x21, "MC_reads"}, \
284 {v, 0x22, "MC_writes"}, \
285 {v, 0x23, "MC_page_close_stall"}
287 static const struct nametable US3_names1
[] = {
288 USall_EVENTS_1(V_US3
),
289 US3all_EVENTS_1(V_US3
),
290 US3_MC_EVENTS_1(V_US3
),
291 {V_US3
, 0x4, "Re_endian_miss"},
295 static const struct nametable US3_PLUS_names1
[] = {
296 USall_EVENTS_1(V_US3_PLUS
),
297 US3all_EVENTS_1(V_US3_PLUS
),
298 US3_MC_EVENTS_1(V_US3_PLUS
),
299 {V_US3_PLUS
, 0x4, "Re_DC_missovhd"},
300 {V_US3_PLUS
, 0x28, "EC_miss_mtag_remote"},
301 {V_US3_PLUS
, 0x29, "EC_miss_remote"},
305 static const struct nametable US3_I_names1
[] = {
306 USall_EVENTS_1(V_US3_I
),
307 US3all_EVENTS_1(V_US3_I
),
308 US3_I_MC_EVENTS_1(V_US3_I
),
309 {V_US3_I
, 0x4, "Re_DC_missovhd"},
313 static const struct nametable US4_PLUS_names1
[] = {
314 {V_US4_PLUS
, 0x0, "Cycle_cnt"},
315 {V_US4_PLUS
, 0x1, "Instr_cnt"},
316 {V_US4_PLUS
, 0x2, "Dispatch0_other"},
317 {V_US4_PLUS
, 0x3, "DC_wr"},
318 {V_US4_PLUS
, 0x4, "Re_DC_missovhd"},
319 {V_US4_PLUS
, 0x5, "Re_FPU_bypass"},
320 {V_US4_PLUS
, 0x6, "L3_write_hit_RTO"},
321 {V_US4_PLUS
, 0x7, "L2L3_snoop_inv_sh"},
322 {V_US4_PLUS
, 0x8, "IC_L2_req"},
323 {V_US4_PLUS
, 0x9, "DC_rd_miss"},
324 {V_US4_PLUS
, 0xa, "L2_hit_I_state_sh"},
325 {V_US4_PLUS
, 0xb, "L3_write_miss_RTO"},
326 {V_US4_PLUS
, 0xc, "L2_miss"},
327 {V_US4_PLUS
, 0xd, "SI_owned_sh"},
328 {V_US4_PLUS
, 0xe, "SI_RTO_src_data"},
329 {V_US4_PLUS
, 0xf, "SW_pf_duplicate"},
330 {V_US4_PLUS
, 0x10, "IU_stat_jmp_mispred"},
331 {V_US4_PLUS
, 0x11, "ITLB_miss"},
332 {V_US4_PLUS
, 0x12, "DTLB_miss"},
333 {V_US4_PLUS
, 0x13, "WC_miss"},
334 {V_US4_PLUS
, 0x14, "IC_fill"},
335 {V_US4_PLUS
, 0x15, "IU_stat_ret_mispred"},
336 {V_US4_PLUS
, 0x16, "Re_L3_miss"},
337 {V_US4_PLUS
, 0x17, "Re_PFQ_full"},
338 {V_US4_PLUS
, 0x18, "PC_soft_hit"},
339 {V_US4_PLUS
, 0x19, "PC_inv"},
340 {V_US4_PLUS
, 0x1a, "PC_hard_hit"},
341 {V_US4_PLUS
, 0x1b, "IC_pf"},
342 {V_US4_PLUS
, 0x1c, "SW_count_NOP"},
343 {V_US4_PLUS
, 0x1d, "IU_stat_br_miss_untaken"},
344 {V_US4_PLUS
, 0x1e, "IU_stat_br_count_taken"},
345 {V_US4_PLUS
, 0x1f, "PC_miss"},
346 {V_US4_PLUS
, 0x20, "MC_writes_0_sh"},
347 {V_US4_PLUS
, 0x21, "MC_writes_1_sh"},
348 {V_US4_PLUS
, 0x22, "MC_writes_2_sh"},
349 {V_US4_PLUS
, 0x23, "MC_writes_3_sh"},
350 {V_US4_PLUS
, 0x24, "MC_stalls_1_sh"},
351 {V_US4_PLUS
, 0x25, "MC_stalls_3_sh"},
352 {V_US4_PLUS
, 0x26, "Re_RAW_miss"},
353 {V_US4_PLUS
, 0x27, "FM_pipe_completion"},
354 {V_US4_PLUS
, 0x28, "SSM_L3_miss_mtag_remote"},
355 {V_US4_PLUS
, 0x29, "SSM_L3_miss_remote"},
356 {V_US4_PLUS
, 0x2a, "SW_pf_exec"},
357 {V_US4_PLUS
, 0x2b, "SW_pf_str_exec"},
358 {V_US4_PLUS
, 0x2c, "SW_pf_dropped"},
359 {V_US4_PLUS
, 0x2d, "SW_pf_L2_installed"},
360 {V_US4_PLUS
, 0x2f, "L2_HW_pf_miss"},
361 {V_US4_PLUS
, 0x31, "L3_miss"},
362 {V_US4_PLUS
, 0x32, "L3_IC_miss"},
363 {V_US4_PLUS
, 0x33, "L3_SW_pf_miss"},
364 {V_US4_PLUS
, 0x34, "L3_hit_other_half"},
365 {V_US4_PLUS
, 0x35, "L3_wb"},
366 {V_US4_PLUS
, 0x36, "L3_wb_sh"},
367 {V_US4_PLUS
, 0x37, "L2L3_snoop_cb_sh"},
371 #undef USall_EVENTS_1
372 #undef US3all_EVENTS_1
374 static const struct nametable
*US12_names
[2] = {
379 static const struct nametable
*US3_names
[2] = {
384 static const struct nametable
*US3_PLUS_names
[2] = {
389 static const struct nametable
*US3_I_names
[2] = {
394 static const struct nametable
*US4_PLUS_names
[2] = {
399 #define MAPCPUVER(cpuver) (cpuvermap[(cpuver) - CPC_ULTRA1])
402 validargs(int cpuver
, int regno
)
404 if (regno
< 0 || regno
> 1)
406 cpuver
-= CPC_ULTRA1
;
408 cpuver
>= sizeof (cpuvermap
) / sizeof (cpuvermap
[0]))
415 versionmatch(int cpuver
, int regno
, const struct nametable
*n
)
417 if (!validargs(cpuver
, regno
) || n
->ver
!= MAPCPUVER(cpuver
))
422 static const struct nametable
*
423 getnametable(int cpuver
, int regno
)
425 const struct nametable
*n
;
427 if (!validargs(cpuver
, regno
))
430 switch (MAPCPUVER(cpuver
)) {
432 n
= US12_names
[regno
];
435 n
= US3_names
[regno
];
438 n
= US3_PLUS_names
[regno
];
441 n
= US3_I_names
[regno
];
444 n
= US4_PLUS_names
[regno
];
454 cpc_walk_names(int cpuver
, int regno
, void *arg
,
455 void (*action
)(void *, int, const char *, uint8_t))
457 const struct nametable
*n
;
459 if ((n
= getnametable(cpuver
, regno
)) == NULL
)
461 for (; n
->ver
!= V_END
; n
++)
462 if (versionmatch(cpuver
, regno
, n
))
463 action(arg
, regno
, n
->name
, n
->bits
);
467 __cpc_reg_to_name(int cpuver
, int regno
, uint8_t bits
)
469 const struct nametable
*n
;
471 if ((n
= getnametable(cpuver
, regno
)) == NULL
)
473 for (; n
->ver
!= V_END
; n
++)
474 if (bits
== n
->bits
&& versionmatch(cpuver
, regno
, n
))
480 * Register names can be specified as strings or even as numbers
483 __cpc_name_to_reg(int cpuver
, int regno
, const char *name
, uint8_t *bits
)
485 const struct nametable
*n
;
489 if ((n
= getnametable(cpuver
, regno
)) == NULL
|| name
== NULL
)
492 for (; n
->ver
!= V_END
; n
++)
493 if (strcmp(name
, n
->name
) == 0 &&
494 versionmatch(cpuver
, regno
, n
)) {
499 value
= strtol(name
, &eptr
, 0);
500 if (name
!= eptr
&& value
>= 0 && value
<= UINT8_MAX
) {
501 *bits
= (uint8_t)value
;
509 cpc_getcciname(int cpuver
)
511 if (validargs(cpuver
, 0))
512 switch (MAPCPUVER(cpuver
)) {
514 return ("UltraSPARC I&II");
516 return ("UltraSPARC III");
518 return ("UltraSPARC III+ & IV");
520 return ("UltraSPARC IIIi & IIIi+");
522 return ("UltraSPARC IV+");
529 #define CPU_REF_URL " Documentation for Sun processors can be found at: " \
530 "http://www.sun.com/processors/manuals"
533 cpc_getcpuref(int cpuver
)
535 if (validargs(cpuver
, 0))
536 switch (MAPCPUVER(cpuver
)) {
539 "See the \"UltraSPARC I/II User\'s Manual\" "
540 "(Part No. 802-7220-02) "
541 "for descriptions of these events." CPU_REF_URL
));
545 "See the \"UltraSPARC III Cu User's Manual\" "
546 "for descriptions of these events." CPU_REF_URL
));
549 "See the \"UltraSPARC IIIi User's Manual\" "
550 "for descriptions of these events." CPU_REF_URL
));
553 "See the \"UltraSPARC IV User's Manual"
555 "for descriptions of these events." CPU_REF_URL
));
563 * This is a functional interface to allow CPUs with fewer %pic registers
564 * to share the same data structure as those with more %pic registers
565 * within the same instruction family.
568 cpc_getnpic(int cpuver
)
577 case CPC_ULTRA3_PLUS
:
579 case CPC_ULTRA4_PLUS
:
580 return (sizeof (event
->ce_pic
) / sizeof (event
->ce_pic
[0]));
587 * Compares the given string against the list of all known CPU node names, and
588 * returns the CPC CPU version code if there is a match. If there is no match,
594 if (strcmp(node
, "SUNW,UltraSPARC") == 0 ||
595 strcmp(node
, "SUNW,UltraSPARC-II") == 0 ||
596 strcmp(node
, "SUNW,UltraSPARC-IIi") == 0 ||
597 strcmp(node
, "SUNW,UltraSPARC-IIe") == 0) {
599 } else if (strcmp(node
, "SUNW,UltraSPARC-III") == 0)
601 else if (strcmp(node
, "SUNW,UltraSPARC-III+") == 0 ||
602 strcmp(node
, "SUNW,UltraSPARC-IV") == 0)
603 return (CPC_ULTRA3_PLUS
);
604 else if (strcmp(node
, "SUNW,UltraSPARC-IIIi") == 0 ||
605 strcmp(node
, "SUNW,UltraSPARC-IIIi+") == 0)
606 return (CPC_ULTRA3_I
);
607 else if (strcmp(node
, "SUNW,UltraSPARC-IV+") == 0)
608 return (CPC_ULTRA4_PLUS
);
614 cpc_get_cpu_ver(di_node_t di_node
, void *arg
)
616 char *node_name
, *compatible_array
;
617 int n_names
, i
, found
= 0;
620 node_name
= di_node_name(di_node
);
621 if (node_name
!= NULL
) {
622 if ((*ver
= node2ver(node_name
)) != -1)
624 else if (strncmp(node_name
, "cpu", 4) == 0) {
626 * CPU nodes associated with CMP use the generic name
627 * of "cpu". We must look at the compatible property
628 * in order to find the implementation specific name.
630 if ((n_names
= di_compatible_names(di_node
,
631 &compatible_array
)) > 0) {
632 for (i
= 0; i
< n_names
; i
++) {
633 if ((*ver
= node2ver(compatible_array
))
639 strlen(compatible_array
) + 1;
646 return (DI_WALK_CONTINUE
);
648 return (DI_WALK_TERMINATE
);
652 * Return the version of the current processor.
654 * Version -1 is defined as 'not performance counter capable'
656 * XXX A better solution would be to use the di_prom_props for the cpu
657 * devinfo nodes. That way we could look at the 'device-type', 'sparc-version'
658 * and 'implementation#' properties in order to determine which version of
659 * UltraSPARC we are running on.
661 * The problem with this is that di_prom_init() requires root access to
662 * open /dev/openprom and cputrack is not a root-only application so
663 * we have to settle for the di_props that we can see as non-root users.
671 di_node_t di_root_node
;
673 if ((di_root_node
= di_init("/", DINFOCPYALL
)) == DI_NODE_NIL
)
676 (void) di_walk_node(di_root_node
, DI_WALK_CLDFIRST
,
677 (void *)&ver
, cpc_get_cpu_ver
);
679 di_fini(di_root_node
);