hwpmc: ABI fixes
- increase pmc cpuid field from 8 to 12 bits - add cpuid version string to initialize entry in the log so that filter can identify which counter index an event name maps to - GC unused config flags - make fixed counter assignment more robust as well as the changes needed to be properly identified for filter
This commit is contained in:
parent
5de96e33d6
commit
07d80fd8dc
@ -69,13 +69,14 @@ static struct pmu_alias pmu_alias_table[] = {
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
static const char *fixed_mode_cntrs[] = {
|
||||
"inst_retired.any",
|
||||
"cpu_clk_unhalted.thread",
|
||||
"cpu_clk_unhalted.thread_any",
|
||||
"cpu_clk_unhalted.ref_tsc",
|
||||
NULL
|
||||
};
|
||||
/*
|
||||
* The Intel fixed mode counters are:
|
||||
* "inst_retired.any",
|
||||
* "cpu_clk_unhalted.thread",
|
||||
* "cpu_clk_unhalted.thread_any",
|
||||
* "cpu_clk_unhalted.ref_tsc",
|
||||
*
|
||||
*/
|
||||
|
||||
static const char *
|
||||
pmu_alias_get(const char *name)
|
||||
@ -95,7 +96,7 @@ struct pmu_event_desc {
|
||||
uint32_t ped_frontend;
|
||||
uint32_t ped_ldlat;
|
||||
uint32_t ped_config1;
|
||||
uint8_t ped_umask;
|
||||
int16_t ped_umask;
|
||||
uint8_t ped_cmask;
|
||||
uint8_t ped_any;
|
||||
uint8_t ped_inv;
|
||||
@ -168,6 +169,7 @@ pmu_parse_event(struct pmu_event_desc *ped, const char *eventin)
|
||||
return (ENOMEM);
|
||||
r = event;
|
||||
bzero(ped, sizeof(*ped));
|
||||
ped->ped_umask = -1;
|
||||
while ((kvp = strsep(&event, ",")) != NULL) {
|
||||
key = strsep(&kvp, "=");
|
||||
if (key == NULL)
|
||||
@ -341,7 +343,6 @@ pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
|
||||
const struct pmu_event *pe;
|
||||
struct pmu_event_desc ped;
|
||||
struct pmc_md_iap_op_pmcallocate *iap;
|
||||
struct pmc_md_iaf_op_pmcallocate *iaf;
|
||||
int idx, isfixed;
|
||||
|
||||
iap = &pm->pm_md.pm_iap;
|
||||
@ -358,35 +359,22 @@ pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
|
||||
if (pmu_parse_event(&ped, pe->event))
|
||||
return (ENOENT);
|
||||
|
||||
for (idx = 0; fixed_mode_cntrs[idx] != NULL; idx++)
|
||||
if (strcmp(fixed_mode_cntrs[idx], event_name) == 0)
|
||||
isfixed = 1;
|
||||
if (isfixed) {
|
||||
iaf = &pm->pm_md.pm_iaf;
|
||||
pm->pm_class = PMC_CLASS_IAF;
|
||||
if (strcasestr(pe->desc, "retired") != NULL)
|
||||
pm->pm_ev = PMC_EV_IAF_INSTR_RETIRED_ANY;
|
||||
else if (strcasestr(pe->desc, "core") != NULL ||
|
||||
strcasestr(pe->desc, "unhalted"))
|
||||
pm->pm_ev = PMC_EV_IAF_CPU_CLK_UNHALTED_CORE;
|
||||
else if (strcasestr(pe->desc, "ref") != NULL)
|
||||
pm->pm_ev = PMC_EV_IAF_CPU_CLK_UNHALTED_REF;
|
||||
iaf->pm_iaf_flags |= (IAF_USR | IAF_OS);
|
||||
if (ped.ped_any)
|
||||
iaf->pm_iaf_flags |= IAF_ANY;
|
||||
if (pm->pm_caps & PMC_CAP_INTERRUPT)
|
||||
iaf->pm_iaf_flags |= IAF_PMI;
|
||||
return (0);
|
||||
} else if (strcasestr(event_name, "UNC_") == event_name ||
|
||||
strcasestr(event_name, "uncore") != NULL) {
|
||||
|
||||
if (strcasestr(event_name, "UNC_") == event_name ||
|
||||
strcasestr(event_name, "uncore") != NULL) {
|
||||
pm->pm_class = PMC_CLASS_UCP;
|
||||
} else {
|
||||
pm->pm_caps |= PMC_CAP_QUALIFIER;
|
||||
} else if ((ped.ped_umask == -1) ||
|
||||
(ped.ped_event == 0x0 && ped.ped_umask == 0x3)) {
|
||||
pm->pm_class = PMC_CLASS_IAF;
|
||||
} else {
|
||||
pm->pm_class = PMC_CLASS_IAP;
|
||||
pm->pm_caps |= PMC_CAP_QUALIFIER;
|
||||
}
|
||||
pm->pm_ev = idx;
|
||||
iap->pm_iap_config |= IAP_EVSEL(ped.ped_event);
|
||||
iap->pm_iap_config |= IAP_UMASK(ped.ped_umask);
|
||||
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;
|
||||
|
||||
|
@ -348,6 +348,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *len,
|
||||
case PMCLOG_TYPE_INITIALIZE:
|
||||
PMCLOG_READ32(le,ev->pl_u.pl_i.pl_version);
|
||||
PMCLOG_READ32(le,ev->pl_u.pl_i.pl_arch);
|
||||
PMCLOG_READ32(le, noop);
|
||||
PMCLOG_READSTRING(le, ev->pl_u.pl_i.pl_cpuid, PMC_CPUID_LEN);
|
||||
ps->ps_version = ev->pl_u.pl_i.pl_version;
|
||||
ps->ps_arch = ev->pl_u.pl_i.pl_arch;
|
||||
ps->ps_initialized = 1;
|
||||
|
@ -64,6 +64,7 @@ struct pmclog_ev_closelog {
|
||||
struct pmclog_ev_initialize {
|
||||
uint32_t pl_version;
|
||||
uint32_t pl_arch;
|
||||
char pl_cpuid[PATH_MAX];
|
||||
};
|
||||
|
||||
struct pmclog_ev_map_in {
|
||||
|
@ -73,7 +73,6 @@ struct pmc_mdep;
|
||||
|
||||
union pmc_md_op_pmcallocate {
|
||||
struct pmc_md_amd_op_pmcallocate pm_amd;
|
||||
struct pmc_md_iaf_op_pmcallocate pm_iaf;
|
||||
struct pmc_md_iap_op_pmcallocate pm_iap;
|
||||
struct pmc_md_ucf_op_pmcallocate pm_ucf;
|
||||
struct pmc_md_ucp_op_pmcallocate pm_ucp;
|
||||
|
@ -224,8 +224,9 @@ static int
|
||||
iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
|
||||
const struct pmc_op_pmcallocate *a)
|
||||
{
|
||||
enum pmc_event ev;
|
||||
uint32_t caps, flags, validflags;
|
||||
uint8_t ev, umask;
|
||||
uint32_t caps, flags, config;
|
||||
const struct pmc_md_iap_op_pmcallocate *iap;
|
||||
|
||||
KASSERT(cpu >= 0 && cpu < pmc_cpu_max(),
|
||||
("[core,%d] illegal CPU %d", __LINE__, cpu));
|
||||
@ -241,19 +242,32 @@ iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
|
||||
(caps & IAF_PMC_CAPS) != caps)
|
||||
return (EINVAL);
|
||||
|
||||
ev = pm->pm_event;
|
||||
iap = &a->pm_md.pm_iap;
|
||||
config = iap->pm_iap_config;
|
||||
ev = IAP_EVSEL_GET(config);
|
||||
umask = IAP_UMASK_GET(config);
|
||||
|
||||
|
||||
if (ev == PMC_EV_IAF_INSTR_RETIRED_ANY && ri != 0)
|
||||
/* INST_RETIRED.ANY */
|
||||
if (ev == 0xC0 && ri != 0)
|
||||
return (EINVAL);
|
||||
if (ev == PMC_EV_IAF_CPU_CLK_UNHALTED_CORE && ri != 1)
|
||||
/* CPU_CLK_UNHALTED.THREAD */
|
||||
else if (ev == 0x3C && ri != 1)
|
||||
return (EINVAL);
|
||||
if (ev == PMC_EV_IAF_CPU_CLK_UNHALTED_REF && ri != 2)
|
||||
/* CPU_CLK_UNHALTED.REF */
|
||||
else if (ev == 0x0 && umask == 0x3 && ri != 2)
|
||||
return (EINVAL);
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
flags = a->pm_md.pm_iaf.pm_iaf_flags;
|
||||
|
||||
validflags = IAF_MASK;
|
||||
flags = 0;
|
||||
if (config & IAP_OS)
|
||||
flags |= IAF_OS;
|
||||
if (config & IAP_USR)
|
||||
flags |= IAF_USR;
|
||||
if (config & IAP_ANY)
|
||||
flags |= IAF_ANY;
|
||||
if (config & IAP_INT)
|
||||
flags |= IAF_PMI;
|
||||
|
||||
if (caps & PMC_CAP_INTERRUPT)
|
||||
flags |= IAF_PMI;
|
||||
|
@ -39,13 +39,6 @@
|
||||
#define PERFCAP_SMM_FREEZE 0x1000
|
||||
#define PERFCAP_FW_WRITE 0x2000 /* full width write aliases */
|
||||
|
||||
/*
|
||||
* Fixed-function PMCs.
|
||||
*/
|
||||
struct pmc_md_iaf_op_pmcallocate {
|
||||
uint16_t pm_iaf_flags; /* additional flags */
|
||||
};
|
||||
|
||||
#define IAF_OS 0x1
|
||||
#define IAF_USR 0x2
|
||||
#define IAF_ANY 0x4
|
||||
|
@ -726,6 +726,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
|
||||
sizeof(struct pmclog_initialize));
|
||||
PMCLOG_EMIT32(PMC_VERSION);
|
||||
PMCLOG_EMIT32(md->pmd_cputype);
|
||||
PMCLOG_EMITSTRING(pmc_cpuid, PMC_CPUID_LEN);
|
||||
PMCLOG_DESPATCH_SYNC(po);
|
||||
|
||||
return (0);
|
||||
|
@ -79,7 +79,6 @@ struct pmc_mdep;
|
||||
|
||||
union pmc_md_op_pmcallocate {
|
||||
struct pmc_md_amd_op_pmcallocate pm_amd;
|
||||
struct pmc_md_iaf_op_pmcallocate pm_iaf;
|
||||
struct pmc_md_iap_op_pmcallocate pm_iap;
|
||||
struct pmc_md_ucf_op_pmcallocate pm_ucf;
|
||||
struct pmc_md_ucp_op_pmcallocate pm_ucp;
|
||||
|
@ -61,13 +61,17 @@
|
||||
*
|
||||
* The patch version is incremented for every bug fix.
|
||||
*/
|
||||
#define PMC_VERSION_MAJOR 0x05
|
||||
#define PMC_VERSION_MAJOR 0x06
|
||||
#define PMC_VERSION_MINOR 0x01
|
||||
#define PMC_VERSION_PATCH 0x0000
|
||||
|
||||
#define PMC_VERSION (PMC_VERSION_MAJOR << 24 | \
|
||||
PMC_VERSION_MINOR << 16 | PMC_VERSION_PATCH)
|
||||
|
||||
#define PMC_CPUID_LEN 64
|
||||
/* cpu model name for pmu lookup */
|
||||
extern char pmc_cpuid[PMC_CPUID_LEN];
|
||||
|
||||
/*
|
||||
* Kinds of CPUs known.
|
||||
*
|
||||
@ -360,13 +364,13 @@ enum pmc_ops {
|
||||
* Flags used in operations on PMCs.
|
||||
*/
|
||||
|
||||
#define PMC_F_FORCE 0x00000001 /*OP ADMIN force operation */
|
||||
#define PMC_F_UNUSED1 0x00000001 /* unused */
|
||||
#define PMC_F_DESCENDANTS 0x00000002 /*OP ALLOCATE track descendants */
|
||||
#define PMC_F_LOG_PROCCSW 0x00000004 /*OP ALLOCATE track ctx switches */
|
||||
#define PMC_F_LOG_PROCEXIT 0x00000008 /*OP ALLOCATE log proc exits */
|
||||
#define PMC_F_NEWVALUE 0x00000010 /*OP RW write new value */
|
||||
#define PMC_F_OLDVALUE 0x00000020 /*OP RW get old value */
|
||||
#define PMC_F_KGMON 0x00000040 /*OP ALLOCATE kgmon(8) profiling */
|
||||
|
||||
/* V2 API */
|
||||
#define PMC_F_CALLCHAIN 0x00000080 /*OP ALLOCATE capture callchains */
|
||||
#define PMC_F_USERCALLCHAIN 0x00000100 /*OP ALLOCATE use userspace stack */
|
||||
@ -392,15 +396,15 @@ typedef uint64_t pmc_value_t;
|
||||
/*
|
||||
* PMC IDs have the following format:
|
||||
*
|
||||
* +--------+----------+-----------+-----------+
|
||||
* | CPU | PMC MODE | PMC CLASS | ROW INDEX |
|
||||
* +--------+----------+-----------+-----------+
|
||||
* +-----------------------+-------+-----------+
|
||||
* | CPU | PMC MODE | CLASS | ROW INDEX |
|
||||
* +-----------------------+-------+-----------+
|
||||
*
|
||||
* where each field is 8 bits wide. Field 'CPU' is set to the
|
||||
* requested CPU for system-wide PMCs or PMC_CPU_ANY for process-mode
|
||||
* PMCs. Field 'PMC MODE' is the allocated PMC mode. Field 'PMC
|
||||
* CLASS' is the class of the PMC. Field 'ROW INDEX' is the row index
|
||||
* for the PMC.
|
||||
* where CPU is 12 bits, MODE 8, CLASS 4, and ROW INDEX 8 Field 'CPU'
|
||||
* is set to the requested CPU for system-wide PMCs or PMC_CPU_ANY for
|
||||
* process-mode PMCs. Field 'PMC MODE' is the allocated PMC mode.
|
||||
* Field 'PMC CLASS' is the class of the PMC. Field 'ROW INDEX' is the
|
||||
* row index for the PMC.
|
||||
*
|
||||
* The 'ROW INDEX' ranges over 0..NWPMCS where NHWPMCS is the total
|
||||
* number of hardware PMCs on this cpu.
|
||||
@ -408,12 +412,12 @@ typedef uint64_t pmc_value_t;
|
||||
|
||||
|
||||
#define PMC_ID_TO_ROWINDEX(ID) ((ID) & 0xFF)
|
||||
#define PMC_ID_TO_CLASS(ID) (((ID) & 0xFF00) >> 8)
|
||||
#define PMC_ID_TO_MODE(ID) (((ID) & 0xFF0000) >> 16)
|
||||
#define PMC_ID_TO_CPU(ID) (((ID) & 0xFF000000) >> 24)
|
||||
#define PMC_ID_TO_CLASS(ID) (((ID) & 0xF00) >> 8)
|
||||
#define PMC_ID_TO_MODE(ID) (((ID) & 0xFF000) >> 12)
|
||||
#define PMC_ID_TO_CPU(ID) (((ID) & 0xFFF00000) >> 20)
|
||||
#define PMC_ID_MAKE_ID(CPU,MODE,CLASS,ROWINDEX) \
|
||||
((((CPU) & 0xFF) << 24) | (((MODE) & 0xFF) << 16) | \
|
||||
(((CLASS) & 0xFF) << 8) | ((ROWINDEX) & 0xFF))
|
||||
((((CPU) & 0xFFF) << 20) | (((MODE) & 0xFF) << 12) | \
|
||||
(((CLASS) & 0xF) << 8) | ((ROWINDEX) & 0xFF))
|
||||
|
||||
/*
|
||||
* Data structures for system calls supported by the pmc driver.
|
||||
@ -1065,9 +1069,6 @@ extern struct pmc_cpu **pmc_pcpu;
|
||||
/* driver statistics */
|
||||
extern struct pmc_driverstats pmc_stats;
|
||||
|
||||
/* cpu model name for pmu lookup */
|
||||
extern char pmc_cpuid[64];
|
||||
|
||||
#if defined(HWPMC_DEBUG)
|
||||
#include <sys/ktr.h>
|
||||
|
||||
|
@ -134,6 +134,7 @@ struct pmclog_initialize {
|
||||
uint32_t pl_version; /* driver version */
|
||||
uint32_t pl_cpu; /* enum pmc_cputype */
|
||||
uint32_t pl_pad;
|
||||
char pl_cpuid[PMC_CPUID_LEN];
|
||||
} __packed;
|
||||
|
||||
struct pmclog_map_in {
|
||||
|
Loading…
Reference in New Issue
Block a user