]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
perf/x86/intel: Support RDPMC metrics clear mode
authorKan Liang <kan.liang@linux.intel.com>
Wed, 11 Dec 2024 16:03:17 +0000 (08:03 -0800)
committerPeter Zijlstra <peterz@infradead.org>
Fri, 20 Dec 2024 14:31:22 +0000 (15:31 +0100)
The new RDPMC enhancement, metrics clear mode, is to clear the
PERF_METRICS-related resources as well as the fixed-function performance
monitoring counter 3 after the read is performed. It is available for
ring 3. The feature is enumerated by the
IA32_PERF_CAPABILITIES.RDPMC_CLEAR_METRICS[bit 19]. To enable the
feature, the IA32_FIXED_CTR_CTRL.METRICS_CLEAR_EN[bit 14] must be set.

Two ways were considered to enable the feature.
- Expose a knob in the sysfs globally. One user may affect the
  measurement of other users when changing the knob. The solution is
  dropped.
- Introduce a new event format, metrics_clear, for the slots event to
  disable/enable the feature only for the current process. Users can
  utilize the feature as needed.
The latter solution is implemented in the patch.

The current KVM doesn't support the perf metrics yet. For
virtualization, the feature can be enabled later separately.

Suggested-by: Andi Kleen <ak@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/20241211160318.235056-1-kan.liang@linux.intel.com
arch/x86/events/intel/core.c
arch/x86/events/perf_event.h
arch/x86/include/asm/perf_event.h

index 2e1e268460500a44aa5f62394c23014ab7a0088d..e76e892f44cddcab52e3595ff0eb2ee4f69c3421 100644 (file)
@@ -2816,6 +2816,9 @@ static void intel_pmu_enable_fixed(struct perf_event *event)
                        return;
 
                idx = INTEL_PMC_IDX_FIXED_SLOTS;
+
+               if (event->attr.config1 & INTEL_TD_CFG_METRIC_CLEAR)
+                       bits |= INTEL_FIXED_3_METRICS_CLEAR;
        }
 
        intel_set_masks(event, idx);
@@ -4071,7 +4074,12 @@ static int intel_pmu_hw_config(struct perf_event *event)
         * is used in a metrics group, it too cannot support sampling.
         */
        if (intel_pmu_has_cap(event, PERF_CAP_METRICS_IDX) && is_topdown_event(event)) {
-               if (event->attr.config1 || event->attr.config2)
+               /* The metrics_clear can only be set for the slots event */
+               if (event->attr.config1 &&
+                   (!is_slots_event(event) || (event->attr.config1 & ~INTEL_TD_CFG_METRIC_CLEAR)))
+                       return -EINVAL;
+
+               if (event->attr.config2)
                        return -EINVAL;
 
                /*
@@ -4680,6 +4688,8 @@ PMU_FORMAT_ATTR(in_tx,  "config:32"       );
 PMU_FORMAT_ATTR(in_tx_cp, "config:33"  );
 PMU_FORMAT_ATTR(eq,    "config:36"     ); /* v6 + */
 
+PMU_FORMAT_ATTR(metrics_clear, "config1:0"); /* PERF_CAPABILITIES.RDPMC_METRICS_CLEAR */
+
 static ssize_t umask2_show(struct device *dev,
                           struct device_attribute *attr,
                           char *page)
@@ -4699,6 +4709,7 @@ static struct device_attribute format_attr_umask2  =
 static struct attribute *format_evtsel_ext_attrs[] = {
        &format_attr_umask2.attr,
        &format_attr_eq.attr,
+       &format_attr_metrics_clear.attr,
        NULL
 };
 
@@ -4723,6 +4734,13 @@ evtsel_ext_is_visible(struct kobject *kobj, struct attribute *attr, int i)
        if (i == 1)
                return (mask & ARCH_PERFMON_EVENTSEL_EQ) ? attr->mode : 0;
 
+       /* PERF_CAPABILITIES.RDPMC_METRICS_CLEAR */
+       if (i == 2) {
+               union perf_capabilities intel_cap = hybrid(dev_get_drvdata(dev), intel_cap);
+
+               return intel_cap.rdpmc_metrics_clear ? attr->mode : 0;
+       }
+
        return 0;
 }
 
index 82c6f45ce97552a175ab9ad047000fca0420dda8..31c2771545a6c66f919c0b73fc0ea00080ee3672 100644 (file)
@@ -624,6 +624,7 @@ union perf_capabilities {
                u64     pebs_output_pt_available:1;
                u64     pebs_timing_info:1;
                u64     anythread_deprecated:1;
+               u64     rdpmc_metrics_clear:1;
        };
        u64     capabilities;
 };
index cb9c4679f45c76a3993a44ba955927113388d86e..1ac79f361645648417a0b200e35cc2c1c5074fb2 100644 (file)
@@ -41,6 +41,7 @@
 #define INTEL_FIXED_0_USER                             (1ULL << 1)
 #define INTEL_FIXED_0_ANYTHREAD                        (1ULL << 2)
 #define INTEL_FIXED_0_ENABLE_PMI                       (1ULL << 3)
+#define INTEL_FIXED_3_METRICS_CLEAR                    (1ULL << 2)
 
 #define HSW_IN_TX                                      (1ULL << 32)
 #define HSW_IN_TX_CHECKPOINTED                         (1ULL << 33)
@@ -372,6 +373,9 @@ static inline bool use_fixed_pseudo_encoding(u64 code)
 #define INTEL_TD_METRIC_MAX                    INTEL_TD_METRIC_MEM_BOUND
 #define INTEL_TD_METRIC_NUM                    8
 
+#define INTEL_TD_CFG_METRIC_CLEAR_BIT          0
+#define INTEL_TD_CFG_METRIC_CLEAR              BIT_ULL(INTEL_TD_CFG_METRIC_CLEAR_BIT)
+
 static inline bool is_metric_idx(int idx)
 {
        return (unsigned)(idx - INTEL_PMC_IDX_METRIC_BASE) < INTEL_TD_METRIC_NUM;