Skip to content

Commit dce0c74

Browse files
Kan LiangPeter Zijlstra
authored andcommitted
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: Dapeng Mi <[email protected]> Signed-off-by: Dapeng Mi <[email protected]> Signed-off-by: Kan Liang <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Andi Kleen <[email protected]> Reviewed-by: Ian Rogers <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent e8fb5d6 commit dce0c74

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

46384685
static struct attribute *intel_arch_formats_attr[] = {
46394686
&format_attr_event.attr,
@@ -4786,8 +4833,14 @@ static inline bool intel_pmu_broken_perf_cap(void)
47864833

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

47924845
if (sub_bitmaps & ARCH_PERFMON_NUM_COUNTER_LEAF_BIT) {
47934846
cpuid_count(ARCH_PERFMON_EXT_LEAF, ARCH_PERFMON_NUM_COUNTER_LEAF,
@@ -5810,6 +5863,12 @@ static struct attribute_group group_format_extra_skl = {
58105863
.is_visible = exra_is_visible,
58115864
};
58125865

5866+
static struct attribute_group group_format_evtsel_ext = {
5867+
.name = "format",
5868+
.attrs = format_evtsel_ext_attrs,
5869+
.is_visible = evtsel_ext_is_visible,
5870+
};
5871+
58135872
static struct attribute_group group_default = {
58145873
.attrs = intel_pmu_attrs,
58155874
.is_visible = default_is_visible,
@@ -5823,6 +5882,7 @@ static const struct attribute_group *attr_update[] = {
58235882
&group_caps_lbr,
58245883
&group_format_extra,
58255884
&group_format_extra_skl,
5885+
&group_format_evtsel_ext,
58265886
&group_default,
58275887
NULL,
58285888
};
@@ -6042,6 +6102,7 @@ static const struct attribute_group *hybrid_attr_update[] = {
60426102
&group_caps_gen,
60436103
&group_caps_lbr,
60446104
&hybrid_group_format_extra,
6105+
&group_format_evtsel_ext,
60456106
&group_default,
60466107
&hybrid_group_cpus,
60476108
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)