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:		28dd6730a5 ("libpmc: enable pmu_utils on arm64")
Fixes:		8cc3815f02 ("hwpmc_arm64: accept raw event codes...")
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D31221
This commit is contained in:
Mitchell Horne 2021-07-21 19:59:27 -03:00
parent 3a57f08b50
commit 27ea55fc65
3 changed files with 12 additions and 5 deletions

View File

@ -577,6 +577,7 @@ int
pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
{
const struct pmu_event *pe;
struct pmu_event_desc ped;
int idx = -1;
event_name = pmu_alias_get(event_name);
@ -584,8 +585,12 @@ pmc_pmu_pmcallocate(const char *event_name, struct pmc_op_pmcallocate *pm)
return (ENOENT);
if (pe->event == NULL)
return (ENOENT);
if (pmu_parse_event(&ped, pe->event))
return (ENOENT);
assert(idx >= 0);
pm->pm_ev = idx;
pm->pm_md.pm_md_config = ped.ped_event;
pm->pm_md.pm_md_flags |= PM_MD_RAW_EVENT;
pm->pm_class = PMC_CLASS_ARMV8;
pm->pm_caps |= (PMC_CAP_READ | PMC_CAP_WRITE);

View File

@ -38,10 +38,12 @@
#include <dev/hwpmc/hwpmc_arm64.h>
union pmc_md_op_pmcallocate {
uint32_t pm_md_flags;
struct {
uint32_t pm_md_config;
uint32_t pm_md_flags;
#define PM_MD_RAW_EVENT 0x1
uint32_t __pad32;
uint64_t __pad[3];
};
uint64_t __pad[4];
};
/* Logging */

View File

@ -182,9 +182,9 @@ arm64_allocate_pmc(int cpu, int ri, struct pmc *pm,
pe = a->pm_ev;
/* Adjust the config value if needed. */
config = (uint32_t)pe;
config = a->pm_md.pm_md_config;
if ((a->pm_md.pm_md_flags & PM_MD_RAW_EVENT) == 0) {
config -= PMC_EV_ARMV8_FIRST;
config = (uint32_t)pe - PMC_EV_ARMV8_FIRST;
if (config > (PMC_EV_ARMV8_LAST - PMC_EV_ARMV8_FIRST))
return (EINVAL);
}