Commit 486a7f46 authored by Shaokun Zhang's avatar Shaokun Zhang Committed by Will Deacon

drivers/perf: hisi: Add new functions for L3C PMU

On HiSilicon Hip09 platform, some new functions are enhanced on L3C PMU:

* tt_req: it is the abbreviation of tracetag request and allows user to
count only read/write/atomic operations. tt_req is 3-bit and details are
listed in the hisi-pmu document.
$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_req=0x4/ sleep 5

* tt_core: it is the abbreviation of tracetag core and allows user to
filter by core/thread within the cluster, it is a 8-bit bitmap that each
bit represents the corresponding core/thread in this L3C.
$# perf stat -a -e hisi_sccl3_l3c0/config=0x02,tt_core=0xf/ sleep 5

* datasrc_cfg: it is the abbreviation of data source configuration and
allows user to check where the data comes from, such as: from local DDR,
cross-die DDR or cross-socket DDR. Its is 5-bit and represents different
data source in the SoC.
$# perf stat -a -e hisi_sccl3_l3c0/dat_access,datasrc_cfg=0xe/ sleep 5

* datasrc_skt: it is the abbreviation of data source from another socket
and is used in the multi-chips, if user wants to check the cross-socket
datat source, it shall be added in perf command. Only one bit is used to
control this.
$# perf stat -a -e hisi_sccl3_l3c0/dat_access,datasrc_cfg=0x10,datasrc_skt=1/ sleep 5

Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: John Garry <john.garry@huawei.com>
Cc: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Reviewed-by: default avatarJohn Garry <john.garry@huawei.com>
Co-developed-by: default avatarQi Liu <liuqi115@huawei.com>
Signed-off-by: default avatarQi Liu <liuqi115@huawei.com>
Signed-off-by: default avatarShaokun Zhang <zhangshaokun@hisilicon.com>
Link: https://lore.kernel.org/r/1615186237-22263-5-git-send-email-zhangshaokun@hisilicon.comSigned-off-by: default avatarWill Deacon <will@kernel.org>
parent 3da582df
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include "hisi_uncore_pmu.h" #include "hisi_uncore_pmu.h"
#define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff) #define HISI_GET_EVENTID(ev) (ev->hw.config_base & 0xff)
#define HISI_MAX_PERIOD(nr) (BIT_ULL(nr) - 1) #define HISI_MAX_PERIOD(nr) (GENMASK_ULL((nr) - 1, 0))
/* /*
* PMU format attributes * PMU format attributes
...@@ -245,6 +245,9 @@ static void hisi_uncore_pmu_enable_event(struct perf_event *event) ...@@ -245,6 +245,9 @@ static void hisi_uncore_pmu_enable_event(struct perf_event *event)
hisi_pmu->ops->write_evtype(hisi_pmu, hwc->idx, hisi_pmu->ops->write_evtype(hisi_pmu, hwc->idx,
HISI_GET_EVENTID(event)); HISI_GET_EVENTID(event));
if (hisi_pmu->ops->enable_filter)
hisi_pmu->ops->enable_filter(event);
hisi_pmu->ops->enable_counter_int(hisi_pmu, hwc); hisi_pmu->ops->enable_counter_int(hisi_pmu, hwc);
hisi_pmu->ops->enable_counter(hisi_pmu, hwc); hisi_pmu->ops->enable_counter(hisi_pmu, hwc);
} }
...@@ -259,6 +262,9 @@ static void hisi_uncore_pmu_disable_event(struct perf_event *event) ...@@ -259,6 +262,9 @@ static void hisi_uncore_pmu_disable_event(struct perf_event *event)
hisi_pmu->ops->disable_counter(hisi_pmu, hwc); hisi_pmu->ops->disable_counter(hisi_pmu, hwc);
hisi_pmu->ops->disable_counter_int(hisi_pmu, hwc); hisi_pmu->ops->disable_counter_int(hisi_pmu, hwc);
if (hisi_pmu->ops->disable_filter)
hisi_pmu->ops->disable_filter(event);
} }
void hisi_uncore_pmu_set_event_period(struct perf_event *event) void hisi_uncore_pmu_set_event_period(struct perf_event *event)
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#ifndef __HISI_UNCORE_PMU_H__ #ifndef __HISI_UNCORE_PMU_H__
#define __HISI_UNCORE_PMU_H__ #define __HISI_UNCORE_PMU_H__
#include <linux/bitfield.h>
#include <linux/cpumask.h> #include <linux/cpumask.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -22,6 +23,7 @@ ...@@ -22,6 +23,7 @@
#undef pr_fmt #undef pr_fmt
#define pr_fmt(fmt) "hisi_pmu: " fmt #define pr_fmt(fmt) "hisi_pmu: " fmt
#define HISI_PMU_V2 0x30
#define HISI_MAX_COUNTERS 0x10 #define HISI_MAX_COUNTERS 0x10
#define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu)) #define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu))
...@@ -35,6 +37,12 @@ ...@@ -35,6 +37,12 @@
#define HISI_PMU_EVENT_ATTR(_name, _config) \ #define HISI_PMU_EVENT_ATTR(_name, _config) \
HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config) HISI_PMU_ATTR(_name, hisi_event_sysfs_show, (unsigned long)_config)
#define HISI_PMU_EVENT_ATTR_EXTRACTOR(name, config, hi, lo) \
static inline u32 hisi_get_##name(struct perf_event *event) \
{ \
return FIELD_GET(GENMASK_ULL(hi, lo), event->attr.config); \
}
struct hisi_pmu; struct hisi_pmu;
struct hisi_uncore_ops { struct hisi_uncore_ops {
...@@ -50,11 +58,14 @@ struct hisi_uncore_ops { ...@@ -50,11 +58,14 @@ struct hisi_uncore_ops {
void (*stop_counters)(struct hisi_pmu *); void (*stop_counters)(struct hisi_pmu *);
u32 (*get_int_status)(struct hisi_pmu *hisi_pmu); u32 (*get_int_status)(struct hisi_pmu *hisi_pmu);
void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx); void (*clear_int_status)(struct hisi_pmu *hisi_pmu, int idx);
void (*enable_filter)(struct perf_event *event);
void (*disable_filter)(struct perf_event *event);
}; };
struct hisi_pmu_hwevents { struct hisi_pmu_hwevents {
struct perf_event *hw_events[HISI_MAX_COUNTERS]; struct perf_event *hw_events[HISI_MAX_COUNTERS];
DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS); DECLARE_BITMAP(used_mask, HISI_MAX_COUNTERS);
const struct attribute_group **attr_groups;
}; };
/* Generic pmu struct for different pmu types */ /* Generic pmu struct for different pmu types */
......
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