Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d108caa authored by Ashwin Chaugule's avatar Ashwin Chaugule Committed by Stephen Boyd
Browse files

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: default avatarAshwin Chaugule <ashwinc@codeaurora.org>
parent bc9b0644
Loading
Loading
Loading
Loading
+38 −11
Original line number Diff line number Diff line
@@ -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 @@ struct pmu_constraints {
};

/* 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 const struct attribute_group *msm_l2_pmu_attr_grps[] = {

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 @@ static void set_evres(int event_groupsel, int event_reg, int event_group_code)
	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 @@ static void krait_l2_enable(struct hw_perf_event *hwc, int idx, int cpu)
{
	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 @@ static void krait_l2_enable(struct hw_perf_event *hwc, int idx, int cpu)
		  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 @@ next:
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 @@ krait_l2_pmu_generic_free_irq(int irq)

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 @@ out:

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 @@ static struct arm_pmu krait_l2_pmu = {
	.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,
+36 −10
Original line number Diff line number Diff line
@@ -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 u32 pmu_type;

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 @@ static unsigned int get_scorpion_l2_evtinfo(unsigned int evt_type,
	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 @@ static inline void scorpion_l2_set_evtyper(int ctr, int val)
	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 @@ static void scorpion_l2_enable(struct hw_perf_event *hwc, int idx, int cpu)
	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 @@ static void scorpion_l2_enable(struct hw_perf_event *hwc, int idx, int cpu)
	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 @@ next:
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 @@ scorpion_l2_pmu_generic_free_irq(int irq)

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 @@ out:

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;