Commit dce0c74d authored by Kan Liang's avatar Kan Liang Committed by Peter Zijlstra

perf/x86/intel: Support PERFEVTSEL extension

Two new fields (the unit mask2, and the equal flag) are added in the
IA32_PERFEVTSELx MSRs. They can be enumerated by the CPUID.23H.0.EBX.

Update the config_mask in x86_pmu and x86_hybrid_pmu for the true layout
of the PERFEVTSEL.
Expose the new formats into sysfs if they are available. The umask
extension reuses the same format attr name "umask" as the previous
umask. Add umask2_show to determine/display the correct format
for the current machine.
Co-developed-by: default avatarDapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: default avatarDapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: default avatarKan Liang <kan.liang@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: default avatarAndi Kleen <ak@linux.intel.com>
Reviewed-by: default avatarIan Rogers <irogers@google.com>
Link: https://lkml.kernel.org/r/20240626143545.480761-8-kan.liang@linux.intel.com
parent e8fb5d6e
...@@ -4632,8 +4632,55 @@ PMU_FORMAT_ATTR(pc, "config:19" ); ...@@ -4632,8 +4632,55 @@ PMU_FORMAT_ATTR(pc, "config:19" );
PMU_FORMAT_ATTR(any, "config:21" ); /* v3 + */ PMU_FORMAT_ATTR(any, "config:21" ); /* v3 + */
PMU_FORMAT_ATTR(inv, "config:23" ); PMU_FORMAT_ATTR(inv, "config:23" );
PMU_FORMAT_ATTR(cmask, "config:24-31" ); PMU_FORMAT_ATTR(cmask, "config:24-31" );
PMU_FORMAT_ATTR(in_tx, "config:32"); PMU_FORMAT_ATTR(in_tx, "config:32" );
PMU_FORMAT_ATTR(in_tx_cp, "config:33"); PMU_FORMAT_ATTR(in_tx_cp, "config:33" );
PMU_FORMAT_ATTR(eq, "config:36" ); /* v6 + */
static ssize_t umask2_show(struct device *dev,
struct device_attribute *attr,
char *page)
{
u64 mask = hybrid(dev_get_drvdata(dev), config_mask) & ARCH_PERFMON_EVENTSEL_UMASK2;
if (mask == ARCH_PERFMON_EVENTSEL_UMASK2)
return sprintf(page, "config:8-15,40-47\n");
/* Roll back to the old format if umask2 is not supported. */
return sprintf(page, "config:8-15\n");
}
static struct device_attribute format_attr_umask2 =
__ATTR(umask, 0444, umask2_show, NULL);
static struct attribute *format_evtsel_ext_attrs[] = {
&format_attr_umask2.attr,
&format_attr_eq.attr,
NULL
};
static umode_t
evtsel_ext_is_visible(struct kobject *kobj, struct attribute *attr, int i)
{
struct device *dev = kobj_to_dev(kobj);
u64 mask;
/*
* The umask and umask2 have different formats but share the
* same attr name. In update mode, the previous value of the
* umask is unconditionally removed before is_visible. If
* umask2 format is not enumerated, it's impossible to roll
* back to the old format.
* Does the check in umask2_show rather than is_visible.
*/
if (i == 0)
return attr->mode;
mask = hybrid(dev_get_drvdata(dev), config_mask);
if (i == 1)
return (mask & ARCH_PERFMON_EVENTSEL_EQ) ? attr->mode : 0;
return 0;
}
static struct attribute *intel_arch_formats_attr[] = { static struct attribute *intel_arch_formats_attr[] = {
&format_attr_event.attr, &format_attr_event.attr,
...@@ -4786,8 +4833,14 @@ static inline bool intel_pmu_broken_perf_cap(void) ...@@ -4786,8 +4833,14 @@ static inline bool intel_pmu_broken_perf_cap(void)
static void update_pmu_cap(struct x86_hybrid_pmu *pmu) static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
{ {
unsigned int sub_bitmaps = cpuid_eax(ARCH_PERFMON_EXT_LEAF); unsigned int sub_bitmaps, eax, ebx, ecx, edx;
unsigned int eax, ebx, ecx, edx;
cpuid(ARCH_PERFMON_EXT_LEAF, &sub_bitmaps, &ebx, &ecx, &edx);
if (ebx & ARCH_PERFMON_EXT_UMASK2)
pmu->config_mask |= ARCH_PERFMON_EVENTSEL_UMASK2;
if (ebx & ARCH_PERFMON_EXT_EQ)
pmu->config_mask |= ARCH_PERFMON_EVENTSEL_EQ;
if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) { if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) {
cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF, cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF,
...@@ -5810,6 +5863,12 @@ static struct attribute_group group_format_extra_skl = { ...@@ -5810,6 +5863,12 @@ static struct attribute_group group_format_extra_skl = {
.is_visible = exra_is_visible, .is_visible = exra_is_visible,
}; };
static struct attribute_group group_format_evtsel_ext = {
.name = "format",
.attrs = format_evtsel_ext_attrs,
.is_visible = evtsel_ext_is_visible,
};
static struct attribute_group group_default = { static struct attribute_group group_default = {
.attrs = intel_pmu_attrs, .attrs = intel_pmu_attrs,
.is_visible = default_is_visible, .is_visible = default_is_visible,
...@@ -5823,6 +5882,7 @@ static const struct attribute_group *attr_update[] = { ...@@ -5823,6 +5882,7 @@ static const struct attribute_group *attr_update[] = {
&group_caps_lbr, &group_caps_lbr,
&group_format_extra, &group_format_extra,
&group_format_extra_skl, &group_format_extra_skl,
&group_format_evtsel_ext,
&group_default, &group_default,
NULL, NULL,
}; };
...@@ -6042,6 +6102,7 @@ static const struct attribute_group *hybrid_attr_update[] = { ...@@ -6042,6 +6102,7 @@ static const struct attribute_group *hybrid_attr_update[] = {
&group_caps_gen, &group_caps_gen,
&group_caps_lbr, &group_caps_lbr,
&hybrid_group_format_extra, &hybrid_group_format_extra,
&group_format_evtsel_ext,
&group_default, &group_default,
&hybrid_group_cpus, &hybrid_group_cpus,
NULL, NULL,
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23) #define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23)
#define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL #define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL
#define ARCH_PERFMON_EVENTSEL_BR_CNTR (1ULL << 35) #define ARCH_PERFMON_EVENTSEL_BR_CNTR (1ULL << 35)
#define ARCH_PERFMON_EVENTSEL_EQ (1ULL << 36)
#define ARCH_PERFMON_EVENTSEL_UMASK2 (0xFFULL << 40)
#define INTEL_FIXED_BITS_MASK 0xFULL #define INTEL_FIXED_BITS_MASK 0xFULL
#define INTEL_FIXED_BITS_STRIDE 4 #define INTEL_FIXED_BITS_STRIDE 4
...@@ -185,6 +187,8 @@ union cpuid10_edx { ...@@ -185,6 +187,8 @@ union cpuid10_edx {
* detection/enumeration details: * detection/enumeration details:
*/ */
#define ARCH_PERFMON_EXT_LEAF 0x00000023 #define ARCH_PERFMON_EXT_LEAF 0x00000023
#define ARCH_PERFMON_EXT_UMASK2 0x1
#define ARCH_PERFMON_EXT_EQ 0x2
#define ARCH_PERFMON_NUM_COUNTER_LEAF_BIT 0x1 #define ARCH_PERFMON_NUM_COUNTER_LEAF_BIT 0x1
#define ARCH_PERFMON_NUM_COUNTER_LEAF 0x1 #define ARCH_PERFMON_NUM_COUNTER_LEAF 0x1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment