Skip to content

Commit 80dac20

Browse files
committed
perf/x86/intel: Support PERFEVTSEL extension
JIRA: https://issues.redhat.com/browse/RHEL-20059 upstream ======== commit dce0c74 Author: Kan Liang <kan.liang@linux.intel.com> Date: Wed Jun 26 07:35:39 2024 -0700 description =========== 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: Dapeng Mi <dapeng1.mi@linux.intel.com> Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Andi Kleen <ak@linux.intel.com> Reviewed-by: Ian Rogers <irogers@google.com> Link: https://lkml.kernel.org/r/20240626143545.480761-8-kan.liang@linux.intel.com Signed-off-by: Michael Petlan <mpetlan@redhat.com>
1 parent 063f320 commit 80dac20

File tree

2 files changed

+69
-4
lines changed

2 files changed

+69
-4
lines changed

arch/x86/events/intel/core.c

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4631,8 +4631,55 @@ PMU_FORMAT_ATTR(pc, "config:19" );
46314631
PMU_FORMAT_ATTR(any, "config:21" ); /* v3 + */
46324632
PMU_FORMAT_ATTR(inv, "config:23" );
46334633
PMU_FORMAT_ATTR(cmask, "config:24-31" );
4634-
PMU_FORMAT_ATTR(in_tx, "config:32");
4635-
PMU_FORMAT_ATTR(in_tx_cp, "config:33");
4634+
PMU_FORMAT_ATTR(in_tx, "config:32" );
4635+
PMU_FORMAT_ATTR(in_tx_cp, "config:33" );
4636+
PMU_FORMAT_ATTR(eq, "config:36" ); /* v6 + */
4637+
4638+
static ssize_t umask2_show(struct device *dev,
4639+
struct device_attribute *attr,
4640+
char *page)
4641+
{
4642+
u64 mask = hybrid(dev_get_drvdata(dev), config_mask) & ARCH_PERFMON_EVENTSEL_UMASK2;
4643+
4644+
if (mask == ARCH_PERFMON_EVENTSEL_UMASK2)
4645+
return sprintf(page, "config:8-15,40-47\n");
4646+
4647+
/* Roll back to the old format if umask2 is not supported. */
4648+
return sprintf(page, "config:8-15\n");
4649+
}
4650+
4651+
static struct device_attribute format_attr_umask2 =
4652+
__ATTR(umask, 0444, umask2_show, NULL);
4653+
4654+
static struct attribute *format_evtsel_ext_attrs[] = {
4655+
&format_attr_umask2.attr,
4656+
&format_attr_eq.attr,
4657+
NULL
4658+
};
4659+
4660+
static umode_t
4661+
evtsel_ext_is_visible(struct kobject *kobj, struct attribute *attr, int i)
4662+
{
4663+
struct device *dev = kobj_to_dev(kobj);
4664+
u64 mask;
4665+
4666+
/*
4667+
* The umask and umask2 have different formats but share the
4668+
* same attr name. In update mode, the previous value of the
4669+
* umask is unconditionally removed before is_visible. If
4670+
* umask2 format is not enumerated, it's impossible to roll
4671+
* back to the old format.
4672+
* Does the check in umask2_show rather than is_visible.
4673+
*/
4674+
if (i == 0)
4675+
return attr->mode;
4676+
4677+
mask = hybrid(dev_get_drvdata(dev), config_mask);
4678+
if (i == 1)
4679+
return (mask & ARCH_PERFMON_EVENTSEL_EQ) ? attr->mode : 0;
4680+
4681+
return 0;
4682+
}
46364683

46374684
static struct attribute *intel_arch_formats_attr[] = {
46384685
&format_attr_event.attr,
@@ -4785,8 +4832,14 @@ static inline bool intel_pmu_broken_perf_cap(void)
47854832

47864833
static void update_pmu_cap(struct x86_hybrid_pmu *pmu)
47874834
{
4788-
unsigned int sub_bitmaps = cpuid_eax(ARCH_PERFMON_EXT_LEAF);
4789-
unsigned int eax, ebx, ecx, edx;
4835+
unsigned int sub_bitmaps, eax, ebx, ecx, edx;
4836+
4837+
cpuid(ARCH_PERFMON_EXT_LEAF, &sub_bitmaps, &ebx, &ecx, &edx);
4838+
4839+
if (ebx & ARCH_PERFMON_EXT_UMASK2)
4840+
pmu->config_mask |= ARCH_PERFMON_EVENTSEL_UMASK2;
4841+
if (ebx & ARCH_PERFMON_EXT_EQ)
4842+
pmu->config_mask |= ARCH_PERFMON_EVENTSEL_EQ;
47904843

47914844
if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) {
47924845
cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF,
@@ -5816,6 +5869,12 @@ static struct attribute_group group_format_extra_skl = {
58165869
.is_visible = exra_is_visible,
58175870
};
58185871

5872+
static struct attribute_group group_format_evtsel_ext = {
5873+
.name = "format",
5874+
.attrs = format_evtsel_ext_attrs,
5875+
.is_visible = evtsel_ext_is_visible,
5876+
};
5877+
58195878
static struct attribute_group group_default = {
58205879
.attrs = intel_pmu_attrs,
58215880
.is_visible = default_is_visible,
@@ -5829,6 +5888,7 @@ static const struct attribute_group *attr_update[] = {
58295888
&group_caps_lbr,
58305889
&group_format_extra,
58315890
&group_format_extra_skl,
5891+
&group_format_evtsel_ext,
58325892
&group_default,
58335893
NULL,
58345894
};
@@ -6048,6 +6108,7 @@ static const struct attribute_group *hybrid_attr_update[] = {
60486108
&group_caps_gen,
60496109
&group_caps_lbr,
60506110
&hybrid_group_format_extra,
6111+
&group_format_evtsel_ext,
60516112
&group_default,
60526113
&hybrid_group_cpus,
60536114
NULL,

arch/x86/include/asm/perf_event.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#define ARCH_PERFMON_EVENTSEL_INV (1ULL << 23)
3333
#define ARCH_PERFMON_EVENTSEL_CMASK 0xFF000000ULL
3434
#define ARCH_PERFMON_EVENTSEL_BR_CNTR (1ULL << 35)
35+
#define ARCH_PERFMON_EVENTSEL_EQ (1ULL << 36)
36+
#define ARCH_PERFMON_EVENTSEL_UMASK2 (0xFFULL << 40)
3537

3638
#define INTEL_FIXED_BITS_MASK 0xFULL
3739
#define INTEL_FIXED_BITS_STRIDE 4
@@ -185,6 +187,8 @@ union cpuid10_edx {
185187
* detection/enumeration details:
186188
*/
187189
#define ARCH_PERFMON_EXT_LEAF 0x00000023
190+
#define ARCH_PERFMON_EXT_UMASK2 0x1
191+
#define ARCH_PERFMON_EXT_EQ 0x2
188192
#define ARCH_PERFMON_NUM_COUNTER_LEAF_BIT 0x1
189193
#define ARCH_PERFMON_NUM_COUNTER_LEAF 0x1
190194

0 commit comments

Comments
 (0)