2018-05-26 19:29:19 +00:00
|
|
|
/*-
|
2023-05-10 15:40:58 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2018-05-26 19:29:19 +00:00
|
|
|
*
|
|
|
|
* Copyright (c) 2018, Matthew Macy
|
2021-05-27 20:02:04 +00:00
|
|
|
* Copyright (c) 2021, The FreeBSD Foundation
|
|
|
|
*
|
|
|
|
* Portions of this software were developed by Mitchell Horne
|
|
|
|
* under sponsorship from the FreeBSD Foundation.
|
2018-05-26 19:29:19 +00:00
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/errno.h>
|
2020-07-28 02:56:26 +00:00
|
|
|
#include <sys/pmc.h>
|
2018-05-26 19:29:19 +00:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <limits.h>
|
2019-11-08 17:27:20 +00:00
|
|
|
#include <regex.h>
|
2018-05-26 19:29:19 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <pmc.h>
|
|
|
|
#include <pmclog.h>
|
2018-06-07 00:55:17 +00:00
|
|
|
#include <assert.h>
|
2018-05-26 19:29:19 +00:00
|
|
|
#include <libpmcstat.h>
|
|
|
|
#include "pmu-events/pmu-events.h"
|
|
|
|
|
|
|
|
struct pmu_alias {
|
|
|
|
const char *pa_alias;
|
|
|
|
const char *pa_name;
|
|
|
|
};
|
2018-08-14 05:18:43 +00:00
|
|
|
|
2021-05-31 14:24:44 +00:00
|
|
|
#if defined(__amd64__) || defined(__i386__)
|
2018-08-14 05:18:43 +00:00
|
|
|
typedef enum {
|
|
|
|
PMU_INVALID,
|
|
|
|
PMU_INTEL,
|
|
|
|
PMU_AMD,
|
|
|
|
} pmu_mfr_t;
|
|
|
|
|
|
|
|
static struct pmu_alias pmu_intel_alias_table[] = {
|
2022-06-02 19:09:38 +00:00
|
|
|
{"UNHALTED_CORE_CYCLES", "cpu_clk_unhalted.thread"},
|
|
|
|
{"UNHALTED-CORE-CYCLES", "cpu_clk_unhalted.thread"},
|
2018-05-30 03:40:02 +00:00
|
|
|
{"LLC_MISSES", "LONGEST_LAT_CACHE.MISS"},
|
|
|
|
{"LLC-MISSES", "LONGEST_LAT_CACHE.MISS"},
|
|
|
|
{"LLC_REFERENCE", "LONGEST_LAT_CACHE.REFERENCE"},
|
|
|
|
{"LLC-REFERENCE", "LONGEST_LAT_CACHE.REFERENCE"},
|
|
|
|
{"LLC_MISS_RHITM", "mem_load_l3_miss_retired.remote_hitm"},
|
|
|
|
{"LLC-MISS-RHITM", "mem_load_l3_miss_retired.remote_hitm"},
|
|
|
|
{"RESOURCE_STALL", "RESOURCE_STALLS.ANY"},
|
|
|
|
{"RESOURCE_STALLS_ANY", "RESOURCE_STALLS.ANY"},
|
|
|
|
{"BRANCH_INSTRUCTION_RETIRED", "BR_INST_RETIRED.ALL_BRANCHES"},
|
|
|
|
{"BRANCH-INSTRUCTION-RETIRED", "BR_INST_RETIRED.ALL_BRANCHES"},
|
|
|
|
{"BRANCH_MISSES_RETIRED", "BR_MISP_RETIRED.ALL_BRANCHES"},
|
|
|
|
{"BRANCH-MISSES-RETIRED", "BR_MISP_RETIRED.ALL_BRANCHES"},
|
2022-06-02 19:09:38 +00:00
|
|
|
{"unhalted-cycles", "cpu_clk_unhalted.thread"},
|
|
|
|
{"instructions", "inst_retired.any"},
|
2018-06-04 04:59:48 +00:00
|
|
|
{"branch-mispredicts", "br_misp_retired.all_branches"},
|
|
|
|
{"branches", "br_inst_retired.all_branches"},
|
2018-06-01 00:45:43 +00:00
|
|
|
{"interrupts", "hw_interrupts.received"},
|
|
|
|
{"ic-misses", "frontend_retired.l1i_miss"},
|
2018-05-30 03:40:02 +00:00
|
|
|
{NULL, NULL},
|
2018-05-26 19:29:19 +00:00
|
|
|
};
|
|
|
|
|
2018-08-14 05:18:43 +00:00
|
|
|
static struct pmu_alias pmu_amd_alias_table[] = {
|
|
|
|
{"UNHALTED_CORE_CYCLES", "ls_not_halted_cyc"},
|
|
|
|
{"UNHALTED-CORE-CYCLES", "ls_not_halted_cyc"},
|
2021-09-30 14:13:37 +00:00
|
|
|
{"LLC_MISSES", "l3_comb_clstr_state.request_miss"},
|
|
|
|
{"LLC-MISSES", "l3_comb_clstr_state.request_miss"},
|
|
|
|
{"LLC_REFERENCE", "l3_request_g1.caching_l3_cache_accesses"},
|
|
|
|
{"LLC-REFERENCE", "l3_request_g1.caching_l3_cache_accesses"},
|
|
|
|
{"BRANCH_INSTRUCTION_RETIRED", "ex_ret_brn"},
|
|
|
|
{"BRANCH-INSTRUCTION-RETIRED", "ex_ret_brn"},
|
|
|
|
{"BRANCH_MISSES_RETIRED", "ex_ret_brn_misp"},
|
|
|
|
{"BRANCH-MISSES-RETIRED", "ex_ret_brn_misp"},
|
|
|
|
{"unhalted-cycles", "ls_not_halted_cyc"},
|
|
|
|
{"instructions", "ex_ret_instr",},
|
|
|
|
{"branch-mispredicts", "ex_ret_brn_misp"},
|
|
|
|
{"branches", "ex_ret_brn"},
|
|
|
|
{"interrupts", "ls_int_taken"}, /* Not on amdzen1 */
|
2018-08-14 05:18:43 +00:00
|
|
|
{NULL, NULL},
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static pmu_mfr_t
|
|
|
|
pmu_events_mfr(void)
|
|
|
|
{
|
2020-07-28 02:56:26 +00:00
|
|
|
char buf[PMC_CPUID_LEN];
|
|
|
|
size_t s = sizeof(buf);
|
2018-08-14 05:18:43 +00:00
|
|
|
pmu_mfr_t mfr;
|
|
|
|
|
|
|
|
if (sysctlbyname("kern.hwpmc.cpuid", buf, &s,
|
2020-07-28 02:56:26 +00:00
|
|
|
(void *)NULL, 0) == -1)
|
2018-08-14 05:18:43 +00:00
|
|
|
return (PMU_INVALID);
|
2020-02-07 22:28:04 +00:00
|
|
|
if (strcasestr(buf, "AuthenticAMD") != NULL ||
|
|
|
|
strcasestr(buf, "HygonGenuine") != NULL)
|
2018-08-14 05:18:43 +00:00
|
|
|
mfr = PMU_AMD;
|
|
|
|
else if (strcasestr(buf, "GenuineIntel") != NULL)
|
|
|
|
mfr = PMU_INTEL;
|
|
|
|
else
|
|
|
|
mfr = PMU_INVALID;
|
|
|
|
return (mfr);
|
|
|
|
}
|
|
|
|
|
2018-06-04 02:05:48 +00:00
|
|
|
/*
|
|
|
|
* The Intel fixed mode counters are:
|
|
|
|
* "inst_retired.any",
|
|
|
|
* "cpu_clk_unhalted.thread",
|
|
|
|
* "cpu_clk_unhalted.thread_any",
|
|
|
|
* "cpu_clk_unhalted.ref_tsc",
|
|
|
|
*
|
|
|
|
*/
|
2018-05-29 04:23:21 +00:00
|
|
|
|
2018-05-26 19:29:19 +00:00
|
|
|
static const char *
|
|
|
|
pmu_alias_get(const char *name)
|
|
|
|
{
|
2018-08-14 05:18:43 +00:00
|
|
|
pmu_mfr_t mfr;
|
2018-05-26 19:29:19 +00:00
|
|
|
struct pmu_alias *pa;
|
2018-08-14 05:18:43 +00:00
|
|
|
struct pmu_alias *pmu_alias_table;
|
|
|
|
|
|
|
|
if ((mfr = pmu_events_mfr()) == PMU_INVALID)
|
|
|
|
return (name);
|
|
|
|
if (mfr == PMU_AMD)
|
|
|
|
pmu_alias_table = pmu_amd_alias_table;
|
|
|
|
else if (mfr == PMU_INTEL)
|
|
|
|
pmu_alias_table = pmu_intel_alias_table;
|
|
|
|
else
|
|
|
|
return (name);
|
2018-05-26 19:29:19 +00:00
|
|
|
|
|
|
|
for (pa = pmu_alias_table; pa->pa_alias != NULL; pa++)
|
|
|
|
if (strcasecmp(name, pa->pa_alias) == 0)
|
|
|
|
return (pa->pa_name);
|
2018-08-14 05:18:43 +00:00
|
|
|
|
2018-05-26 19:29:19 +00:00
|
|
|
return (name);
|
|
|
|
}
|
2021-07-23 18:09:09 +00:00
|
|
|
#elif defined(__powerpc64__)
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
pmu_alias_get(const char *name)
|
|
|
|
{
|
|
|
|
return (name);
|
|
|
|
}
|
2018-05-26 19:29:19 +00:00
|
|
|
|
2021-05-27 20:02:04 +00:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
|
|
|
|
static struct pmu_alias pmu_armv8_alias_table[] = {
|
2022-07-06 17:30:03 +00:00
|
|
|
{"UNHALTED_CORE_CYCLES", "CPU_CYCLES"},
|
|
|
|
{"UNHALTED-CORE-CYCLES", "CPU_CYCLES"},
|
|
|
|
{"LLC_MISSES", "LL_CACHE_MISS_RD"},
|
|
|
|
{"LLC-MISSES", "LL_CACHE_MISS_RD"},
|
|
|
|
{"LLC_REFERENCE", "LL_CACHE_RD"},
|
|
|
|
{"LLC-REFERENCE", "LL_CACHE_RD"},
|
|
|
|
{"BRANCH_INSTRUCTION_RETIRED", "BR_RETIRED"},
|
|
|
|
{"BRANCH-INSTRUCTION-RETIRED", "BR_RETIRED"},
|
|
|
|
{"BRANCH_MISSES_RETIRED", "BR_MIS_PRED_RETIRED"},
|
|
|
|
{"BRANCH-MISSES-RETIRED", "BR_MIS_PRED_RETIRED"},
|
|
|
|
{"unhalted-cycles", "CPU_CYCLES"},
|
|
|
|
{"instructions", "INST_RETIRED",},
|
|
|
|
{"branch-mispredicts", "BR_MIS_PRED_RETIRED"},
|
|
|
|
{"branches", "BR_RETIRED"},
|
|
|
|
{"interrupts", "EXC_IRQ"},
|
2021-05-27 20:02:04 +00:00
|
|
|
{NULL, NULL},
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
pmu_alias_get(const char *name)
|
|
|
|
{
|
|
|
|
struct pmu_alias *pa;
|
|
|
|
|
|
|
|
for (pa = pmu_armv8_alias_table; pa->pa_alias != NULL; pa++)
|
|
|
|
if (strcasecmp(name, pa->pa_alias) == 0)
|
|
|
|
return (pa->pa_name);
|
|
|
|
|
|
|
|
return (name);
|
|
|
|
}
|
|
|
|
|
2021-05-31 14:24:44 +00:00
|
|
|
#else
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
pmu_alias_get(const char *name)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (name);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-05-26 19:29:19 +00:00
|
|
|
struct pmu_event_desc {
|
|
|
|
uint64_t ped_period;
|
|
|
|
uint64_t ped_offcore_rsp;
|
2018-11-04 06:24:27 +00:00
|
|
|
uint64_t ped_l3_thread;
|
|
|
|
uint64_t ped_l3_slice;
|
2018-05-26 19:29:19 +00:00
|
|
|
uint32_t ped_event;
|
|
|
|
uint32_t ped_frontend;
|
|
|
|
uint32_t ped_ldlat;
|
|
|
|
uint32_t ped_config1;
|
2018-06-04 02:05:48 +00:00
|
|
|
int16_t ped_umask;
|
2018-05-30 03:40:02 +00:00
|
|
|
uint8_t ped_cmask;
|
|
|
|
uint8_t ped_any;
|
|
|
|
uint8_t ped_inv;
|
|
|
|
uint8_t ped_edge;
|
|
|
|
uint8_t ped_fc_mask;
|
|
|
|
uint8_t ped_ch_mask;
|
2018-05-26 19:29:19 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct pmu_events_map *
|
2018-06-04 04:59:48 +00:00
|
|
|
pmu_events_map_get(const char *cpuid)
|
2018-05-26 19:29:19 +00:00
|
|
|
{
|
2019-11-08 16:56:48 +00:00
|
|
|
regex_t re;
|
|
|
|
regmatch_t pmatch[1];
|
2020-07-28 02:56:26 +00:00
|
|
|
char buf[PMC_CPUID_LEN];
|
|
|
|
size_t s = sizeof(buf);
|
2019-11-08 16:56:48 +00:00
|
|
|
int match;
|
2018-05-26 19:29:19 +00:00
|
|
|
const struct pmu_events_map *pme;
|
|
|
|
|
2018-06-04 04:59:48 +00:00
|
|
|
if (cpuid != NULL) {
|
2020-07-28 02:56:26 +00:00
|
|
|
strlcpy(buf, cpuid, s);
|
2018-06-04 04:59:48 +00:00
|
|
|
} else {
|
|
|
|
if (sysctlbyname("kern.hwpmc.cpuid", buf, &s,
|
|
|
|
(void *)NULL, 0) == -1)
|
|
|
|
return (NULL);
|
|
|
|
}
|
2019-11-08 16:56:48 +00:00
|
|
|
for (pme = pmu_events_map; pme->cpuid != NULL; pme++) {
|
|
|
|
if (regcomp(&re, pme->cpuid, REG_EXTENDED) != 0) {
|
|
|
|
printf("regex '%s' failed to compile, ignoring\n",
|
|
|
|
pme->cpuid);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
match = regexec(&re, buf, 1, pmatch, 0);
|
|
|
|
regfree(&re);
|
|
|
|
if (match == 0) {
|
2020-07-14 18:11:05 +00:00
|
|
|
if (pmatch[0].rm_so == 0 && (buf[pmatch[0].rm_eo] == 0
|
|
|
|
|| buf[pmatch[0].rm_eo] == '-'))
|
2019-11-08 16:56:48 +00:00
|
|
|
return (pme);
|
|
|
|
}
|
|
|
|
}
|
2018-05-26 19:29:19 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct pmu_event *
|
2018-06-04 04:59:48 +00:00
|
|
|
pmu_event_get(const char *cpuid, const char *event_name, int *idx)
|
2018-05-26 19:29:19 +00:00
|
|
|
{
|
|
|
|
const struct pmu_events_map *pme;
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
int i;
|
|
|
|
|
2018-06-04 04:59:48 +00:00
|
|
|
if ((pme = pmu_events_map_get(cpuid)) == NULL)
|
2018-05-26 19:29:19 +00:00
|
|
|
return (NULL);
|
|
|
|
for (i = 0, pe = pme->table; pe->name || pe->desc || pe->event; pe++, i++) {
|
|
|
|
if (pe->name == NULL)
|
|
|
|
continue;
|
|
|
|
if (strcasecmp(pe->name, event_name) == 0) {
|
|
|
|
if (idx)
|
|
|
|
*idx = i;
|
|
|
|
return (pe);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2018-06-04 04:59:48 +00:00
|
|
|
int
|
|
|
|
pmc_pmu_idx_get_by_event(const char *cpuid, const char *event)
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
const char *realname;
|
|
|
|
|
|
|
|
realname = pmu_alias_get(event);
|
|
|
|
if (pmu_event_get(cpuid, realname, &idx) == NULL)
|
|
|
|
return (-1);
|
|
|
|
return (idx);
|
|
|
|
}
|
|
|
|
|
2018-05-26 19:29:19 +00:00
|
|
|
const char *
|
2018-06-06 02:48:09 +00:00
|
|
|
pmc_pmu_event_get_by_idx(const char *cpuid, int idx)
|
2018-05-26 19:29:19 +00:00
|
|
|
{
|
|
|
|
const struct pmu_events_map *pme;
|
|
|
|
|
2018-06-06 02:48:09 +00:00
|
|
|
if ((pme = pmu_events_map_get(cpuid)) == NULL)
|
2018-05-26 19:29:19 +00:00
|
|
|
return (NULL);
|
2018-06-07 00:55:17 +00:00
|
|
|
assert(pme->table[idx].name);
|
|
|
|
return (pme->table[idx].name);
|
2018-05-26 19:29:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
pmu_parse_event(struct pmu_event_desc *ped, const char *eventin)
|
|
|
|
{
|
|
|
|
char *event;
|
2018-05-29 21:02:13 +00:00
|
|
|
char *kvp, *key, *value, *r;
|
2018-05-26 19:29:19 +00:00
|
|
|
char *debug;
|
|
|
|
|
|
|
|
if ((event = strdup(eventin)) == NULL)
|
|
|
|
return (ENOMEM);
|
2018-05-29 21:02:13 +00:00
|
|
|
r = event;
|
2018-05-26 19:29:19 +00:00
|
|
|
bzero(ped, sizeof(*ped));
|
2018-09-14 01:30:05 +00:00
|
|
|
ped->ped_period = DEFAULT_SAMPLE_COUNT;
|
2018-06-04 02:05:48 +00:00
|
|
|
ped->ped_umask = -1;
|
2018-05-26 19:29:19 +00:00
|
|
|
while ((kvp = strsep(&event, ",")) != NULL) {
|
|
|
|
key = strsep(&kvp, "=");
|
|
|
|
if (key == NULL)
|
|
|
|
abort();
|
|
|
|
value = kvp;
|
|
|
|
if (strcmp(key, "umask") == 0)
|
|
|
|
ped->ped_umask = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "event") == 0)
|
|
|
|
ped->ped_event = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "period") == 0)
|
|
|
|
ped->ped_period = strtol(value, NULL, 10);
|
|
|
|
else if (strcmp(key, "offcore_rsp") == 0)
|
|
|
|
ped->ped_offcore_rsp = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "any") == 0)
|
|
|
|
ped->ped_any = strtol(value, NULL, 10);
|
|
|
|
else if (strcmp(key, "cmask") == 0)
|
|
|
|
ped->ped_cmask = strtol(value, NULL, 10);
|
|
|
|
else if (strcmp(key, "inv") == 0)
|
|
|
|
ped->ped_inv = strtol(value, NULL, 10);
|
|
|
|
else if (strcmp(key, "edge") == 0)
|
|
|
|
ped->ped_edge = strtol(value, NULL, 10);
|
|
|
|
else if (strcmp(key, "frontend") == 0)
|
|
|
|
ped->ped_frontend = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "ldlat") == 0)
|
|
|
|
ped->ped_ldlat = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "fc_mask") == 0)
|
|
|
|
ped->ped_fc_mask = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "ch_mask") == 0)
|
|
|
|
ped->ped_ch_mask = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "config1") == 0)
|
|
|
|
ped->ped_config1 = strtol(value, NULL, 16);
|
2018-11-04 06:24:27 +00:00
|
|
|
else if (strcmp(key, "l3_thread_mask") == 0)
|
|
|
|
ped->ped_l3_thread = strtol(value, NULL, 16);
|
|
|
|
else if (strcmp(key, "l3_slice_mask") == 0)
|
|
|
|
ped->ped_l3_slice = strtol(value, NULL, 16);
|
2018-05-26 19:29:19 +00:00
|
|
|
else {
|
|
|
|
debug = getenv("PMUDEBUG");
|
|
|
|
if (debug != NULL && strcmp(debug, "true") == 0 && value != NULL)
|
|
|
|
printf("unrecognized kvpair: %s:%s\n", key, value);
|
|
|
|
}
|
|
|
|
}
|
2018-05-29 21:02:13 +00:00
|
|
|
free(r);
|
2018-05-26 19:29:19 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t
|
|
|
|
pmc_pmu_sample_rate_get(const char *event_name)
|
|
|
|
{
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
struct pmu_event_desc ped;
|
|
|
|
|
|
|
|
event_name = pmu_alias_get(event_name);
|
2018-06-04 04:59:48 +00:00
|
|
|
if ((pe = pmu_event_get(NULL, event_name, NULL)) == NULL)
|
2018-05-26 19:29:19 +00:00
|
|
|
return (DEFAULT_SAMPLE_COUNT);
|
|
|
|
if (pe->event == NULL)
|
|
|
|
return (DEFAULT_SAMPLE_COUNT);
|
|
|
|
if (pmu_parse_event(&ped, pe->event))
|
|
|
|
return (DEFAULT_SAMPLE_COUNT);
|
|
|
|
return (ped.ped_period);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
pmc_pmu_enabled(void)
|
|
|
|
{
|
|
|
|
|
2018-06-04 04:59:48 +00:00
|
|
|
return (pmu_events_map_get(NULL) != NULL);
|
2018-05-26 19:29:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-06-01 00:45:53 +00:00
|
|
|
pmc_pmu_print_counters(const char *event_name)
|
2018-05-26 19:29:19 +00:00
|
|
|
{
|
|
|
|
const struct pmu_events_map *pme;
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
struct pmu_event_desc ped;
|
|
|
|
char *debug;
|
|
|
|
int do_debug;
|
2018-05-30 03:40:02 +00:00
|
|
|
|
2018-05-26 19:29:19 +00:00
|
|
|
debug = getenv("PMUDEBUG");
|
|
|
|
do_debug = 0;
|
|
|
|
|
|
|
|
if (debug != NULL && strcmp(debug, "true") == 0)
|
|
|
|
do_debug = 1;
|
2018-06-04 04:59:48 +00:00
|
|
|
if ((pme = pmu_events_map_get(NULL)) == NULL)
|
2018-05-26 19:29:19 +00:00
|
|
|
return;
|
|
|
|
for (pe = pme->table; pe->name || pe->desc || pe->event; pe++) {
|
|
|
|
if (pe->name == NULL)
|
|
|
|
continue;
|
2018-06-01 00:45:53 +00:00
|
|
|
if (event_name != NULL && strcasestr(pe->name, event_name) == NULL)
|
|
|
|
continue;
|
2018-05-26 19:29:19 +00:00
|
|
|
printf("\t%s\n", pe->name);
|
|
|
|
if (do_debug)
|
|
|
|
pmu_parse_event(&ped, pe->event);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pmc_pmu_print_counter_desc(const char *ev)
|
|
|
|
{
|
|
|
|
const struct pmu_events_map *pme;
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
|
2018-06-04 04:59:48 +00:00
|
|
|
if ((pme = pmu_events_map_get(NULL)) == NULL)
|
2018-05-26 19:29:19 +00:00
|
|
|
return;
|
|
|
|
for (pe = pme->table; pe->name || pe->desc || pe->event; pe++) {
|
|
|
|
if (pe->name == NULL)
|
|
|
|
continue;
|
|
|
|
if (strcasestr(pe->name, ev) != NULL &&
|
2018-05-30 03:40:02 +00:00
|
|
|
pe->desc != NULL)
|
|
|
|
printf("%s:\t%s\n", pe->name, pe->desc);
|
2018-05-26 19:29:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pmc_pmu_print_counter_desc_long(const char *ev)
|
|
|
|
{
|
|
|
|
const struct pmu_events_map *pme;
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
|
2018-06-04 04:59:48 +00:00
|
|
|
if ((pme = pmu_events_map_get(NULL)) == NULL)
|
2018-05-26 19:29:19 +00:00
|
|
|
return;
|
|
|
|
for (pe = pme->table; pe->name || pe->desc || pe->event; pe++) {
|
|
|
|
if (pe->name == NULL)
|
|
|
|
continue;
|
|
|
|
if (strcasestr(pe->name, ev) != NULL) {
|
|
|
|
if (pe->long_desc != NULL)
|
|
|
|
printf("%s:\n%s\n", pe->name, pe->long_desc);
|
|
|
|
else if (pe->desc != NULL)
|
|
|
|
printf("%s:\t%s\n", pe->name, pe->desc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-01 00:45:53 +00:00
|
|
|
void
|
|
|
|
pmc_pmu_print_counter_full(const char *ev)
|
|
|
|
{
|
|
|
|
const struct pmu_events_map *pme;
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
|
2018-06-04 04:59:48 +00:00
|
|
|
if ((pme = pmu_events_map_get(NULL)) == NULL)
|
2018-06-01 00:45:53 +00:00
|
|
|
return;
|
|
|
|
for (pe = pme->table; pe->name || pe->desc || pe->event; pe++) {
|
|
|
|
if (pe->name == NULL)
|
|
|
|
continue;
|
|
|
|
if (strcasestr(pe->name, ev) == NULL)
|
|
|
|
continue;
|
|
|
|
printf("name: %s\n", pe->name);
|
|
|
|
if (pe->long_desc != NULL)
|
|
|
|
printf("desc: %s\n", pe->long_desc);
|
|
|
|
else if (pe->desc != NULL)
|
|
|
|
printf("desc: %s\n", pe->desc);
|
|
|
|
if (pe->event != NULL)
|
|
|
|
printf("event: %s\n", pe->event);
|
|
|
|
if (pe->topic != NULL)
|
|
|
|
printf("topic: %s\n", pe->topic);
|
|
|
|
if (pe->pmu != NULL)
|
|
|
|
printf("pmu: %s\n", pe->pmu);
|
|
|
|
if (pe->unit != NULL)
|
|
|
|
printf("unit: %s\n", pe->unit);
|
|
|
|
if (pe->perpkg != NULL)
|
|
|
|
printf("perpkg: %s\n", pe->perpkg);
|
|
|
|
if (pe->metric_expr != NULL)
|
|
|
|
printf("metric_expr: %s\n", pe->metric_expr);
|
|
|
|
if (pe->metric_name != NULL)
|
|
|
|
printf("metric_name: %s\n", pe->metric_name);
|
|
|
|
if (pe->metric_group != NULL)
|
|
|
|
printf("metric_group: %s\n", pe->metric_group);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-31 14:24:44 +00:00
|
|
|
#if defined(__amd64__) || defined(__i386__)
|
2018-08-14 05:18:43 +00:00
|
|
|
static int
|
2018-11-04 06:24:27 +00:00
|
|
|
pmc_pmu_amd_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm,
|
2018-08-14 05:18:43 +00:00
|
|
|
struct pmu_event_desc *ped)
|
2018-05-26 19:29:19 +00:00
|
|
|
{
|
2018-08-14 05:18:43 +00:00
|
|
|
struct pmc_md_amd_op_pmcallocate *amd;
|
2018-11-04 06:24:27 +00:00
|
|
|
const struct pmu_event *pe;
|
|
|
|
int idx = -1;
|
2018-05-26 19:29:19 +00:00
|
|
|
|
2018-08-14 05:18:43 +00:00
|
|
|
amd = &pm->pm_md.pm_amd;
|
|
|
|
if (ped->ped_umask > 0) {
|
|
|
|
pm->pm_caps |= PMC_CAP_QUALIFIER;
|
|
|
|
amd->pm_amd_config |= AMD_PMC_TO_UNITMASK(ped->ped_umask);
|
|
|
|
}
|
|
|
|
pm->pm_class = PMC_CLASS_K8;
|
2018-11-04 06:24:27 +00:00
|
|
|
pe = pmu_event_get(NULL, event_name, &idx);
|
|
|
|
|
|
|
|
if (strcmp("l3cache", pe->topic) == 0){
|
|
|
|
amd->pm_amd_config |= AMD_PMC_TO_EVENTMASK(ped->ped_event);
|
|
|
|
amd->pm_amd_sub_class = PMC_AMD_SUB_CLASS_L3_CACHE;
|
|
|
|
amd->pm_amd_config |= AMD_PMC_TO_L3SLICE(ped->ped_l3_slice);
|
|
|
|
amd->pm_amd_config |= AMD_PMC_TO_L3CORE(ped->ped_l3_thread);
|
|
|
|
}
|
|
|
|
else if (strcmp("data fabric", pe->topic) == 0){
|
2018-08-14 05:18:43 +00:00
|
|
|
|
2018-11-04 06:24:27 +00:00
|
|
|
amd->pm_amd_config |= AMD_PMC_TO_EVENTMASK_DF(ped->ped_event);
|
|
|
|
amd->pm_amd_sub_class = PMC_AMD_SUB_CLASS_DATA_FABRIC;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
amd->pm_amd_config |= AMD_PMC_TO_EVENTMASK(ped->ped_event);
|
|
|
|
amd->pm_amd_sub_class = PMC_AMD_SUB_CLASS_CORE;
|
|
|
|
if ((pm->pm_caps & (PMC_CAP_USER|PMC_CAP_SYSTEM)) == 0 ||
|
|
|
|
(pm->pm_caps & (PMC_CAP_USER|PMC_CAP_SYSTEM)) ==
|
|
|
|
(PMC_CAP_USER|PMC_CAP_SYSTEM))
|
|
|
|
amd->pm_amd_config |= (AMD_PMC_USR | AMD_PMC_OS);
|
|
|
|
else if (pm->pm_caps & PMC_CAP_USER)
|
|
|
|
amd->pm_amd_config |= AMD_PMC_USR;
|
|
|
|
else if (pm->pm_caps & PMC_CAP_SYSTEM)
|
|
|
|
amd->pm_amd_config |= AMD_PMC_OS;
|
|
|
|
if (ped->ped_edge)
|
|
|
|
amd->pm_amd_config |= AMD_PMC_EDGE;
|
|
|
|
if (ped->ped_inv)
|
2022-05-31 04:02:06 +00:00
|
|
|
amd->pm_amd_config |= AMD_PMC_INVERT;
|
2018-11-04 06:24:27 +00:00
|
|
|
if (pm->pm_caps & PMC_CAP_INTERRUPT)
|
|
|
|
amd->pm_amd_config |= AMD_PMC_INT;
|
|
|
|
}
|
2018-08-14 05:18:43 +00:00
|
|
|
return (0);
|
|
|
|
}
|
2018-05-26 19:29:19 +00:00
|
|
|
|
2018-08-14 05:18:43 +00:00
|
|
|
static int
|
|
|
|
pmc_pmu_intel_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm,
|
|
|
|
struct pmu_event_desc *ped)
|
|
|
|
{
|
|
|
|
struct pmc_md_iap_op_pmcallocate *iap;
|
2018-06-04 02:05:48 +00:00
|
|
|
|
2018-08-14 05:18:43 +00:00
|
|
|
iap = &pm->pm_md.pm_iap;
|
2018-06-04 02:05:48 +00:00
|
|
|
if (strcasestr(event_name, "UNC_") == event_name ||
|
2018-06-04 04:59:48 +00:00
|
|
|
strcasestr(event_name, "uncore") != NULL) {
|
2018-05-31 22:26:50 +00:00
|
|
|
pm->pm_class = PMC_CLASS_UCP;
|
|
|
|
pm->pm_caps |= PMC_CAP_QUALIFIER;
|
2022-05-30 23:58:40 +00:00
|
|
|
} else if (ped->ped_event == 0x0) {
|
2018-06-04 02:05:48 +00:00
|
|
|
pm->pm_class = PMC_CLASS_IAF;
|
|
|
|
} else {
|
2018-05-31 22:26:50 +00:00
|
|
|
pm->pm_class = PMC_CLASS_IAP;
|
2018-06-04 02:05:48 +00:00
|
|
|
pm->pm_caps |= PMC_CAP_QUALIFIER;
|
2018-05-29 04:23:21 +00:00
|
|
|
}
|
2018-08-14 05:18:43 +00:00
|
|
|
iap->pm_iap_config |= IAP_EVSEL(ped->ped_event);
|
|
|
|
if (ped->ped_umask > 0)
|
|
|
|
iap->pm_iap_config |= IAP_UMASK(ped->ped_umask);
|
|
|
|
iap->pm_iap_config |= IAP_CMASK(ped->ped_cmask);
|
|
|
|
iap->pm_iap_rsp = ped->ped_offcore_rsp;
|
|
|
|
|
|
|
|
if ((pm->pm_caps & (PMC_CAP_USER|PMC_CAP_SYSTEM)) == 0 ||
|
|
|
|
(pm->pm_caps & (PMC_CAP_USER|PMC_CAP_SYSTEM)) ==
|
|
|
|
(PMC_CAP_USER|PMC_CAP_SYSTEM))
|
|
|
|
iap->pm_iap_config |= (IAP_USR | IAP_OS);
|
|
|
|
else if (pm->pm_caps & PMC_CAP_USER)
|
|
|
|
iap->pm_iap_config |= IAP_USR;
|
|
|
|
else if (pm->pm_caps & PMC_CAP_SYSTEM)
|
|
|
|
iap->pm_iap_config |= IAP_OS;
|
|
|
|
if (ped->ped_edge)
|
2018-05-26 19:29:19 +00:00
|
|
|
iap->pm_iap_config |= IAP_EDGE;
|
2018-08-14 05:18:43 +00:00
|
|
|
if (ped->ped_any)
|
2018-05-26 19:29:19 +00:00
|
|
|
iap->pm_iap_config |= IAP_ANY;
|
2018-08-14 05:18:43 +00:00
|
|
|
if (ped->ped_inv)
|
2022-05-31 04:02:06 +00:00
|
|
|
iap->pm_iap_config |= IAP_INV;
|
2018-05-26 19:29:19 +00:00
|
|
|
if (pm->pm_caps & PMC_CAP_INTERRUPT)
|
|
|
|
iap->pm_iap_config |= IAP_INT;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2023-06-19 22:32:22 +00:00
|
|
|
static int
|
|
|
|
pmc_pmu_pmcallocate_md(const char *event_name, struct pmc_op_pmcallocate *pm)
|
2018-08-14 05:18:43 +00:00
|
|
|
{
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
struct pmu_event_desc ped;
|
|
|
|
pmu_mfr_t mfr;
|
|
|
|
int idx = -1;
|
|
|
|
|
|
|
|
if ((mfr = pmu_events_mfr()) == PMU_INVALID)
|
|
|
|
return (ENOENT);
|
|
|
|
|
|
|
|
bzero(&pm->pm_md, sizeof(pm->pm_md));
|
|
|
|
pm->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
|
|
|
|
event_name = pmu_alias_get(event_name);
|
|
|
|
if ((pe = pmu_event_get(NULL, event_name, &idx)) == NULL)
|
|
|
|
return (ENOENT);
|
|
|
|
assert(idx >= 0);
|
|
|
|
pm->pm_ev = idx;
|
|
|
|
|
|
|
|
if (pe->event == NULL)
|
|
|
|
return (ENOENT);
|
|
|
|
if (pmu_parse_event(&ped, pe->event))
|
|
|
|
return (ENOENT);
|
|
|
|
|
|
|
|
if (mfr == PMU_INTEL)
|
|
|
|
return (pmc_pmu_intel_pmcallocate(event_name, pm, &ped));
|
|
|
|
else
|
|
|
|
return (pmc_pmu_amd_pmcallocate(event_name, pm, &ped));
|
|
|
|
}
|
|
|
|
|
2021-07-23 18:09:09 +00:00
|
|
|
#elif defined(__powerpc64__)
|
|
|
|
|
2023-06-19 22:32:22 +00:00
|
|
|
static int
|
|
|
|
pmc_pmu_pmcallocate_md(const char *event_name, struct pmc_op_pmcallocate *pm)
|
2021-07-23 18:09:09 +00:00
|
|
|
{
|
|
|
|
const struct pmu_event *pe;
|
|
|
|
struct pmu_event_desc ped;
|
|
|
|
int idx = -1;
|
|
|
|
|
|
|
|
bzero(&pm->pm_md, sizeof(pm->pm_md));
|
|
|
|
pm->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
|
|
|
|
event_name = pmu_alias_get(event_name);
|
|
|
|
|
|
|
|
if ((pe = pmu_event_get(NULL, event_name, &idx)) == NULL)
|
|
|
|
return (ENOENT);
|
|
|
|
if (pe->event == NULL)
|
|
|
|
return (ENOENT);
|
|
|
|
if (pmu_parse_event(&ped, pe->event))
|
|
|
|
return (ENOENT);
|
|
|
|
|
|
|
|
assert(ped.ped_event >= 0);
|
|
|
|
pm->pm_ev = idx;
|
|
|
|
pm->pm_md.pm_event = ped.ped_event;
|
|
|
|
pm->pm_class = PMC_CLASS_POWER8;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2021-05-27 20:02:04 +00:00
|
|
|
#elif defined(__aarch64__)
|
|
|
|
|
2023-06-19 22:32:22 +00:00
|
|
|
static int
|
|
|
|
pmc_pmu_pmcallocate_md(const char *event_name, struct pmc_op_pmcallocate *pm)
|
2021-05-27 20:02:04 +00:00
|
|
|
{
|
|
|
|
const struct pmu_event *pe;
|
libpmc/hwpmc: fix issues with arm64 pmu-events support
Due to a mis-merge, the changes committed to libpmc never called
pmu_parse_event(), or set pm->pm_ev. However, this field shouldn't be
used to carry the actual pmc event code anyway, as it is expected to
contain the index into the pmu event array (otherwise, it breaks event
name lookup in pmclog_get_event()). Add a new MD field,
pm_md.pm_md_config, to pass the raw event code to arm64_allocate_pmc().
Additionally, the change made to pmc_md_op_pmcallocate was incorrect, as
this is a union, not a struct. Restore the proper padding size.
Reviewed by: luporl, ray, andrew
Fixes: 28dd6730a5d6 ("libpmc: enable pmu_utils on arm64")
Fixes: 8cc3815f02be ("hwpmc_arm64: accept raw event codes...")
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31221
2021-07-21 22:59:27 +00:00
|
|
|
struct pmu_event_desc ped;
|
2021-05-27 20:02:04 +00:00
|
|
|
int idx = -1;
|
|
|
|
|
|
|
|
event_name = pmu_alias_get(event_name);
|
|
|
|
if ((pe = pmu_event_get(NULL, event_name, &idx)) == NULL)
|
|
|
|
return (ENOENT);
|
|
|
|
if (pe->event == NULL)
|
|
|
|
return (ENOENT);
|
libpmc/hwpmc: fix issues with arm64 pmu-events support
Due to a mis-merge, the changes committed to libpmc never called
pmu_parse_event(), or set pm->pm_ev. However, this field shouldn't be
used to carry the actual pmc event code anyway, as it is expected to
contain the index into the pmu event array (otherwise, it breaks event
name lookup in pmclog_get_event()). Add a new MD field,
pm_md.pm_md_config, to pass the raw event code to arm64_allocate_pmc().
Additionally, the change made to pmc_md_op_pmcallocate was incorrect, as
this is a union, not a struct. Restore the proper padding size.
Reviewed by: luporl, ray, andrew
Fixes: 28dd6730a5d6 ("libpmc: enable pmu_utils on arm64")
Fixes: 8cc3815f02be ("hwpmc_arm64: accept raw event codes...")
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31221
2021-07-21 22:59:27 +00:00
|
|
|
if (pmu_parse_event(&ped, pe->event))
|
|
|
|
return (ENOENT);
|
2021-05-27 20:02:04 +00:00
|
|
|
|
|
|
|
assert(idx >= 0);
|
libpmc/hwpmc: fix issues with arm64 pmu-events support
Due to a mis-merge, the changes committed to libpmc never called
pmu_parse_event(), or set pm->pm_ev. However, this field shouldn't be
used to carry the actual pmc event code anyway, as it is expected to
contain the index into the pmu event array (otherwise, it breaks event
name lookup in pmclog_get_event()). Add a new MD field,
pm_md.pm_md_config, to pass the raw event code to arm64_allocate_pmc().
Additionally, the change made to pmc_md_op_pmcallocate was incorrect, as
this is a union, not a struct. Restore the proper padding size.
Reviewed by: luporl, ray, andrew
Fixes: 28dd6730a5d6 ("libpmc: enable pmu_utils on arm64")
Fixes: 8cc3815f02be ("hwpmc_arm64: accept raw event codes...")
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D31221
2021-07-21 22:59:27 +00:00
|
|
|
pm->pm_ev = idx;
|
|
|
|
pm->pm_md.pm_md_config = ped.ped_event;
|
2021-05-27 20:02:04 +00:00
|
|
|
pm->pm_class = PMC_CLASS_ARMV8;
|
|
|
|
pm->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2018-05-26 19:29:19 +00:00
|
|
|
#else
|
2018-05-30 03:40:02 +00:00
|
|
|
|
2023-06-19 22:32:22 +00:00
|
|
|
static int
|
|
|
|
pmc_pmu_pmcallocate_md(const char *e __unused, struct pmc_op_pmcallocate *p __unused)
|
2018-05-30 03:40:02 +00:00
|
|
|
{
|
|
|
|
return (EOPNOTSUPP);
|
|
|
|
}
|
2018-05-26 19:29:19 +00:00
|
|
|
#endif
|
2023-06-19 22:32:22 +00:00
|
|
|
|
|
|
|
int
|
|
|
|
pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = pmc_pmu_pmcallocate_md(event_name, pm);
|
|
|
|
if (error != 0) {
|
|
|
|
/* Reset any changes. */
|
|
|
|
pm->pm_ev = 0;
|
|
|
|
pm->pm_caps = 0;
|
|
|
|
pm->pm_class = 0;
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
pmc: better distinguish pmu-events allocation path
Background:
The pm_ev field of struct pmc_op_pmcallocate and struct pmc
traditionally contains the index of the chosen event, corresponding to
the __PMC_EVENTS array in pmc_events.h. This is a static list of events,
maintained by FreeBSD.
In the usual case, libpmc translates the user supplied event name
(string) into the pm_ev index, which is passed as an argument to the
allocation syscall. On the kernel side, the allocation method for the
relevant hwpmc class translates the given index into the event code that
will be written to an event selection register.
In 2018, a new source of performance event definitions was introduced:
the pmu-events json files, which are maintained by the Linux kernel. The
result was better coverage for newer Intel processors with a reduced
maintenance burden for libpmc/hwpmc. Intel and AMD CPUs were
unconditionally switched to allocate events from pmu-events instead of
the traditional scheme (959826ca1bb0a, 81eb4dcf9e0d).
Under the pmu-events scheme, the pm_ev field contains an index
corresponding to the selected event from the pmu-events table, something
which the kernel has no knowledge of. The configuration for the
performance counting registers is instead passed via class-dependent
fields (struct pmc_md_op_pmcallocate).
In 2021 I changed the allocation logic so that it would attempt to
pull from the pmu-events table first, and fall-back to the traditional
method (dfb4fb41166bc3). Later, pmu-events support for arm64 and power8
CPUs was added (28dd6730a5d6 and b48a2770d48b).
The problem that remains is that the pm_ev field is overloaded, without
a definitive way to determine whether the event allocation came from the
pmu-events table or FreeBSD's statically-defined PMC events. This
resulted in a recent fix, 21f7397a61f7.
Change:
To disambiguate these two supported but separate use-cases, add a new
flag, PMC_F_EV_PMU, to be set as part of the allocation, indicating that
the event index came from pmu-events.
This is useful in two ways:
1. On the kernel side, we can validate the syscall arguments better.
Some classes support only the traditional event scheme (e.g.
hwpmc_armv7), while others support only the pmu-events method (e.g.
hwpmc_core for Intel). We can now check for this. The hwpmc_arm64
class supports both methods, so the new flag supersedes the existing
MD flag, PM_MD_EVENT_RAW.
2. The flag will be tracked in struct pmc for the duration of its
lifetime, meaning it is communicated back to userspace. This allows
libpmc to perform the reverse index-to-event-name translation
without speculating about the meaning of the index value.
Adding the flag is a backwards-incompatible ABI change. We recently
bumped the major version of the hwpmc module, so this breakage is
acceptable.
Reviewed by: jkoshy
MFC after: 3 days
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D40753
2023-06-06 17:26:46 +00:00
|
|
|
pm->pm_flags |= PMC_F_EV_PMU;
|
2023-06-19 22:32:22 +00:00
|
|
|
return (0);
|
|
|
|
}
|