Perf: Add L2 slave port filtering
The L2CC PMU's can filter traffic at the L2 slave port.
This patch allows the user to count non-CPU master events.
Change-Id: I42283a0902b8e746cb86440d423136ae394e7cd6
Signed-off-by: Ashwin Chaugule <ashwinc@codeaurora.org>
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index 22dbff3..5f76a92 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -21,6 +21,10 @@
#define MAX_L2_PERIOD ((1ULL << 32) - 1)
#define MAX_KRAIT_L2_CTRS 5
+#define L2_EVT_MASK 0xfffff
+
+#define L2_SLAVE_EV_PREFIX 4
+
#define L2PMCCNTR 0x409
#define L2PMCCNTCR 0x408
#define L2PMCCNTSR 0x40A
@@ -49,9 +53,12 @@
/* event format is -e rsRCCG See get_event_desc() */
-#define EVENT_REG_MASK 0xf000
-#define EVENT_GROUPSEL_MASK 0x000f
-#define EVENT_GROUPCODE_MASK 0x0ff0
+#define EVENT_PREFIX_MASK 0xf0000
+#define EVENT_REG_MASK 0x0f000
+#define EVENT_GROUPSEL_MASK 0x0000f
+#define EVENT_GROUPCODE_MASK 0x00ff0
+
+#define EVENT_PREFIX_SHIFT 16
#define EVENT_REG_SHIFT 12
#define EVENT_GROUPCODE_SHIFT 4
@@ -70,11 +77,13 @@
};
/* NRCCG format for perf RAW codes. */
+PMU_FORMAT_ATTR(l2_prefix, "config:16-19");
PMU_FORMAT_ATTR(l2_reg, "config:12-15");
PMU_FORMAT_ATTR(l2_code, "config:4-11");
PMU_FORMAT_ATTR(l2_grp, "config:0-3");
static struct attribute *msm_l2_ev_formats[] = {
+ &format_attr_l2_prefix.attr,
&format_attr_l2_reg.attr,
&format_attr_l2_code.attr,
&format_attr_l2_grp.attr,
@@ -97,6 +106,9 @@
static u32 l2_orig_filter_prefix = 0x000f0030;
+/* L2 slave port traffic filtering */
+static u32 l2_slv_filter_prefix = 0x000f0010;
+
static u32 pmu_type;
static struct arm_pmu krait_l2_pmu;
@@ -167,19 +179,25 @@
set_l2_indirect_reg(group_reg, resr_val);
}
-static void set_evfilter_task_mode(int ctr)
+static void set_evfilter_task_mode(int ctr, unsigned int is_slv)
{
u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
u32 filter_val = l2_orig_filter_prefix | 1 << smp_processor_id();
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
+
set_l2_indirect_reg(filter_reg, filter_val);
}
-static void set_evfilter_sys_mode(int ctr)
+static void set_evfilter_sys_mode(int ctr, unsigned int is_slv)
{
u32 filter_reg = (ctr * 16) + IA_L2PMXEVFILTER_BASE;
u32 filter_val = l2_orig_filter_prefix | 0xf;
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
+
set_l2_indirect_reg(filter_reg, filter_val);
}
@@ -251,12 +269,21 @@
{
struct event_desc evdesc;
unsigned long iflags;
+ unsigned int is_slv = 0;
+ unsigned int evt_prefix;
raw_spin_lock_irqsave(&krait_l2_pmu_hw_events.pmu_lock, iflags);
if (hwc->config_base == L2CYCLE_CTR_RAW_CODE)
goto out;
+ /* Check if user requested any special origin filtering. */
+ evt_prefix = (hwc->config_base &
+ EVENT_PREFIX_MASK) >> EVENT_PREFIX_SHIFT;
+
+ if (evt_prefix == L2_SLAVE_EV_PREFIX)
+ is_slv = 1;
+
set_evcntcr(idx);
memset(&evdesc, 0, sizeof(evdesc));
@@ -269,9 +296,9 @@
evdesc.event_group_code);
if (cpu < 0)
- set_evfilter_task_mode(idx);
+ set_evfilter_task_mode(idx, is_slv);
else
- set_evfilter_sys_mode(idx);
+ set_evfilter_sys_mode(idx, is_slv);
out:
enable_intenset(idx);
@@ -397,7 +424,7 @@
static int krait_l2_map_event(struct perf_event *event)
{
if (pmu_type > 0 && pmu_type == event->attr.type)
- return event->attr.config & 0xffff;
+ return event->attr.config & L2_EVT_MASK;
else
return -ENOENT;
}
@@ -419,7 +446,7 @@
static int msm_l2_test_set_ev_constraint(struct perf_event *event)
{
- u32 evt_type = event->attr.config & 0xffff;
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
u8 reg = (evt_type & 0x0F000) >> 12;
u8 group = evt_type & 0x0000F;
unsigned long flags;
@@ -444,7 +471,7 @@
static int msm_l2_clear_ev_constraint(struct perf_event *event)
{
- u32 evt_type = event->attr.config & 0xffff;
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
u8 reg = (evt_type & 0x0F000) >> 12;
u8 group = evt_type & 0x0000F;
unsigned long flags;
@@ -476,7 +503,7 @@
.read_counter = krait_l2_read_counter,
.write_counter = krait_l2_write_counter,
.map_event = krait_l2_map_event,
- .max_period = (1LLU << 32) - 1,
+ .max_period = MAX_L2_PERIOD,
.get_hw_events = krait_l2_get_hw_events,
.num_events = MAX_KRAIT_L2_CTRS,
.test_set_event_constraints = msm_l2_test_set_ev_constraint,
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
index e3ab64a..5a5bf57 100644
--- a/arch/arm/mach-msm/perf_event_msm_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_l2.c
@@ -24,6 +24,11 @@
#define SCORPION_L2_EVT_PREFIX 3
#define SCORPION_MAX_L2_REG 4
+#define L2_EVT_MASK 0xfffff
+#define L2_EVT_PREFIX_MASK 0xf0000
+#define L2_EVT_PREFIX_SHIFT 16
+#define L2_SLAVE_EVT_PREFIX 4
+
/*
* The L2 PMU is shared between all CPU's, so protect
@@ -69,6 +74,11 @@
static struct arm_pmu scorpion_l2_pmu;
+static u32 l2_orig_filter_prefix = 0x000f0030;
+
+/* L2 slave port traffic filtering */
+static u32 l2_slv_filter_prefix = 0x000f0010;
+
static struct perf_event *l2_events[MAX_SCORPION_L2_CTRS];
static unsigned long l2_used_mask[BITS_TO_LONGS(MAX_SCORPION_L2_CTRS)];
@@ -418,7 +428,8 @@
u8 group;
prefix = (evt_type & 0xF0000) >> 16;
- if (prefix == SCORPION_L2_EVT_PREFIX) {
+ if (prefix == SCORPION_L2_EVT_PREFIX ||
+ prefix == L2_SLAVE_EVT_PREFIX) {
reg = (evt_type & 0x0F000) >> 12;
code = (evt_type & 0x00FF0) >> 4;
group = evt_type & 0x0000F;
@@ -475,16 +486,22 @@
asm volatile ("mcr p15, 3, %0, c15, c6, 7" : : "r" (val));
}
-static void scorpion_l2_set_evfilter_task_mode(void)
+static void scorpion_l2_set_evfilter_task_mode(unsigned int is_slv)
{
- u32 filter_val = 0x000f0030 | 1 << smp_processor_id();
+ u32 filter_val = l2_orig_filter_prefix | 1 << smp_processor_id();
+
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
}
-static void scorpion_l2_set_evfilter_sys_mode(void)
+static void scorpion_l2_set_evfilter_sys_mode(unsigned int is_slv)
{
- u32 filter_val = 0x000f003f;
+ u32 filter_val = l2_orig_filter_prefix | 0xf;
+
+ if (is_slv)
+ filter_val = l2_slv_filter_prefix;
asm volatile ("mcr p15, 3, %0, c15, c6, 3" : : "r" (filter_val));
}
@@ -584,12 +601,21 @@
int evtype = hwc->config_base;
int ev_typer;
unsigned long iflags;
+ unsigned int is_slv = 0;
+ unsigned int evt_prefix;
raw_spin_lock_irqsave(&scorpion_l2_pmu_hw_events.pmu_lock, iflags);
if (hwc->config_base == SCORPION_L2CYCLE_CTR_RAW_CODE)
goto out;
+ /* Check if user requested any special origin filtering. */
+ evt_prefix = (hwc->config_base &
+ L2_EVT_PREFIX_MASK) >> L2_EVT_PREFIX_SHIFT;
+
+ if (evt_prefix == L2_SLAVE_EVT_PREFIX)
+ is_slv = 1;
+
memset(&evtinfo, 0, sizeof(evtinfo));
ev_typer = get_scorpion_l2_evtinfo(evtype, &evtinfo);
@@ -599,9 +625,9 @@
scorpion_l2_set_evcntcr();
if (cpu < 0)
- scorpion_l2_set_evfilter_task_mode();
+ scorpion_l2_set_evfilter_task_mode(is_slv);
else
- scorpion_l2_set_evfilter_sys_mode();
+ scorpion_l2_set_evfilter_sys_mode(is_slv);
scorpion_l2_evt_setup(evtinfo.grp, evtinfo.val);
@@ -735,7 +761,7 @@
static int scorpion_l2_map_event(struct perf_event *event)
{
if (pmu_type > 0 && pmu_type == event->attr.type)
- return event->attr.config & 0xfffff;
+ return event->attr.config & L2_EVT_MASK;
else
return -ENOENT;
}
@@ -757,7 +783,7 @@
static int msm_l2_test_set_ev_constraint(struct perf_event *event)
{
- u32 evt_type = event->attr.config & 0xfffff;
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
u8 prefix = (evt_type & 0xF0000) >> 16;
u8 reg = (evt_type & 0x0F000) >> 12;
u8 group = evt_type & 0x0000F;
@@ -787,7 +813,7 @@
static int msm_l2_clear_ev_constraint(struct perf_event *event)
{
- u32 evt_type = event->attr.config & 0xfffff;
+ u32 evt_type = event->attr.config & L2_EVT_MASK;
u8 prefix = (evt_type & 0xF0000) >> 16;
u8 reg = (evt_type & 0x0F000) >> 12;
u8 group = evt_type & 0x0000F;