aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/libpmc/libpmc.c9
-rw-r--r--lib/libpmc/pmclog.c27
2 files changed, 29 insertions, 7 deletions
diff --git a/lib/libpmc/libpmc.c b/lib/libpmc/libpmc.c
index 57b9c90de256..003d9615a44a 100644
--- a/lib/libpmc/libpmc.c
+++ b/lib/libpmc/libpmc.c
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
#include <sys/pmc.h>
#include <sys/syscall.h>
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <err.h>
@@ -1084,8 +1085,14 @@ pmc_allocate(const char *ctrspec, enum pmc_mode mode,
r = spec_copy = strdup(ctrspec);
ctrname = strsep(&r, ",");
if (pmc_pmu_enabled()) {
- if (pmc_pmu_pmcallocate(ctrname, &pmc_config) == 0)
+ if (pmc_pmu_pmcallocate(ctrname, &pmc_config) == 0) {
+ /*
+ * XXX: pmclog_get_event exploits this to disambiguate
+ * PMU from PMC event codes in PMCALLOCATE events.
+ */
+ assert(pmc_config.pm_ev < PMC_EVENT_FIRST);
goto found;
+ }
/* Otherwise, reset any changes */
pmc_config.pm_ev = 0;
diff --git a/lib/libpmc/pmclog.c b/lib/libpmc/pmclog.c
index 0db91cf51bc2..92bcb1c2b161 100644
--- a/lib/libpmc/pmclog.c
+++ b/lib/libpmc/pmclog.c
@@ -356,12 +356,27 @@ pmclog_get_event(void *cookie, char **data, ssize_t *len,
PMCLOG_READ32(le,ev->pl_u.pl_a.pl_flags);
PMCLOG_READ32(le,noop);
PMCLOG_READ64(le,ev->pl_u.pl_a.pl_rate);
- ev->pl_u.pl_a.pl_evname = pmc_pmu_event_get_by_idx(ps->ps_cpuid, ev->pl_u.pl_a.pl_event);
- if (ev->pl_u.pl_a.pl_evname != NULL)
- break;
- else if ((ev->pl_u.pl_a.pl_evname =
- _pmc_name_of_event(ev->pl_u.pl_a.pl_event, ps->ps_arch))
- == NULL) {
+
+ /*
+ * Could be either a PMC event code or a PMU event index;
+ * assume that their encodings don't overlap (i.e. no PMU event
+ * table is more than 0x1000 entries) to distinguish them here.
+ * Otherwise pmc_pmu_event_get_by_idx will go out of bounds if
+ * given a PMC event code when it knows about that CPU.
+ *
+ * XXX: Ideally we'd have user flags to give us that context.
+ */
+ if (ev->pl_u.pl_a.pl_event < PMC_EVENT_FIRST)
+ ev->pl_u.pl_a.pl_evname =
+ pmc_pmu_event_get_by_idx(ps->ps_cpuid,
+ ev->pl_u.pl_a.pl_event);
+ else if (ev->pl_u.pl_a.pl_event <= PMC_EVENT_LAST)
+ ev->pl_u.pl_a.pl_evname =
+ _pmc_name_of_event(ev->pl_u.pl_a.pl_event,
+ ps->ps_arch);
+ else
+ ev->pl_u.pl_a.pl_evname = NULL;
+ if (ev->pl_u.pl_a.pl_evname == NULL) {
printf("unknown event\n");
goto error;
}