0001
0002
0003
0004
0005
0006
0007 #include "util/cpumap.h"
0008 #include "util/debug.h"
0009 #include "util/event.h"
0010 #include "util/evlist.h"
0011 #include "util/evsel.h"
0012 #include "util/parse-events.h"
0013 #include "util/pmu.h"
0014 #include "util/pfm.h"
0015
0016 #include <string.h>
0017 #include <linux/kernel.h>
0018 #include <perfmon/pfmlib_perf_event.h>
0019
0020 static void libpfm_initialize(void)
0021 {
0022 int ret;
0023
0024 ret = pfm_initialize();
0025 if (ret != PFM_SUCCESS) {
0026 ui__warning("libpfm failed to initialize: %s\n",
0027 pfm_strerror(ret));
0028 }
0029 }
0030
0031 int parse_libpfm_events_option(const struct option *opt, const char *str,
0032 int unset __maybe_unused)
0033 {
0034 struct evlist *evlist = *(struct evlist **)opt->value;
0035 struct perf_event_attr attr;
0036 struct perf_pmu *pmu;
0037 struct evsel *evsel, *grp_leader = NULL;
0038 char *p, *q, *p_orig;
0039 const char *sep;
0040 int grp_evt = -1;
0041 int ret;
0042
0043 libpfm_initialize();
0044
0045 p_orig = p = strdup(str);
0046 if (!p)
0047 return -1;
0048
0049
0050
0051 perf_pmu__scan(NULL);
0052
0053 for (q = p; strsep(&p, ",{}"); q = p) {
0054 sep = p ? str + (p - p_orig - 1) : "";
0055 if (*sep == '{') {
0056 if (grp_evt > -1) {
0057 ui__error(
0058 "nested event groups not supported\n");
0059 goto error;
0060 }
0061 grp_evt++;
0062 }
0063
0064
0065 if (*q == '\0') {
0066 if (*sep == '}') {
0067 if (grp_evt < 0) {
0068 ui__error("cannot close a non-existing event group\n");
0069 goto error;
0070 }
0071 grp_evt--;
0072 }
0073 continue;
0074 }
0075
0076 memset(&attr, 0, sizeof(attr));
0077 event_attr_init(&attr);
0078
0079 ret = pfm_get_perf_event_encoding(q, PFM_PLM0|PFM_PLM3,
0080 &attr, NULL, NULL);
0081
0082 if (ret != PFM_SUCCESS) {
0083 ui__error("failed to parse event %s : %s\n", str,
0084 pfm_strerror(ret));
0085 goto error;
0086 }
0087
0088 pmu = perf_pmu__find_by_type((unsigned int)attr.type);
0089 evsel = parse_events__add_event(evlist->core.nr_entries,
0090 &attr, q, NULL,
0091 pmu);
0092 if (evsel == NULL)
0093 goto error;
0094
0095 evsel->is_libpfm_event = true;
0096
0097 evlist__add(evlist, evsel);
0098
0099 if (grp_evt == 0)
0100 grp_leader = evsel;
0101
0102 if (grp_evt > -1) {
0103 evsel__set_leader(evsel, grp_leader);
0104 grp_leader->core.nr_members++;
0105 grp_evt++;
0106 }
0107
0108 if (*sep == '}') {
0109 if (grp_evt < 0) {
0110 ui__error(
0111 "cannot close a non-existing event group\n");
0112 goto error;
0113 }
0114 evlist->core.nr_groups++;
0115 grp_leader = NULL;
0116 grp_evt = -1;
0117 }
0118 }
0119 free(p_orig);
0120 return 0;
0121 error:
0122 free(p_orig);
0123 return -1;
0124 }
0125
0126 static const char *srcs[PFM_ATTR_CTRL_MAX] = {
0127 [PFM_ATTR_CTRL_UNKNOWN] = "???",
0128 [PFM_ATTR_CTRL_PMU] = "PMU",
0129 [PFM_ATTR_CTRL_PERF_EVENT] = "perf_event",
0130 };
0131
0132 static void
0133 print_attr_flags(pfm_event_attr_info_t *info)
0134 {
0135 int n = 0;
0136
0137 if (info->is_dfl) {
0138 printf("[default] ");
0139 n++;
0140 }
0141
0142 if (info->is_precise) {
0143 printf("[precise] ");
0144 n++;
0145 }
0146
0147 if (!n)
0148 printf("- ");
0149 }
0150
0151 static void
0152 print_libpfm_events_detailed(pfm_event_info_t *info, bool long_desc)
0153 {
0154 pfm_event_attr_info_t ainfo;
0155 const char *src;
0156 int j, ret;
0157
0158 ainfo.size = sizeof(ainfo);
0159
0160 printf(" %s\n", info->name);
0161 printf(" [%s]\n", info->desc);
0162 if (long_desc) {
0163 if (info->equiv)
0164 printf(" Equiv: %s\n", info->equiv);
0165
0166 printf(" Code : 0x%"PRIx64"\n", info->code);
0167 }
0168 pfm_for_each_event_attr(j, info) {
0169 ret = pfm_get_event_attr_info(info->idx, j,
0170 PFM_OS_PERF_EVENT_EXT, &ainfo);
0171 if (ret != PFM_SUCCESS)
0172 continue;
0173
0174 if (ainfo.type == PFM_ATTR_UMASK) {
0175 printf(" %s:%s\n", info->name, ainfo.name);
0176 printf(" [%s]\n", ainfo.desc);
0177 }
0178
0179 if (!long_desc)
0180 continue;
0181
0182 if (ainfo.ctrl >= PFM_ATTR_CTRL_MAX)
0183 ainfo.ctrl = PFM_ATTR_CTRL_UNKNOWN;
0184
0185 src = srcs[ainfo.ctrl];
0186 switch (ainfo.type) {
0187 case PFM_ATTR_UMASK:
0188 printf(" Umask : 0x%02"PRIx64" : %s: ",
0189 ainfo.code, src);
0190 print_attr_flags(&ainfo);
0191 putchar('\n');
0192 break;
0193 case PFM_ATTR_MOD_BOOL:
0194 printf(" Modif : %s: [%s] : %s (boolean)\n", src,
0195 ainfo.name, ainfo.desc);
0196 break;
0197 case PFM_ATTR_MOD_INTEGER:
0198 printf(" Modif : %s: [%s] : %s (integer)\n", src,
0199 ainfo.name, ainfo.desc);
0200 break;
0201 case PFM_ATTR_NONE:
0202 case PFM_ATTR_RAW_UMASK:
0203 case PFM_ATTR_MAX:
0204 default:
0205 printf(" Attr : %s: [%s] : %s\n", src,
0206 ainfo.name, ainfo.desc);
0207 }
0208 }
0209 }
0210
0211
0212
0213
0214
0215 static void
0216 print_libpfm_events_raw(pfm_pmu_info_t *pinfo, pfm_event_info_t *info)
0217 {
0218 pfm_event_attr_info_t ainfo;
0219 int j, ret;
0220 bool has_umask = false;
0221
0222 ainfo.size = sizeof(ainfo);
0223
0224 pfm_for_each_event_attr(j, info) {
0225 ret = pfm_get_event_attr_info(info->idx, j,
0226 PFM_OS_PERF_EVENT_EXT, &ainfo);
0227 if (ret != PFM_SUCCESS)
0228 continue;
0229
0230 if (ainfo.type != PFM_ATTR_UMASK)
0231 continue;
0232
0233 printf("%s::%s:%s\n", pinfo->name, info->name, ainfo.name);
0234 has_umask = true;
0235 }
0236 if (!has_umask)
0237 printf("%s::%s\n", pinfo->name, info->name);
0238 }
0239
0240 void print_libpfm_events(bool name_only, bool long_desc)
0241 {
0242 pfm_event_info_t info;
0243 pfm_pmu_info_t pinfo;
0244 int i, p, ret;
0245
0246 libpfm_initialize();
0247
0248
0249 info.size = sizeof(info);
0250 pinfo.size = sizeof(pinfo);
0251
0252 if (!name_only)
0253 puts("\nList of pre-defined events (to be used in --pfm-events):\n");
0254
0255 pfm_for_all_pmus(p) {
0256 bool printed_pmu = false;
0257
0258 ret = pfm_get_pmu_info(p, &pinfo);
0259 if (ret != PFM_SUCCESS)
0260 continue;
0261
0262
0263 if (!pinfo.is_present)
0264 continue;
0265
0266
0267 if (pinfo.pmu == PFM_PMU_PERF_EVENT)
0268 continue;
0269
0270 for (i = pinfo.first_event; i != -1;
0271 i = pfm_get_event_next(i)) {
0272
0273 ret = pfm_get_event_info(i, PFM_OS_PERF_EVENT_EXT,
0274 &info);
0275 if (ret != PFM_SUCCESS)
0276 continue;
0277
0278 if (!name_only && !printed_pmu) {
0279 printf("%s:\n", pinfo.name);
0280 printed_pmu = true;
0281 }
0282
0283 if (!name_only)
0284 print_libpfm_events_detailed(&info, long_desc);
0285 else
0286 print_libpfm_events_raw(&pinfo, &info);
0287 }
0288 if (!name_only && printed_pmu)
0289 putchar('\n');
0290 }
0291 }