/* * core_pmus: A PMU belongs to core_pmus if it's name is "cpu" or it's sysfs * directory contains "cpus" file. All PMUs belonging to core_pmus * must have pmu->is_core=1. If there are more than one PMU in * this list, perf interprets it as a heterogeneous platform. * (FWIW, certain ARM platforms having heterogeneous cores uses * homogeneous PMU, and thus they are treated as homogeneous * platform by perf because core_pmus will have only one entry) * other_pmus: All other PMUs which are not part of core_pmus list. It doesn't * matter whether PMU is present per SMT-thread or outside of the * core in the hw. For e.g., an instance of AMD ibs_fetch// and * ibs_op// PMUs is present in each hw SMT thread, however they * are captured under other_pmus. PMUs belonging to other_pmus * must have pmu->is_core=0 but pmu->is_uncore could be 0 or 1.
*/ static LIST_HEAD(core_pmus); static LIST_HEAD(other_pmus); enum perf_tool_pmu_type {
PERF_TOOL_PMU_TYPE_PE_CORE,
PERF_TOOL_PMU_TYPE_PE_OTHER,
PERF_TOOL_PMU_TYPE_TOOL,
PERF_TOOL_PMU_TYPE_HWMON,
PERF_TOOL_PMU_TYPE_DRM,
if (len > 0 && len != orig_len && str[len - 1] == '_') { /* * There is a '_{num}' suffix. For decimal suffixes any length * will do, for hexadecimal ensure more than 2 hex digits so * that S390's cpum_cf PMU doesn't match.
*/ if (!has_hex_digits || (orig_len - len) > 2) return len - 1;
} /* Use the full length. */ return orig_len;
}
/* * Once PMU is loaded it stays in the list, * so we keep us from multiple reading/parsing * the pmu format definitions.
*/
pmu = pmu_find(name); if (pmu) return pmu;
if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK) return NULL;
/* Looking up an individual perf event PMU failed, check if a tool PMU should be read. */ if (!strncmp(name, "hwmon_", 6))
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK; elseif (!strncmp(name, "drm_", 4))
to_read_pmus |= PERF_TOOL_PMU_TYPE_DRM_MASK; elseif (!strcmp(name, "tool"))
to_read_pmus |= PERF_TOOL_PMU_TYPE_TOOL_MASK;
if (to_read_pmus) {
pmu_read_sysfs(to_read_pmus);
pmu = pmu_find(name); if (pmu) return pmu;
} /* Read all necessary PMUs from sysfs and see if the PMU is found. */
to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK; if (!core_pmu)
to_read_pmus |= PERF_TOOL_PMU_TYPE_PE_OTHER_MASK;
pmu_read_sysfs(to_read_pmus); return pmu_find(name);
}
/* * Once PMU is loaded it stays in the list, * so we keep us from multiple reading/parsing * the pmu format definitions.
*/
pmu = pmu_find(name); if (pmu) return pmu;
if (read_pmu_types == PERF_TOOL_PMU_TYPE_ALL_MASK) return NULL;
while ((dent = io_dir__readdir(&dir)) != NULL) { if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; if (core_only && !is_pmu_core(dent->d_name)) continue; /* add to static LIST_HEAD(core_pmus) or LIST_HEAD(other_pmus): */
perf_pmu__find2(fd, dent->d_name);
}
close(fd);
}
skip_pe_pmus: if ((to_read_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK) && list_empty(&core_pmus)) { if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
pr_err("Failure to set up any core PMUs\n");
}
list_sort(NULL, &core_pmus, pmus_cmp);
/* * pmu iterator: If pmu is NULL, we start at the begin, otherwise return the * next pmu. Returns NULL on end.
*/ struct perf_pmu *perf_pmus__scan(struct perf_pmu *pmu)
{ bool use_core_pmus = !pmu || pmu->is_core;
if (!pmu) {
pmu_read_sysfs(PERF_TOOL_PMU_TYPE_ALL_MASK);
pmu = list_prepare_entry(pmu, &core_pmus, list);
} if (use_core_pmus) {
list_for_each_entry_continue(pmu, &core_pmus, list) return pmu;
if (!pmu) { /* Hwmon filename values that aren't used. */ enum hwmon_type type; int number; /* * Core PMUs, other sysfs PMUs and tool PMU can take all event * types or aren't wother optimizing for.
*/ unsignedint to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK |
PERF_TOOL_PMU_TYPE_PE_OTHER_MASK |
PERF_TOOL_PMU_TYPE_TOOL_MASK;
/* Could the event be a hwmon event? */ if (parse_hwmon_filename(event, &type, &number, /*item=*/NULL, /*alarm=*/NULL))
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK;
/* Could the event be a DRM event? */ if (strlen(event) > 4 && strncmp("drm-", event, 4) == 0)
to_read_pmus |= PERF_TOOL_PMU_TYPE_DRM_MASK;
if (!pmu) { /* * Core PMUs, other sysfs PMUs and tool PMU can have any name or * aren't wother optimizing for.
*/ unsignedint to_read_pmus = PERF_TOOL_PMU_TYPE_PE_CORE_MASK |
PERF_TOOL_PMU_TYPE_PE_OTHER_MASK |
PERF_TOOL_PMU_TYPE_TOOL_MASK;
/* * Hwmon PMUs have an alias from a sysfs name like hwmon0, * hwmon1, etc. or have a name of hwmon_<name>. They therefore * can only have a wildcard match if the wildcard begins with * "hwmon". Similarly drm PMUs must start "drm_", avoid reading * such events unless the PMU could match.
*/ if (strisglob(wildcard)) {
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK |
PERF_TOOL_PMU_TYPE_DRM_MASK;
} elseif (strlen(wildcard) >= 4 && strncmp("drm_", wildcard, 4) == 0) {
to_read_pmus |= PERF_TOOL_PMU_TYPE_DRM_MASK;
} elseif (strlen(wildcard) >= 5 && strncmp("hwmon", wildcard, 5) == 0) {
to_read_pmus |= PERF_TOOL_PMU_TYPE_HWMON_MASK;
}
struct perf_pmu *perf_pmus__find_by_attr(conststruct perf_event_attr *attr)
{ struct perf_pmu *pmu = perf_pmus__find_by_type(attr->type);
u32 type = attr->type; bool legacy_core_type = type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE;
if (!pmu && legacy_core_type && perf_pmus__supports_extended_type()) {
type = attr->config >> PERF_PMU_TYPE_SHIFT;
pmu = perf_pmus__find_by_type(type);
} if (!pmu && (legacy_core_type || type == PERF_TYPE_RAW)) { /* * For legacy events, if there was no extended type info then * assume the PMU is the first core PMU. * * On architectures like ARM there is no sysfs PMU with type * PERF_TYPE_RAW, assume the RAW events are going to be handled * by the first core PMU.
*/
pmu = perf_pmus__find_core_pmu();
} return pmu;
}
struct perf_pmu *perf_pmus__add_test_pmu(int test_sysfs_dirfd, constchar *name)
{ /* * Some PMU functions read from the sysfs mount point, so care is * needed, hence passing the eager_load flag to load things like the * format files.
*/ return perf_pmu__lookup(&other_pmus, test_sysfs_dirfd, name, /*eager_load=*/true);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.