4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #define __EXTENSIONS__ /* header bug! strtok_r is overly hidden */
49 #define MAX_RHS_COLUMN 76
50 #define EVENT_MARGIN 17
51 #define ATTR_MARGIN 20
55 list_cap(void *arg
, uint_t regno
, const char *name
)
57 struct args
*args
= arg
;
60 if ((args
->colnum
+ strlen(name
) + 1) > MAX_RHS_COLUMN
) {
61 (void) fprintf(args
->fp
, "\n");
62 for (i
= 0; i
< args
->margin
; i
++)
63 (void) fprintf(args
->fp
, " ");
64 args
->colnum
= args
->margin
;
66 args
->colnum
+= fprintf(args
->fp
, "%s ", name
);
70 list_attr(void *arg
, const char *name
)
73 * The following attributes are used by the commands but should not be
74 * reported to the user, since they may not be specified directly.
76 if (strncmp(name
, "picnum", 7) == 0 ||
77 strncmp(name
, "count_sibling_usr", 18) == 0 ||
78 strncmp(name
, "count_sibling_sys", 18) == 0)
81 list_cap(arg
, 0, name
);
89 if ((ptr
= malloc(size
)) == NULL
) {
90 (void) fprintf(stderr
, gettext("no memory available\n"));
98 * Used by allpics_equal().
102 cap_walker(void *arg
, uint_t regno
, const char *name
)
104 struct evlist
*list
= arg
;
106 list
->size
+= strlen(name
);
107 if ((list
->list
= realloc(list
->list
, list
->size
+ 1)) == NULL
) {
108 (void) fprintf(stderr
, gettext("no memory available\n"));
112 (void) strcat(list
->list
, name
);
116 * Returns 1 if all counters on this chip can count all possible events.
119 allpics_equal(cpc_t
*cpc
)
121 int npics
= cpc_npic(cpc
);
123 struct evlist
**lists
;
126 lists
= emalloc(npics
* sizeof (struct evlist
*));
128 for (i
= 0; i
< npics
; i
++) {
129 lists
[i
] = emalloc(sizeof (struct evlist
));
131 lists
[i
]->list
= emalloc(1);
132 lists
[i
]->list
[0] = '\0';
133 cpc_walk_events_pic(cpc
, i
, lists
[i
], cap_walker
);
136 for (i
= 1; i
< npics
; i
++)
137 if (lists
[i
]->size
!= lists
[0]->size
||
138 strncmp(lists
[i
]->list
, lists
[0]->list
,
139 lists
[0]->size
) != 0) {
144 for (i
= 0; i
< npics
; i
++) {
145 free(lists
[i
]->list
);
154 capabilities(cpc_t
*cpc
, FILE *fp
)
156 struct args _args
, *args
= &_args
;
157 char *text
, *tok
, *cp
;
159 int npic
= cpc_npic(cpc
);
160 int i
, pics_equal
= allpics_equal(cpc
);
164 if ((ccp
= cpc_cciname(cpc
)) == NULL
)
165 ccp
= "No information available";
166 (void) fprintf(args
->fp
, "\t%s: %s\n\n",
167 gettext("CPU performance counter interface"), ccp
);
169 (void) fprintf(args
->fp
, gettext("\tevent specification syntax:\n"));
171 (void) fprintf(args
->fp
, "\t[picn=]<eventn>[,attr[n][=<val>]]"
172 "[,[picn=]<eventn>[,attr[n][=<val>]],...]\n");
174 (void) fprintf(args
->fp
, gettext("\n\tGeneric Events:\n"));
177 args
->margin
= args
->colnum
= EVENT_MARGIN
;
178 (void) fprintf(args
->fp
, "\n\tevent[0-%d]: ", npic
- 1);
179 cpc_walk_generic_events_pic(cpc
, 0, args
, list_cap
);
180 (void) fprintf(args
->fp
, "\n");
182 args
->margin
= EVENT_MARGIN
;
183 for (i
= 0; i
< npic
; i
++) {
184 (void) fprintf(args
->fp
, "\n\tevent%d: ", i
);
185 if (i
< 10) (void) fprintf(args
->fp
, " ");
186 args
->colnum
= EVENT_MARGIN
;
187 cpc_walk_generic_events_pic(cpc
, i
, args
, list_cap
);
188 (void) fprintf(args
->fp
, "\n");
192 (void) fprintf(args
->fp
, gettext("\n\tSee generic_events(3CPC) for"
193 " descriptions of these events\n\n"));
195 (void) fprintf(args
->fp
, gettext("\tPlatform Specific Events:\n"));
198 args
->margin
= args
->colnum
= EVENT_MARGIN
;
199 (void) fprintf(args
->fp
, "\n\tevent[0-%d]: ", npic
- 1);
200 cpc_walk_events_pic(cpc
, 0, args
, list_cap
);
201 (void) fprintf(args
->fp
, "\n");
203 args
->margin
= EVENT_MARGIN
;
204 for (i
= 0; i
< npic
; i
++) {
205 (void) fprintf(args
->fp
, "\n\tevent%d: ", i
);
206 if (i
< 10) (void) fprintf(args
->fp
, " ");
207 args
->colnum
= EVENT_MARGIN
;
208 cpc_walk_events_pic(cpc
, i
, args
, list_cap
);
209 (void) fprintf(args
->fp
, "\n");
213 (void) fprintf(args
->fp
, "\n\tattributes: ");
214 args
->colnum
= args
->margin
= ATTR_MARGIN
;
215 cpc_walk_attrs(cpc
, args
, list_attr
);
217 * In addition to the attributes published by the kernel, we allow the
218 * user to specify two additional tokens on all platforms. List them
221 list_cap(args
, 0, "nouser");
222 list_cap(args
, 0, "sys");
223 (void) fprintf(args
->fp
, "\n\n\t");
226 if ((ccp
= cpc_cpuref(cpc
)) == NULL
)
227 ccp
= "No information available";
228 if ((text
= strdup(ccp
)) == NULL
) {
229 (void) fprintf(stderr
, gettext("no memory available.\n"));
232 for (cp
= strtok_r(text
, " ", &tok
);
233 cp
!= NULL
; cp
= strtok_r(NULL
, " ", &tok
)) {
234 if ((args
->colnum
+ strlen(cp
) + 1) > MAX_RHS_COLUMN
) {
235 (void) fprintf(args
->fp
, "\n\t");
238 args
->colnum
+= fprintf(args
->fp
, "%s ", cp
);
240 (void) fprintf(args
->fp
, "\n");
247 * Returns 1 on SMT processors which do not have full CPC hardware for each
251 smt_limited_cpc_hw(cpc_t
*cpc
)
253 if (strcmp(cpc_cciname(cpc
), "Pentium 4 with HyperThreading") == 0)