linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] ARCv2 port to Linux - (C) perf
@ 2015-06-09 12:19 Vineet Gupta
  2015-06-09 12:19 ` [PATCH 1/8] ARC: perf: support RAW events Vineet Gupta
                   ` (7 more replies)
  0 siblings, 8 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Vineet Gupta

Hi Peter,

This mini-series adds perf support for ARCv2 based cores, which brings in
overflow interupts and SMP. Additionally now raw events are supported as well.

This is part of series which adds ARCv2 ISA support to linux.

Please see [1] for prep patches and [2] for actual port. I've CC'ed you
for some of the patches related to barriers, atomic ops in [2].

Some more info at
 - www.synopsys.com/dw/ipdir.php?ds=arc-hs38-processor
 - http://news.synopsys.com/2014-10-14-New-DesignWare-ARC-HS38-Processor-Doubles-Performance-for-Embedded-Linux-Applications
 - http://www.embedded.com/electronics-news/4435975/Synopsys-ARC-HS38-core-gives-2X-boost-to-Linux-based-apps

Please review !

Thx,
-Vineet

[1] https://lkml.org/lkml/2015/6/7/25
[2] http://www.spinics.net/lists/kernel/msg2009508.html

Alexey Brodkin (6):
  ARC: perf: support RAW events
  ARCv2: perf: implement "event_set_period" for future use with
    interrupts
  ARCv2: perf: Support sampling events using overflow interrupts
  ARCv2: perf: set usable max period as a half of real max period
  ARCv2: perf: implement exclusion of event counting in user or kernel
    mode
  ARCv2: perf: SMP support

Vineet Gupta (2):
  ARC: perf: cap the number of counters to hardware max of 32
  ARCv2: perf: Finally introduce HS perf unit

 .../devicetree/bindings/arc/archs-pct.txt          |  17 ++
 arch/arc/include/asm/perf_event.h                  |  24 +-
 arch/arc/kernel/perf_event.c                       | 310 +++++++++++++++++++--
 3 files changed, 326 insertions(+), 25 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/archs-pct.txt

-- 
1.9.1


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/8] ARC: perf: support RAW events
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  2015-06-15 15:30   ` Peter Zijlstra
  2015-06-09 12:19 ` [PATCH 2/8] ARC: perf: cap the number of counters to hardware max of 32 Vineet Gupta
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Vineet Gupta

From: Alexey Brodkin <abrodkin@synopsys.com>

To run perf against raw event user may issue following command:
--->---
Initializing raw event: crun

 Performance counter stats for 'sleep 0':

            583202 r6372756e

       0.020000000 seconds time elapsed
--->---

"-e rXXX" is indication of raw event to count.
XXX is 64-bit ASCII value.
0x6372756e = crun (in ASCII)

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/perf_event.h |  3 +++
 arch/arc/kernel/perf_event.c      | 54 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
index 2b8880e953a2..ea43477f8a59 100644
--- a/arch/arc/include/asm/perf_event.h
+++ b/arch/arc/include/asm/perf_event.h
@@ -15,6 +15,9 @@
 /* real maximum varies per CPU, this is the maximum supported by the driver */
 #define ARC_PMU_MAX_HWEVENTS	64
 
+/* Max number of countable events that CPU may have */
+#define ARC_PERF_MAX_EVENTS	256
+
 #define ARC_REG_CC_BUILD	0xF6
 #define ARC_REG_CC_INDEX	0x240
 #define ARC_REG_CC_NAME0	0x241
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index eea8a7b42e87..400965973bb0 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -22,8 +22,10 @@ struct arc_pmu {
 	struct pmu	pmu;
 	int		counter_size;	/* in bits */
 	int		n_counters;
+	int		n_events;
 	unsigned long	used_mask[BITS_TO_LONGS(ARC_PMU_MAX_HWEVENTS)];
 	int		ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
+	u64             raw_events[ARC_PERF_MAX_EVENTS];
 };
 
 struct arc_callchain_trace {
@@ -136,6 +138,44 @@ static int arc_pmu_cache_event(u64 config)
 	return ret;
 }
 
+/*
+ * Raw events are specified in hex value of ASCII chars:
+ *
+ * In PCT register CC_NAME{0,1} event name string[] is saved from LSB side:
+ * e.g. cycles corresponds to ARC "crun" and is saved as 0x6e757263
+ *							    n u r c
+ * However in perf cmdline they are specified in human order as r6372756e
+ *
+ * Thus event from cmdline requires an word swap
+ */
+static int arc_pmu_raw_event(u64 config)
+{
+	int i;
+	char name[sizeof(u64) + 1] = {0};
+	u64 swapped = __swab64(config);
+
+	/* Trim leading zeroes */
+	for (i = 0; i < sizeof(u64); i++)
+		if (!(swapped & 0xFF))
+			swapped = swapped >> 8;
+		else
+			break;
+
+	for (i = 0; i < arc_pmu->n_events; i++) {
+		if (swapped == arc_pmu->raw_events[i])
+			break;
+	}
+
+	if (i == arc_pmu->n_events)
+		return -ENOENT;
+
+	memcpy(name, &swapped, sizeof(u64));
+
+	pr_debug("Initializing raw event: %s\n", name);
+
+	return i;
+}
+
 /* initializes hw_perf_event structure if event is supported */
 static int arc_pmu_event_init(struct perf_event *event)
 {
@@ -159,6 +199,14 @@ static int arc_pmu_event_init(struct perf_event *event)
 			return ret;
 		hwc->config = arc_pmu->ev_hw_idx[ret];
 		return 0;
+
+	case PERF_TYPE_RAW:
+		ret = arc_pmu_raw_event(event->attr.config);
+		if (ret < 0)
+			return ret;
+		hwc->config |= ret;
+		return 0;
+
 	default:
 		return -ENOENT;
 	}
@@ -289,6 +337,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
 	READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
 	BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */
+	BUG_ON(cc_bcr.c > ARC_PERF_MAX_EVENTS);
 
 	arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
 	if (!arc_pmu)
@@ -300,6 +349,8 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 	pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
 		arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c);
 
+	arc_pmu->n_events = cc_bcr.c;
+
 	cc_name.str[8] = 0;
 	for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++)
 		arc_pmu->ev_hw_idx[i] = -1;
@@ -310,6 +361,9 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 		cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
 		cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
 
+		arc_pmu->raw_events[j] = ((u64)cc_name.indiv.word1 << 32) |
+						cc_name.indiv.word0;
+
 		/* See if it has been mapped to a perf event_id */
 		for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
 			if (arc_pmu_ev_hw_map[i] &&
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 2/8] ARC: perf: cap the number of counters to hardware max of 32
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
  2015-06-09 12:19 ` [PATCH 1/8] ARC: perf: support RAW events Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  2015-06-09 12:19 ` [PATCH 3/8] ARCv2: perf: implement "event_set_period" for future use with interrupts Vineet Gupta
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Vineet Gupta,
	Peter Zijlstra, Arnaldo Carvalho de Melo

The number of counters in PCT can never be more than 32 (while countable
conditions could be 100+) for both ARCompact and ARCv2

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/perf_event.h | 5 +++--
 arch/arc/kernel/perf_event.c      | 4 ++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
index ea43477f8a59..ca8c414738de 100644
--- a/arch/arc/include/asm/perf_event.h
+++ b/arch/arc/include/asm/perf_event.h
@@ -1,6 +1,7 @@
 /*
  * Linux performance counter support for ARC
  *
+ * Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.com)
  * Copyright (C) 2011-2013 Synopsys, Inc. (www.synopsys.com)
  *
  * This program is free software; you can redistribute it and/or modify
@@ -12,8 +13,8 @@
 #ifndef __ASM_PERF_EVENT_H
 #define __ASM_PERF_EVENT_H
 
-/* real maximum varies per CPU, this is the maximum supported by the driver */
-#define ARC_PMU_MAX_HWEVENTS	64
+/* Max number of counters that PCT block may ever have */
+#define ARC_PERF_MAX_COUNTERS	32
 
 /* Max number of countable events that CPU may have */
 #define ARC_PERF_MAX_EVENTS	256
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 400965973bb0..18b074f63cb6 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -23,7 +23,7 @@ struct arc_pmu {
 	int		counter_size;	/* in bits */
 	int		n_counters;
 	int		n_events;
-	unsigned long	used_mask[BITS_TO_LONGS(ARC_PMU_MAX_HWEVENTS)];
+	unsigned long	used_mask[BITS_TO_LONGS(ARC_PERF_MAX_COUNTERS)];
 	int		ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
 	u64             raw_events[ARC_PERF_MAX_EVENTS];
 };
@@ -333,7 +333,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 		pr_err("This core does not have performance counters!\n");
 		return -ENODEV;
 	}
-	BUG_ON(pct_bcr.c > ARC_PMU_MAX_HWEVENTS);
+	BUG_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS);
 
 	READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
 	BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 3/8] ARCv2: perf: implement "event_set_period" for future use with interrupts
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
  2015-06-09 12:19 ` [PATCH 1/8] ARC: perf: support RAW events Vineet Gupta
  2015-06-09 12:19 ` [PATCH 2/8] ARC: perf: cap the number of counters to hardware max of 32 Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  2015-06-15 15:38   ` Peter Zijlstra
  2015-06-09 12:19 ` [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts Vineet Gupta
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Vineet Gupta

From: Alexey Brodkin <abrodkin@synopsys.com>

This generalization prepares for support of overflow interrupts.

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
[vgupta: Fixed up so @counter need not be in struct arc_pmu

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/kernel/perf_event.c | 67 +++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 7 deletions(-)

diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 18b074f63cb6..065daed8ad5f 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -20,10 +20,10 @@
 
 struct arc_pmu {
 	struct pmu	pmu;
-	int		counter_size;	/* in bits */
 	int		n_counters;
 	int		n_events;
 	unsigned long	used_mask[BITS_TO_LONGS(ARC_PERF_MAX_COUNTERS)];
+	u64		max_period;
 	int		ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
 	u64             raw_events[ARC_PERF_MAX_EVENTS];
 };
@@ -99,8 +99,7 @@ static void arc_perf_event_update(struct perf_event *event,
 	} while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
 				 new_raw_count) != prev_raw_count);
 
-	delta = (new_raw_count - prev_raw_count) &
-		((1ULL << arc_pmu->counter_size) - 1ULL);
+	delta = (new_raw_count - prev_raw_count) & arc_pmu->max_period;
 
 	local64_add(delta, &event->count);
 	local64_sub(delta, &hwc->period_left);
@@ -182,6 +181,13 @@ static int arc_pmu_event_init(struct perf_event *event)
 	struct hw_perf_event *hwc = &event->hw;
 	int ret;
 
+	if (!is_sampling_event(event)) {
+		hwc->sample_period  = arc_pmu->max_period;
+		hwc->last_period = hwc->sample_period;
+		local64_set(&hwc->period_left, hwc->sample_period);
+	} else
+		return -ENOENT;
+
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
 		if (event->attr.config >= PERF_COUNT_HW_MAX)
@@ -228,6 +234,49 @@ static void arc_pmu_disable(struct pmu *pmu)
 	write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0);
 }
 
+static int arc_pmu_event_set_period(struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	u64 left = local64_read(&hwc->period_left);
+	u64 period = hwc->sample_period;
+	int idx = hwc->idx;
+	int ret = 0;
+	u64 value;
+
+	if (unlikely(left <= -period)) {
+		/* left underflowed by more than period. */
+		left = period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	} else	if (unlikely((left + period) <= period)) {
+		/* left underflowed by less than period. */
+		left += period;
+		local64_set(&hwc->period_left, left);
+		hwc->last_period = period;
+		ret = 1;
+	}
+
+	if (left > arc_pmu->max_period) {
+		left = arc_pmu->max_period;
+		local64_set(&hwc->period_left, left);
+	}
+
+	value = arc_pmu->max_period - left;
+	local64_set(&hwc->prev_count, value);
+
+	/* Select counter */
+	write_aux_reg(ARC_REG_PCT_INDEX, idx);
+
+	/* Write value */
+	write_aux_reg(ARC_REG_PCT_COUNTL, value & 0xffffffff);
+	write_aux_reg(ARC_REG_PCT_COUNTH, (value >> 32));
+
+	perf_event_update_userpage(event);
+
+	return ret;
+}
+
 /*
  * Assigns hardware counter to hardware condition.
  * Note that there is no separate start/stop mechanism;
@@ -242,9 +291,11 @@ static void arc_pmu_start(struct perf_event *event, int flags)
 		return;
 
 	if (flags & PERF_EF_RELOAD)
-		WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+		WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
+
+	hwc->state = 0;
 
-	event->hw.state = 0;
+	arc_pmu_event_set_period(event);
 
 	/* enable ARC pmu here */
 	write_aux_reg(ARC_REG_PCT_INDEX, idx);
@@ -318,6 +369,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 	struct arc_reg_pct_build pct_bcr;
 	struct arc_reg_cc_build cc_bcr;
 	int i, j;
+	int counter_size;	/* in bits */
 
 	union cc_name {
 		struct {
@@ -344,10 +396,11 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	arc_pmu->n_counters = pct_bcr.c;
-	arc_pmu->counter_size = 32 + (pct_bcr.s << 4);
+	counter_size = 32 + (pct_bcr.s << 4);
+	arc_pmu->max_period = (1ULL << counter_size) - 1ULL;
 
 	pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
-		arc_pmu->n_counters, arc_pmu->counter_size, cc_bcr.c);
+		arc_pmu->n_counters, counter_size, cc_bcr.c);
 
 	arc_pmu->n_events = cc_bcr.c;
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
                   ` (2 preceding siblings ...)
  2015-06-09 12:19 ` [PATCH 3/8] ARCv2: perf: implement "event_set_period" for future use with interrupts Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  2015-06-15 15:48   ` Peter Zijlstra
  2015-06-15 16:25   ` Peter Zijlstra
  2015-06-09 12:19 ` [PATCH 5/8] ARCv2: perf: set usable max period as a half of real max period Vineet Gupta
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Vineet Gupta

From: Alexey Brodkin <abrodkin@synopsys.com>

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/perf_event.h |   8 ++-
 arch/arc/kernel/perf_event.c      | 123 ++++++++++++++++++++++++++++++++++++--
 2 files changed, 124 insertions(+), 7 deletions(-)

diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
index ca8c414738de..33a6eb2998ac 100644
--- a/arch/arc/include/asm/perf_event.h
+++ b/arch/arc/include/asm/perf_event.h
@@ -32,15 +32,19 @@
 #define ARC_REG_PCT_CONFIG	0x254
 #define ARC_REG_PCT_CONTROL	0x255
 #define ARC_REG_PCT_INDEX	0x256
+#define ARC_REG_PCT_INT_CNTL	0x25C
+#define ARC_REG_PCT_INT_CNTH	0x25D
+#define ARC_REG_PCT_INT_CTRL	0x25E
+#define ARC_REG_PCT_INT_ACT	0x25F
 
 #define ARC_REG_PCT_CONTROL_CC	(1 << 16)	/* clear counts */
 #define ARC_REG_PCT_CONTROL_SN	(1 << 17)	/* snapshot */
 
 struct arc_reg_pct_build {
 #ifdef CONFIG_CPU_BIG_ENDIAN
-	unsigned int m:8, c:8, r:6, s:2, v:8;
+	unsigned int m:8, c:8, r:5, i:1, s:2, v:8;
 #else
-	unsigned int v:8, s:2, r:6, c:8, m:8;
+	unsigned int v:8, s:2, i:1, r:5, c:8, m:8;
 #endif
 };
 
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 065daed8ad5f..4e3211948467 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -11,6 +11,7 @@
  *
  */
 #include <linux/errno.h>
+#include <linux/interrupt.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/perf_event.h>
@@ -20,11 +21,13 @@
 
 struct arc_pmu {
 	struct pmu	pmu;
+	int		has_interrupts;
 	int		n_counters;
 	int		n_events;
 	unsigned long	used_mask[BITS_TO_LONGS(ARC_PERF_MAX_COUNTERS)];
 	u64		max_period;
 	int		ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
+	struct perf_event *act_counter[ARC_PERF_MAX_COUNTERS];
 	u64             raw_events[ARC_PERF_MAX_EVENTS];
 };
 
@@ -186,7 +189,8 @@ static int arc_pmu_event_init(struct perf_event *event)
 		hwc->last_period = hwc->sample_period;
 		local64_set(&hwc->period_left, hwc->sample_period);
 	} else
-		return -ENOENT;
+		if (!arc_pmu->has_interrupts)
+			return -ENOENT;
 
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
@@ -307,6 +311,17 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
 
+	/* Disable interrupt for this counter */
+	if (is_sampling_event(event)) {
+		/*
+		 * Reset interrupt flag by writing of 1. This is required
+		 * to make sure pending interrupt was not left.
+		 */
+		write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+		write_aux_reg(ARC_REG_PCT_INT_CTRL,
+			      read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~(1 << idx));
+	}
+
 	if (!(event->hw.state & PERF_HES_STOPPED)) {
 		/* stop ARC pmu here */
 		write_aux_reg(ARC_REG_PCT_INDEX, idx);
@@ -329,6 +344,8 @@ static void arc_pmu_del(struct perf_event *event, int flags)
 	arc_pmu_stop(event, PERF_EF_UPDATE);
 	__clear_bit(event->hw.idx, arc_pmu->used_mask);
 
+	arc_pmu->act_counter[event->hw.idx] = 0;
+
 	perf_event_update_userpage(event);
 }
 
@@ -349,6 +366,21 @@ static int arc_pmu_add(struct perf_event *event, int flags)
 	}
 
 	write_aux_reg(ARC_REG_PCT_INDEX, idx);
+
+	arc_pmu->act_counter[idx] = event;
+
+	if (is_sampling_event(event)) {
+		/* Mimic full counter overflow as other arches do */
+		write_aux_reg(ARC_REG_PCT_INT_CNTL, arc_pmu->max_period &
+						    0xffffffff);
+		write_aux_reg(ARC_REG_PCT_INT_CNTH,
+			      (arc_pmu->max_period >> 32));
+
+		/* Enable interrupt for this counter */
+		write_aux_reg(ARC_REG_PCT_INT_CTRL,
+			      read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+	}
+
 	write_aux_reg(ARC_REG_PCT_CONFIG, 0);
 	write_aux_reg(ARC_REG_PCT_COUNTL, 0);
 	write_aux_reg(ARC_REG_PCT_COUNTH, 0);
@@ -363,6 +395,65 @@ static int arc_pmu_add(struct perf_event *event, int flags)
 	return 0;
 }
 
+#ifdef CONFIG_ISA_ARCV2
+static irqreturn_t arc_pmu_intr(int irq, void *dev)
+{
+	struct perf_sample_data data;
+	struct arc_pmu *arc_pmu = (struct arc_pmu *)dev;
+	struct pt_regs *regs;
+	int active_ints;
+	int idx;
+
+	arc_pmu_disable(&arc_pmu->pmu);
+
+	active_ints = read_aux_reg(ARC_REG_PCT_INT_ACT);
+
+	regs = get_irq_regs();
+
+	for (idx = 0; idx < arc_pmu->n_counters; idx++) {
+		struct perf_event *event = arc_pmu->act_counter[idx];
+		struct hw_perf_event *hwc;
+
+		if (!(active_ints & (1 << idx)))
+			continue;
+
+		/* Reset interrupt flag by writing of 1 */
+		write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+
+		/*
+		 * On reset of "interrupt active" bit corresponding
+		 * "interrupt enable" bit gets automatically reset as well.
+		 * Now we need to re-enable interrupt for the counter.
+		 */
+		write_aux_reg(ARC_REG_PCT_INT_CTRL,
+			read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+
+		hwc = &event->hw;
+
+		WARN_ON_ONCE(hwc->idx != idx);
+
+		arc_perf_event_update(event, &event->hw, event->hw.idx);
+		perf_sample_data_init(&data, 0, hwc->last_period);
+		if (!arc_pmu_event_set_period(event))
+			continue;
+
+		if (perf_event_overflow(event, &data, regs))
+			arc_pmu_stop(event, 0);
+	}
+
+	arc_pmu_enable(&arc_pmu->pmu);
+
+	return IRQ_HANDLED;
+}
+#else
+
+static irqreturn_t arc_pmu_intr(int irq, void *dev)
+{
+	return IRQ_NONE;
+}
+
+#endif /* CONFIG_ISA_ARCV2 */
+
 static int arc_pmu_device_probe(struct platform_device *pdev)
 {
 	struct arc_pmu *arc_pmu;
@@ -395,12 +486,16 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 	if (!arc_pmu)
 		return -ENOMEM;
 
+	arc_pmu->has_interrupts = is_isa_arcv2() ? pct_bcr.i : 0;
+
 	arc_pmu->n_counters = pct_bcr.c;
 	counter_size = 32 + (pct_bcr.s << 4);
+
 	arc_pmu->max_period = (1ULL << counter_size) - 1ULL;
 
-	pr_info("ARC perf\t: %d counters (%d bits), %d countable conditions\n",
-		arc_pmu->n_counters, counter_size, cc_bcr.c);
+	pr_info("ARC perf\t: %d counters (%d bits), %d conditions%s\n",
+		arc_pmu->n_counters, counter_size, cc_bcr.c,
+		arc_pmu->has_interrupts ? ", [overflow IRQ support]":"");
 
 	arc_pmu->n_events = cc_bcr.c;
 
@@ -440,8 +535,26 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 		.read		= arc_pmu_read,
 	};
 
-	/* ARC 700 PMU does not support sampling events */
-	arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+	if (arc_pmu->has_interrupts) {
+		int irq = platform_get_irq(pdev, 0);
+
+		if (irq < 0) {
+			pr_err("Cannot get IRQ number for the platform\n");
+			return -ENODEV;
+		}
+
+		ret = devm_request_irq(&pdev->dev, irq, arc_pmu_intr, 0,
+				       "arc-pmu", arc_pmu);
+		if (ret) {
+			pr_err("could not allocate PMU IRQ\n");
+			return ret;
+		}
+
+		/* Clean all pending interrupt flags */
+		write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
+	} else {
+		arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
+	}
 
 	return perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
 }
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 5/8] ARCv2: perf: set usable max period as a half of real max period
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
                   ` (3 preceding siblings ...)
  2015-06-09 12:19 ` [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  2015-06-09 12:19 ` [PATCH 6/8] ARCv2: perf: implement exclusion of event counting in user or kernel mode Vineet Gupta
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Vineet Gupta

From: Alexey Brodkin <abrodkin@synopsys.com>

Overflow interrupt happens when counter reaches a limit which we set as a
maximum value of the counter.

But for better precision counter continues registration of assigned events
even after reaching pre-defined limit. To not really overlap we leave half
of the counter values free.

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/kernel/perf_event.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 4e3211948467..a7b4e4826533 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -491,7 +491,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 	arc_pmu->n_counters = pct_bcr.c;
 	counter_size = 32 + (pct_bcr.s << 4);
 
-	arc_pmu->max_period = (1ULL << counter_size) - 1ULL;
+	arc_pmu->max_period = (1ULL << counter_size) / 2 - 1ULL;
 
 	pr_info("ARC perf\t: %d counters (%d bits), %d conditions%s\n",
 		arc_pmu->n_counters, counter_size, cc_bcr.c,
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 6/8] ARCv2: perf: implement exclusion of event counting in user or kernel mode
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
                   ` (4 preceding siblings ...)
  2015-06-09 12:19 ` [PATCH 5/8] ARCv2: perf: set usable max period as a half of real max period Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  2015-06-09 12:19 ` [PATCH 7/8] ARCv2: perf: SMP support Vineet Gupta
  2015-06-09 12:19 ` [PATCH 8/8] ARCv2: perf: Finally introduce HS perf unit Vineet Gupta
  7 siblings, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Vineet Gupta

From: Alexey Brodkin <abrodkin@synopsys.com>

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/include/asm/perf_event.h |  3 +++
 arch/arc/kernel/perf_event.c      | 16 ++++++++++++++--
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
index 33a6eb2998ac..e915c0d4b630 100644
--- a/arch/arc/include/asm/perf_event.h
+++ b/arch/arc/include/asm/perf_event.h
@@ -37,6 +37,9 @@
 #define ARC_REG_PCT_INT_CTRL	0x25E
 #define ARC_REG_PCT_INT_ACT	0x25F
 
+#define ARC_REG_PCT_CONFIG_USER	(1 << 18)	/* count in user mode */
+#define ARC_REG_PCT_CONFIG_KERN	(1 << 19)	/* count in kernel mode */
+
 #define ARC_REG_PCT_CONTROL_CC	(1 << 16)	/* clear counts */
 #define ARC_REG_PCT_CONTROL_SN	(1 << 17)	/* snapshot */
 
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index a7b4e4826533..01aa0ea16bae 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -192,13 +192,25 @@ static int arc_pmu_event_init(struct perf_event *event)
 		if (!arc_pmu->has_interrupts)
 			return -ENOENT;
 
+	hwc->config = 0;
+
+	if (is_isa_arcv2()) {
+		/* "exclude user" means "count only kernel" */
+		if (event->attr.exclude_user)
+			hwc->config |= ARC_REG_PCT_CONFIG_KERN;
+
+		/* "exclude kernel" means "count only user" */
+		if (event->attr.exclude_kernel)
+			hwc->config |= ARC_REG_PCT_CONFIG_USER;
+	}
+
 	switch (event->attr.type) {
 	case PERF_TYPE_HARDWARE:
 		if (event->attr.config >= PERF_COUNT_HW_MAX)
 			return -ENOENT;
 		if (arc_pmu->ev_hw_idx[event->attr.config] < 0)
 			return -ENOENT;
-		hwc->config = arc_pmu->ev_hw_idx[event->attr.config];
+		hwc->config |= arc_pmu->ev_hw_idx[event->attr.config];
 		pr_debug("init event %d with h/w %d \'%s\'\n",
 			 (int) event->attr.config, (int) hwc->config,
 			 arc_pmu_ev_hw_map[event->attr.config]);
@@ -207,7 +219,7 @@ static int arc_pmu_event_init(struct perf_event *event)
 		ret = arc_pmu_cache_event(event->attr.config);
 		if (ret < 0)
 			return ret;
-		hwc->config = arc_pmu->ev_hw_idx[ret];
+		hwc->config |= arc_pmu->ev_hw_idx[ret];
 		return 0;
 
 	case PERF_TYPE_RAW:
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 7/8] ARCv2: perf: SMP support
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
                   ` (5 preceding siblings ...)
  2015-06-09 12:19 ` [PATCH 6/8] ARCv2: perf: implement exclusion of event counting in user or kernel mode Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  2015-06-09 12:19 ` [PATCH 8/8] ARCv2: perf: Finally introduce HS perf unit Vineet Gupta
  7 siblings, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Peter Zijlstra,
	Arnaldo Carvalho de Melo, Vineet Gupta

From: Alexey Brodkin <abrodkin@synopsys.com>

* split off pmu info into singleton and per-cpu bits
* setup PMU on all cores

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 arch/arc/kernel/perf_event.c | 73 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 55 insertions(+), 18 deletions(-)

diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index 01aa0ea16bae..a40772b37b77 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -21,16 +21,27 @@
 
 struct arc_pmu {
 	struct pmu	pmu;
-	int		has_interrupts;
+	unsigned int	irq:31, has_interrupts:1;
 	int		n_counters;
 	int		n_events;
-	unsigned long	used_mask[BITS_TO_LONGS(ARC_PERF_MAX_COUNTERS)];
 	u64		max_period;
 	int		ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
-	struct perf_event *act_counter[ARC_PERF_MAX_COUNTERS];
 	u64             raw_events[ARC_PERF_MAX_EVENTS];
 };
 
+struct arc_pmu_cpu {
+	/*
+	 * A 1 bit for an index indicates that the counter is being used for
+	 * an event. A 0 means that the counter can be used.
+	 */
+	unsigned long	used_mask[BITS_TO_LONGS(ARC_PERF_MAX_COUNTERS)];
+
+	/*
+	 * The events that are active on the PMU for the given index.
+	 */
+	struct perf_event *act_counter[ARC_PERF_MAX_COUNTERS];
+};
+
 struct arc_callchain_trace {
 	int depth;
 	void *perf_stuff;
@@ -70,6 +81,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 }
 
 static struct arc_pmu *arc_pmu;
+static DEFINE_PER_CPU(struct arc_pmu_cpu, arc_pmu_cpu);
 
 /* read counter #idx; note that counter# != event# on ARC! */
 static uint64_t arc_pmu_read_counter(int idx)
@@ -353,10 +365,12 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
 
 static void arc_pmu_del(struct perf_event *event, int flags)
 {
+	struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
+
 	arc_pmu_stop(event, PERF_EF_UPDATE);
-	__clear_bit(event->hw.idx, arc_pmu->used_mask);
+	__clear_bit(event->hw.idx, pmu_cpu->used_mask);
 
-	arc_pmu->act_counter[event->hw.idx] = 0;
+	pmu_cpu->act_counter[event->hw.idx] = 0;
 
 	perf_event_update_userpage(event);
 }
@@ -364,22 +378,23 @@ static void arc_pmu_del(struct perf_event *event, int flags)
 /* allocate hardware counter and optionally start counting */
 static int arc_pmu_add(struct perf_event *event, int flags)
 {
+	struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
 
-	if (__test_and_set_bit(idx, arc_pmu->used_mask)) {
-		idx = find_first_zero_bit(arc_pmu->used_mask,
+	if (__test_and_set_bit(idx, pmu_cpu->used_mask)) {
+		idx = find_first_zero_bit(pmu_cpu->used_mask,
 					  arc_pmu->n_counters);
 		if (idx == arc_pmu->n_counters)
 			return -EAGAIN;
 
-		__set_bit(idx, arc_pmu->used_mask);
+		__set_bit(idx, pmu_cpu->used_mask);
 		hwc->idx = idx;
 	}
 
 	write_aux_reg(ARC_REG_PCT_INDEX, idx);
 
-	arc_pmu->act_counter[idx] = event;
+	pmu_cpu->act_counter[idx] = event;
 
 	if (is_sampling_event(event)) {
 		/* Mimic full counter overflow as other arches do */
@@ -411,7 +426,7 @@ static int arc_pmu_add(struct perf_event *event, int flags)
 static irqreturn_t arc_pmu_intr(int irq, void *dev)
 {
 	struct perf_sample_data data;
-	struct arc_pmu *arc_pmu = (struct arc_pmu *)dev;
+	struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
 	struct pt_regs *regs;
 	int active_ints;
 	int idx;
@@ -423,7 +438,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
 	regs = get_irq_regs();
 
 	for (idx = 0; idx < arc_pmu->n_counters; idx++) {
-		struct perf_event *event = arc_pmu->act_counter[idx];
+		struct perf_event *event = pmu_cpu->act_counter[idx];
 		struct hw_perf_event *hwc;
 
 		if (!(active_ints & (1 << idx)))
@@ -466,9 +481,19 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
 
 #endif /* CONFIG_ISA_ARCV2 */
 
+void arc_cpu_pmu_irq_init(void)
+{
+	struct arc_pmu_cpu *pmu_cpu = this_cpu_ptr(&arc_pmu_cpu);
+
+	arc_request_percpu_irq(arc_pmu->irq, smp_processor_id(), arc_pmu_intr,
+			       "ARC perf counters", pmu_cpu);
+
+	/* Clear all pending interrupt flags */
+	write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
+}
+
 static int arc_pmu_device_probe(struct platform_device *pdev)
 {
-	struct arc_pmu *arc_pmu;
 	struct arc_reg_pct_build pct_bcr;
 	struct arc_reg_cc_build cc_bcr;
 	int i, j;
@@ -549,18 +574,30 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
 	if (arc_pmu->has_interrupts) {
 		int irq = platform_get_irq(pdev, 0);
+		unsigned long flags;
 
 		if (irq < 0) {
 			pr_err("Cannot get IRQ number for the platform\n");
 			return -ENODEV;
 		}
 
-		ret = devm_request_irq(&pdev->dev, irq, arc_pmu_intr, 0,
-				       "arc-pmu", arc_pmu);
-		if (ret) {
-			pr_err("could not allocate PMU IRQ\n");
-			return ret;
-		}
+		arc_pmu->irq = irq;
+
+		/*
+		 * arc_cpu_pmu_irq_init() needs to be called on all cores for
+		 * their respective local PMU.
+		 * However we use opencoded on_each_cpu() to ensure it is called
+		 * on core0 first, so that arc_request_percpu_irq() sets up
+		 * AUTOEN etc. Otherwise enable_percpu_irq() fails to enable
+		 * perf IRQ on non master cores.
+		 * see arc_request_percpu_irq()
+		 */
+		preempt_disable();
+		local_irq_save(flags);
+		arc_cpu_pmu_irq_init();
+		local_irq_restore(flags);
+		smp_call_function((smp_call_func_t)arc_cpu_pmu_irq_init, 0, 1);
+		preempt_enable();
 
 		/* Clean all pending interrupt flags */
 		write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 8/8] ARCv2: perf: Finally introduce HS perf unit
  2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
                   ` (6 preceding siblings ...)
  2015-06-09 12:19 ` [PATCH 7/8] ARCv2: perf: SMP support Vineet Gupta
@ 2015-06-09 12:19 ` Vineet Gupta
  7 siblings, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-09 12:19 UTC (permalink / raw)
  To: linux-arch, linux-kernel
  Cc: arnd, Alexey Brodkin, arc-linux-dev, Vineet Gupta,
	Peter Zijlstra, Arnaldo Carvalho de Melo

With all features in place, the ARC HS pct block can now be effectively
allowed to be probed/used

Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
---
 Documentation/devicetree/bindings/arc/archs-pct.txt | 17 +++++++++++++++++
 arch/arc/include/asm/perf_event.h                   |  5 ++++-
 arch/arc/kernel/perf_event.c                        |  3 ++-
 3 files changed, 23 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/arc/archs-pct.txt

diff --git a/Documentation/devicetree/bindings/arc/archs-pct.txt b/Documentation/devicetree/bindings/arc/archs-pct.txt
new file mode 100644
index 000000000000..1ae98b87c640
--- /dev/null
+++ b/Documentation/devicetree/bindings/arc/archs-pct.txt
@@ -0,0 +1,17 @@
+* ARC HS Performance Counters
+
+The ARC HS can be configured with a pipeline performance monitor for counting
+CPU and cache events like cache misses and hits. Like conventional PCT there
+are 100+ hardware conditions dynamically mapped to upto 32 counters.
+It also supports overflow interrupts.
+
+Required properties:
+
+- compatible : should contain
+	"snps,archs-pct"
+
+Example:
+
+pmu {
+        compatible = "snps,archs-pct";
+};
diff --git a/arch/arc/include/asm/perf_event.h b/arch/arc/include/asm/perf_event.h
index e915c0d4b630..e4d758718bb5 100644
--- a/arch/arc/include/asm/perf_event.h
+++ b/arch/arc/include/asm/perf_event.h
@@ -108,8 +108,11 @@ static const char * const arc_pmu_ev_hw_map[] = {
 	[PERF_COUNT_HW_INSTRUCTIONS] = "iall",
 	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp",
 	[PERF_COUNT_ARC_BPOK]         = "bpok",	  /* NP-NT, PT-T, PNT-NT */
+#ifdef CONFIG_ISA_ARCV2
+	[PERF_COUNT_HW_BRANCH_MISSES] = "bpmp",
+#else
 	[PERF_COUNT_HW_BRANCH_MISSES] = "bpfail", /* NP-T, PT-NT, PNT-T */
-
+#endif
 	[PERF_COUNT_ARC_LDC] = "imemrdc",	/* Instr: mem read cached */
 	[PERF_COUNT_ARC_STC] = "imemwrc",	/* Instr: mem write cached */
 
diff --git a/arch/arc/kernel/perf_event.c b/arch/arc/kernel/perf_event.c
index a40772b37b77..e2ce9e03ea3d 100644
--- a/arch/arc/kernel/perf_event.c
+++ b/arch/arc/kernel/perf_event.c
@@ -611,6 +611,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 #ifdef CONFIG_OF
 static const struct of_device_id arc_pmu_match[] = {
 	{ .compatible = "snps,arc700-pct" },
+	{ .compatible = "snps,archs-pct" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, arc_pmu_match);
@@ -618,7 +619,7 @@ MODULE_DEVICE_TABLE(of, arc_pmu_match);
 
 static struct platform_driver arc_pmu_driver = {
 	.driver	= {
-		.name		= "arc700-pct",
+		.name		= "arc-pct",
 		.of_match_table = of_match_ptr(arc_pmu_match),
 	},
 	.probe		= arc_pmu_device_probe,
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/8] ARC: perf: support RAW events
  2015-06-09 12:19 ` [PATCH 1/8] ARC: perf: support RAW events Vineet Gupta
@ 2015-06-15 15:30   ` Peter Zijlstra
  2015-06-16 11:45     ` Alexey Brodkin
  2015-06-17 12:32     ` Vineet Gupta
  0 siblings, 2 replies; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-15 15:30 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Tue, Jun 09, 2015 at 05:49:25PM +0530, Vineet Gupta wrote:
> +/*
> + * Raw events are specified in hex value of ASCII chars:
> + *
> + * In PCT register CC_NAME{0,1} event name string[] is saved from LSB side:
> + * e.g. cycles corresponds to ARC "crun" and is saved as 0x6e757263
> + *							    n u r c
> + * However in perf cmdline they are specified in human order as r6372756e
> + *
> + * Thus event from cmdline requires an word swap
> + */
> +static int arc_pmu_raw_event(u64 config)
> +{
> +	int i;
> +	char name[sizeof(u64) + 1] = {0};
> +	u64 swapped = __swab64(config);
> +
> +	/* Trim leading zeroes */
> +	for (i = 0; i < sizeof(u64); i++)
> +		if (!(swapped & 0xFF))
> +			swapped = swapped >> 8;
> +		else
> +			break;
> +
> +	for (i = 0; i < arc_pmu->n_events; i++) {
> +		if (swapped == arc_pmu->raw_events[i])
> +			break;
> +	}
> +
> +	if (i == arc_pmu->n_events)
> +		return -ENOENT;
> +
> +	memcpy(name, &swapped, sizeof(u64));
> +
> +	pr_debug("Initializing raw event: %s\n", name);
> +
> +	return i;
> +}

Urgh, what? Why?

raw is just that _raw_, no mucking about with the value.

If you want convenience, provide the event/format stuff so you can
write:

	perf record -e 'cpu/c=0xff,r=0cff,u=0xff,n=0xff'

Or whatever that syntax was again (I keep forgetting).

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/8] ARCv2: perf: implement "event_set_period" for future use with interrupts
  2015-06-09 12:19 ` [PATCH 3/8] ARCv2: perf: implement "event_set_period" for future use with interrupts Vineet Gupta
@ 2015-06-15 15:38   ` Peter Zijlstra
  2015-06-22 15:26     ` Alexey Brodkin
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-15 15:38 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Tue, Jun 09, 2015 at 05:49:27PM +0530, Vineet Gupta wrote:
> @@ -99,8 +99,7 @@ static void arc_perf_event_update(struct perf_event *event,
>  	} while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
>  				 new_raw_count) != prev_raw_count);
>  
> -	delta = (new_raw_count - prev_raw_count) &
> -		((1ULL << arc_pmu->counter_size) - 1ULL);
> +	delta = (new_raw_count - prev_raw_count) & arc_pmu->max_period;

I don't know how your PMU works, but you seem to be assuming new_raw >
prev_raw, which implies its counting up.

Now, typically these things trigger when they reach 0, so when we're
counting up that would mean your values are negative.

In that case, where's the sign extension?

> @@ -182,6 +181,13 @@ static int arc_pmu_event_init(struct perf_event *event)
>  	struct hw_perf_event *hwc = &event->hw;
>  	int ret;
>  
> +	if (!is_sampling_event(event)) {
> +		hwc->sample_period  = arc_pmu->max_period;
> +		hwc->last_period = hwc->sample_period;
> +		local64_set(&hwc->period_left, hwc->sample_period);
> +	} else
> +		return -ENOENT;

-ENOENT is wrong for is_sampling_event().

Either the event is for this PMU, in which case you should return a
fatal error, or its not (-ENOENT is correct in that case).


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-09 12:19 ` [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts Vineet Gupta
@ 2015-06-15 15:48   ` Peter Zijlstra
  2015-06-22 15:57     ` Alexey Brodkin
  2015-06-15 16:25   ` Peter Zijlstra
  1 sibling, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-15 15:48 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Tue, Jun 09, 2015 at 05:49:28PM +0530, Vineet Gupta wrote:
> From: Alexey Brodkin <abrodkin@synopsys.com>

-ENOCHANGELOG

> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
> Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> ---

>  struct arc_pmu {
>  	struct pmu	pmu;
> +	int		has_interrupts;

we have pmu::flags & PERF_PMU_CAP_NO_INTERRUPT


> @@ -186,7 +189,8 @@ static int arc_pmu_event_init(struct perf_event *event)
>  		hwc->last_period = hwc->sample_period;
>  		local64_set(&hwc->period_left, hwc->sample_period);
>  	} else
> -		return -ENOENT;
> +		if (!arc_pmu->has_interrupts)
> +			return -ENOENT;

Same as before, first determine if the event is yours, then return a
fatal error.

> @@ -307,6 +311,17 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
>  	struct hw_perf_event *hwc = &event->hw;
>  	int idx = hwc->idx;
>  
> +	/* Disable interrupt for this counter */
> +	if (is_sampling_event(event)) {

but but but, a sampling event needs the interrupt enabled?

> +		/*
> +		 * Reset interrupt flag by writing of 1. This is required
> +		 * to make sure pending interrupt was not left.
> +		 */

Would not typically the interrupt latch be a property of the interrupt
controller, not the device generating it?

That is, how can the device programming affect pending interrupts?

> +		write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
> +		write_aux_reg(ARC_REG_PCT_INT_CTRL,
> +			      read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~(1 << idx));
> +	}
> +

> +	if (is_sampling_event(event)) {
> +		/* Mimic full counter overflow as other arches do */

With this you mean the pretending we have 63bit of overflow counter?

> +		write_aux_reg(ARC_REG_PCT_INT_CNTL, arc_pmu->max_period &
> +						    0xffffffff);

Would not (u32)arc_pmu->max_period, be clearer?

> +		write_aux_reg(ARC_REG_PCT_INT_CNTH,
> +			      (arc_pmu->max_period >> 32));

But should you not program: min(period, max_period) instead? If the
requested period is shorter than your max period you do not want to
program the max. Or are you missing a negative somewhere?

That is, program the max_period for !sampling events to deal with
overflow folding.

> +
> +		/* Enable interrupt for this counter */
> +		write_aux_reg(ARC_REG_PCT_INT_CTRL,
> +			      read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
> +	}
> +
>  	write_aux_reg(ARC_REG_PCT_CONFIG, 0);
>  	write_aux_reg(ARC_REG_PCT_COUNTL, 0);
>  	write_aux_reg(ARC_REG_PCT_COUNTH, 0);

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-09 12:19 ` [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts Vineet Gupta
  2015-06-15 15:48   ` Peter Zijlstra
@ 2015-06-15 16:25   ` Peter Zijlstra
  2015-06-16  5:37     ` Vineet Gupta
  1 sibling, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-15 16:25 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Tue, Jun 09, 2015 at 05:49:28PM +0530, Vineet Gupta wrote:
> +	if (arc_pmu->has_interrupts) {
> +		int irq = platform_get_irq(pdev, 0);

Hmm, so you're requesting a regular interrupt.

I see your architecture has IRQ priorities, could you play games and
create NMIs using those?

For example, never mask L1 (assuming that's the highest priority) and
treat that as an NMI.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-15 16:25   ` Peter Zijlstra
@ 2015-06-16  5:37     ` Vineet Gupta
  2015-06-16  9:07       ` Peter Zijlstra
  0 siblings, 1 reply; 26+ messages in thread
From: Vineet Gupta @ 2015-06-16  5:37 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Monday 15 June 2015 09:55 PM, Peter Zijlstra wrote:
> On Tue, Jun 09, 2015 at 05:49:28PM +0530, Vineet Gupta wrote:
>> +	if (arc_pmu->has_interrupts) {
>> +		int irq = platform_get_irq(pdev, 0);
> Hmm, so you're requesting a regular interrupt.
>
> I see your architecture has IRQ priorities, could you play games and
> create NMIs using those?
>
> For example, never mask L1 (assuming that's the highest priority) and
> treat that as an NMI.

I've had this idea before, however, while ARCv2 provides hardware interrupt
priorities, we really can't implement true NMI, because CLRI / SETI used at
backend of loal_irq_save() / restore() impact all priorities (statsu32 register
has a global enable interrupt bit which these wiggle). So e.g. a
spin_lock_irqsave() will lock out even the perf interrupt.

OTOH, we can improve the perf isr path a bit - by not routing it thru regular
interrupt return path (song and dance of CONFIG_PREEMPT_IRQ and possible
preemption). Plus there's a bit more we can do in the isr itself - not looping
thru 32 counters etc using ffs() etc - but I'd rather do that as separate series,
once we have the core support in.

-Vineet





^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-16  5:37     ` Vineet Gupta
@ 2015-06-16  9:07       ` Peter Zijlstra
  2015-06-16  9:33         ` Vineet Gupta
  2015-06-17 11:48         ` Vineet Gupta
  0 siblings, 2 replies; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-16  9:07 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Tue, Jun 16, 2015 at 05:37:40AM +0000, Vineet Gupta wrote:
> On Monday 15 June 2015 09:55 PM, Peter Zijlstra wrote:
> > On Tue, Jun 09, 2015 at 05:49:28PM +0530, Vineet Gupta wrote:
> >> +	if (arc_pmu->has_interrupts) {
> >> +		int irq = platform_get_irq(pdev, 0);
> > Hmm, so you're requesting a regular interrupt.
> >
> > I see your architecture has IRQ priorities, could you play games and
> > create NMIs using those?
> >
> > For example, never mask L1 (assuming that's the highest priority) and
> > treat that as an NMI.
> 
> I've had this idea before, however, while ARCv2 provides hardware interrupt
> priorities, we really can't implement true NMI, because CLRI / SETI used at
> backend of loal_irq_save() / restore() impact all priorities (statsu32 register
> has a global enable interrupt bit which these wiggle). So e.g. a
> spin_lock_irqsave() will lock out even the perf interrupt.

Hmm, bugger. I (of course) only looked at the kernel source, since that
is all I have, and the current arch/arc/ frobs with those two En bits in
status32.

So arcv2 changed all that, shame.

> OTOH, we can improve the perf isr path a bit - by not routing it thru regular
> interrupt return path (song and dance of CONFIG_PREEMPT_IRQ and possible
> preemption). Plus there's a bit more we can do in the isr itself - not looping
> thru 32 counters etc using ffs() etc - but I'd rather do that as separate series,
> once we have the core support in.

Yeah, borderline useful though, the reason the NMI thing is so useful is
that you can profile _inside_ IRQ-disabled regions. Now your
local_irq_enable() et al will be the hottest functions ever :-)

Regular interrupts are really only useful for userspace profiling, which
if plenty useful on its own of course. But kernel profiling is very
handy too :-)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-16  9:07       ` Peter Zijlstra
@ 2015-06-16  9:33         ` Vineet Gupta
  2015-06-17 11:48         ` Vineet Gupta
  1 sibling, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-16  9:33 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Tuesday 16 June 2015 02:37 PM, Peter Zijlstra wrote:

On Tue, Jun 16, 2015 at 05:37:40AM +0000, Vineet Gupta wrote:


> On Monday 15 June 2015 09:55 PM, Peter Zijlstra wrote:


> > On Tue, Jun 09, 2015 at 05:49:28PM +0530, Vineet Gupta wrote:


> >> +  if (arc_pmu->has_interrupts) {
> >> +          int irq = platform_get_irq(pdev, 0);


> > Hmm, so you're requesting a regular interrupt.
> >
> > I see your architecture has IRQ priorities, could you play games and
> > create NMIs using those?
> >
> > For example, never mask L1 (assuming that's the highest priority) and
> > treat that as an NMI.


>
> I've had this idea before, however, while ARCv2 provides hardware interrupt
> priorities, we really can't implement true NMI, because CLRI / SETI used at
> backend of loal_irq_save() / restore() impact all priorities (statsu32 register
> has a global enable interrupt bit which these wiggle). So e.g. a
> spin_lock_irqsave() will lock out even the perf interrupt.


Hmm, bugger. I (of course) only looked at the kernel source, since that
is all I have, and the current arch/arc/ frobs with those two En bits in
status32.

Yeah the new intc and handling is series #B currently floated on lkml - we are discussing #C here - perf sub-series.


So arcv2 changed all that, shame.

Not really - arcv2 intc priorities (0-15, kind of excessive for linux usecase) is a logical extension of fixed 2 levels provided by arcompact (L2 high, L1 normal). Instead of 2 bits each of enable/active we have multiple now - spread over a couple of registers (statsu32.EN, irq_priority....).
arcv2 core interrupt handling is loads better than what we had before - specially with hardware stack switching / auto reg file save etc.

Plus now hardware enforces strict priority. In arcompact, the prio enable is semi-loosely enforced. L2 (high prio) can obviously interrupt L1 (low prio). But the other way around is possible too - if E1 is set - hence the beautiful code in arch/arc/kernel/irq.c : arch_local_irq_enable()

Technically we could also do something here, not use SETI / CLRI for disabling / enabling interrupts, but play with allowed intr level etc - but I think the cost of writing to interrupt priority/enable registers that often will be prohibitive at best.





> OTOH, we can improve the perf isr path a bit - by not routing it thru regular
> interrupt return path (song and dance of CONFIG_PREEMPT_IRQ and possible
> preemption). Plus there's a bit more we can do in the isr itself - not looping
> thru 32 counters etc using ffs() etc - but I'd rather do that as separate series,
> once we have the core support in.


Yeah, borderline useful though, the reason the NMI thing is so useful is
that you can profile _inside_ IRQ-disabled regions. Now your
local_irq_enable() et al will be the hottest functions ever :-)

Regular interrupts are really only useful for userspace profiling, which
if plenty useful on its own of course. But kernel profiling is very
handy too :-)


Totally agree !

^ permalink raw reply	[flat|nested] 26+ messages in thread

* RE: [PATCH 1/8] ARC: perf: support RAW events
  2015-06-15 15:30   ` Peter Zijlstra
@ 2015-06-16 11:45     ` Alexey Brodkin
  2015-06-17 13:33       ` Peter Zijlstra
  2015-06-17 12:32     ` Vineet Gupta
  1 sibling, 1 reply; 26+ messages in thread
From: Alexey Brodkin @ 2015-06-16 11:45 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, arnd, arc-linux-dev,
	Arnaldo Carvalho de Melo, Vineet Gupta

Hi Peter,

On Mon, 2015-06-15 at 17:30 +0200, Peter Zijlstra wrote:
> On Tue, Jun 09, 2015 at 05:49:25PM +0530, Vineet Gupta wrote:
> > +/*
> > + * Raw events are specified in hex value of ASCII chars:
> > + *
> > + * In PCT register CC_NAME{0,1} event name string[] is saved from
> > LSB side:
> > + * e.g. cycles corresponds to ARC "crun" and is saved as
> > 0x6e757263
> > + *							    n u r
> > c
> > + * However in perf cmdline they are specified in human order as
> > r6372756e
> > + *
> > + * Thus event from cmdline requires an word swap
> > + */
> > +static int arc_pmu_raw_event(u64 config)
> > +{
> > +	int i;
> > +	char name[sizeof(u64) + 1] = {0};
> > +	u64 swapped = __swab64(config);
> > +
> > +	/* Trim leading zeroes */
> > +	for (i = 0; i < sizeof(u64); i++)
> > +		if (!(swapped & 0xFF))
> > +			swapped = swapped >> 8;
> > +		else
> > +			break;
> > +
> > +	for (i = 0; i < arc_pmu->n_events; i++) {
> > +		if (swapped == arc_pmu->raw_events[i])
> > +			break;
> > +	}
> > +
> > +	if (i == arc_pmu->n_events)
> > +		return -ENOENT;
> > +
> > +	memcpy(name, &swapped, sizeof(u64));
> > +
> > +	pr_debug("Initializing raw event: %s\n", name);
> > +
> > +	return i;
> > +}
> 
> Urgh, what? Why?
> 
> raw is just that _raw_, no mucking about with the value.
> 
> If you want convenience, provide the event/format stuff so you can
> write:
> 
> 	perf record -e 'cpu/c=0xff,r=0cff,u=0xff,n=0xff'
> 
> Or whatever that syntax was again (I keep forgetting).

It was me who implemented that code so let me comment on that.

First let me clarify a bit how we deal with hardware events in ARC cores.

 a) ARC core may have an arbitrary set of hardware events built-in. Upon creation of new ASIC project hardware engineer may select which events will be exposed to event counters. For example only a very basic set of events could be made available like "cycles running", "committed instructions" etc. Or much more extensive set of events could be exposed to event counters including very specific architectural events like separate "committed 16-bit instructions" and "committed 32-bit instructions".

 b) Also list of all possible events is much longer than 32 or 64 entries that makes it impossible to map all possible events as a separate bits in 32- or 64-bit word.

Having both [a] and [b] in mind we implemented the following scheme of working with HW events.

 [1] Hardware may report a list of all event that could be counted in this particular CPU.

 [2] That lists consists of short ASCII names (up to 8 characters) for each event.

 [3] Index of the particular even in the list is used to setup an event counter.

See corresponding code for it here: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arc/kernel/perf_event.c#n308

I.e. if we need to count "xxx" event and we know it's 10th in the list of events we set event counter to count event #10, see http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arc/kernel/perf_event.c#n151

With generic hardware events we don't do any visible trickery as you may see from code by the link above simply because we know how to translate PERF_COUNT_HW_CPU_CYCLES to the index of corresponding event, see: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arc/include/asm/perf_event.h#n87

But in case of raw events we need to set a counter with index of a particular event. For example we need to count "myevnt0" events. For this we need first to find-out what's an index in events list of "myevnt0" event and then set event counter to count event #x.

Even though in theory we may set raw even passing an index of desired event but given my explanation above each particular CPU may have the same event with different index in events list.

And to make life of perf user a bit easier we allow specification of raw event as a hex-encoded ASCII name of the event.

For example if we want to count "crun" events we pass "r6372756e" which is "r" for raw event and 0x63 ("c"), 0x72 ("r"), 0x75 ("u") and 0x6e ("n").

Here're more examples:
 * "bflush" (pipeline bubbles caused by any type of flush) will be "r62666c757368"
 * "icm" (instruction cache miss) will be "r69636d"
 * "imemwrc" (instruction: memory write) will be "r696d656d777263"

I understand that even this method of raw events specification is not the most human friendly but given rare need to use we believe it worth having it.

Fortunately there's already a patch series floating in LKML that attempts to simplify usage of architecture-specific events, see http://www.spinics.net/lists/kernel/msg2010232.html

And once mentioned patch series is accepted (it's on its 15th respin so I hope sooner or later it will be in mainline) probably we'll be able to get rid of discussed tricky functionality in ARC perf. But for now we'd like to have currently working tool that allows us to do low-level profiling today.

I hope my explanation makes some sense. Otherwise please don;'t hesitate to ask more questions and I'll try to address them.

-Alexey

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-16  9:07       ` Peter Zijlstra
  2015-06-16  9:33         ` Vineet Gupta
@ 2015-06-17 11:48         ` Vineet Gupta
  2015-06-17 12:44           ` Peter Zijlstra
  1 sibling, 1 reply; 26+ messages in thread
From: Vineet Gupta @ 2015-06-17 11:48 UTC (permalink / raw)
  To: Peter Zijlstra, Chuck Jordan
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Tuesday 16 June 2015 02:37 PM, Peter Zijlstra wrote:
> On Tue, Jun 16, 2015 at 05:37:40AM +0000, Vineet Gupta wrote:
>> > On Monday 15 June 2015 09:55 PM, Peter Zijlstra wrote:
>>> > > On Tue, Jun 09, 2015 at 05:49:28PM +0530, Vineet Gupta wrote:
>>>> > >> +	if (arc_pmu->has_interrupts) {
>>>> > >> +		int irq = platform_get_irq(pdev, 0);
>>> > > Hmm, so you're requesting a regular interrupt.
>>> > >
>>> > > I see your architecture has IRQ priorities, could you play games and
>>> > > create NMIs using those?
>>> > >
>>> > > For example, never mask L1 (assuming that's the highest priority) and
>>> > > treat that as an NMI.
>> > 
>> > I've had this idea before, however, while ARCv2 provides hardware interrupt
>> > priorities, we really can't implement true NMI, because CLRI / SETI used at
>> > backend of loal_irq_save() / restore() impact all priorities (statsu32 register
>> > has a global enable interrupt bit which these wiggle). So e.g. a
>> > spin_lock_irqsave() will lock out even the perf interrupt.
> Hmm, bugger. I (of course) only looked at the kernel source, since that
> is all I have, and the current arch/arc/ frobs with those two En bits in
> status32.
> 
> So arcv2 changed all that, shame.

Turns out that it is possible to implement NMI on ARCv2 in a pretty
straightforward way.

Our RTOS Guru, Chuck, told me off list, that instead of using CLRI / SETI, we can
use SETI with different args which would keep the stat32.IE enabled all the times,
but wiggle the stat32.E[ ] to change the intr prio level, effectively locking out
only lower prio interrupts in any local_irq_save() / restore() region.
But isn't this defying the irq disable/enable semantics and could lead to
potential breach of *some* critical section.

Neverthless, doing this requires some more changes in ARCv2 support code - so for
now we will go with the normal interrupts and later bolt on the NMI emulation.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/8] ARC: perf: support RAW events
  2015-06-15 15:30   ` Peter Zijlstra
  2015-06-16 11:45     ` Alexey Brodkin
@ 2015-06-17 12:32     ` Vineet Gupta
  1 sibling, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-17 12:32 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: linux-arch, linux-kernel, arnd, Alexey Brodkin, arc-linux-dev,
	Arnaldo Carvalho de Melo

On Monday 15 June 2015 09:00 PM, Peter Zijlstra wrote:
> On Tue, Jun 09, 2015 at 05:49:25PM +0530, Vineet Gupta wrote:
>> +/*
>> + * Raw events are specified in hex value of ASCII chars:
>> + *
>> + * In PCT register CC_NAME{0,1} event name string[] is saved from LSB side:
>> + * e.g. cycles corresponds to ARC "crun" and is saved as 0x6e757263
>> + *							    n u r c
>> + * However in perf cmdline they are specified in human order as r6372756e
>> + *
>> + * Thus event from cmdline requires an word swap
>> + */
>> +static int arc_pmu_raw_event(u64 config)
>> +{
>> +	int i;
>> +	char name[sizeof(u64) + 1] = {0};
>> +	u64 swapped = __swab64(config);
>> +
>> +	/* Trim leading zeroes */
>> +	for (i = 0; i < sizeof(u64); i++)
>> +		if (!(swapped & 0xFF))
>> +			swapped = swapped >> 8;
>> +		else
>> +			break;
>> +
>> +	for (i = 0; i < arc_pmu->n_events; i++) {
>> +		if (swapped == arc_pmu->raw_events[i])
>> +			break;
>> +	}
>> +
>> +	if (i == arc_pmu->n_events)
>> +		return -ENOENT;
>> +
>> +	memcpy(name, &swapped, sizeof(u64));
>> +
>> +	pr_debug("Initializing raw event: %s\n", name);
>> +
>> +	return i;
>> +}
> 
> Urgh, what? Why?
> 
> raw is just that _raw_, no mucking about with the value.
> 
> If you want convenience, provide the event/format stuff so you can
> write:
> 
> 	perf record -e 'cpu/c=0xff,r=0cff,u=0xff,n=0xff'
> 
> Or whatever that syntax was again (I keep forgetting).


I'm not too familiar with elaborate raw events from other arches, but it seems
cpu/event style makes sense when there are params (e.g. umask etc) in addition to
event id.

For us raw is just the event id, albeit an ascii string, which can vary from 3 to
8 chars. PMU saves the event name as string in LSB so "crun" is 0x6e757263 which
corresponds to 'n' 'u' 'r' 'c'

The only convenience we are giving the user is ability to specify the raw event as
ASCII string in *human order* which we need to swap around for comparing against
what we have in the driver tables - setup at the time of probe

If you absolutely detest that, we can pre-swap those values in probe to save in
human order.

Perhaps it is batter that way anyways - what say you ?

-Vineet

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-17 11:48         ` Vineet Gupta
@ 2015-06-17 12:44           ` Peter Zijlstra
  0 siblings, 0 replies; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-17 12:44 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: Chuck Jordan, linux-arch, linux-kernel, arnd, Alexey Brodkin,
	arc-linux-dev, Arnaldo Carvalho de Melo

On Wed, Jun 17, 2015 at 05:18:27PM +0530, Vineet Gupta wrote:
> Turns out that it is possible to implement NMI on ARCv2 in a pretty
> straightforward way.
> 
> Our RTOS Guru, Chuck, told me off list, that instead of using CLRI / SETI, we can
> use SETI with different args which would keep the stat32.IE enabled all the times,
> but wiggle the stat32.E[ ] to change the intr prio level, effectively locking out
> only lower prio interrupts in any local_irq_save() / restore() region.

Nice.

> But isn't this defying the irq disable/enable semantics and could lead to
> potential breach of *some* critical section.

Well only if you then hand out interrupts for that priority level
without treating them as NMIs.

Note that NMIs do not nest, so if your hardware can raise multiple
interrupts for any one level it needs to mask the level in your
handler's entry code.

> Neverthless, doing this requires some more changes in ARCv2 support code - so for
> now we will go with the normal interrupts and later bolt on the NMI emulation.

Sure, smalls steps etc.. :-)

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/8] ARC: perf: support RAW events
  2015-06-16 11:45     ` Alexey Brodkin
@ 2015-06-17 13:33       ` Peter Zijlstra
  2015-06-17 14:10         ` Vineet Gupta
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-17 13:33 UTC (permalink / raw)
  To: Alexey Brodkin
  Cc: linux-arch, linux-kernel, arnd, arc-linux-dev,
	Arnaldo Carvalho de Melo, Vineet Gupta

On Tue, Jun 16, 2015 at 11:45:52AM +0000, Alexey Brodkin wrote:
> First let me clarify a bit how we deal with hardware events in ARC cores.
> 
>  a) ARC core may have an arbitrary set of hardware events built-in.
>  Upon creation of new ASIC project hardware engineer may select which
>  events will be exposed to event counters. For example only a very
>  basic set of events could be made available like "cycles running",
>  "committed instructions" etc. Or much more extensive set of events
>  could be exposed to event counters including very specific
>  architectural events like separate "committed 16-bit instructions"
>  and "committed 32-bit instructions".
> 
>  b) Also list of all possible events is much longer than 32 or 64
>  entries that makes it impossible to map all possible events as a
>  separate bits in 32- or 64-bit word.
> 
> Having both [a] and [b] in mind we implemented the following scheme of working with HW events.
> 
>  [1] Hardware may report a list of all event that could be counted in this particular CPU.
> 
>  [2] That lists consists of short ASCII names (up to 8 characters) for each event.
> 
>  [3] Index of the particular even in the list is used to setup an event counter.
> 
> See corresponding code for it here:
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arc/kernel/perf_event.c#n308
> 
> I.e. if we need to count "xxx" event and we know it's 10th in the list
> of events we set event counter to count event #10, see
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arc/kernel/perf_event.c#n151
> 
> With generic hardware events we don't do any visible trickery as you
> may see from code by the link above simply because we know how to
> translate PERF_COUNT_HW_CPU_CYCLES to the index of corresponding
> event, see:
> http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arc/include/asm/perf_event.h#n87
> 
> But in case of raw events we need to set a counter with index of a
> particular event. For example we need to count "myevnt0" events. For
> this we need first to find-out what's an index in events list of
> "myevnt0" event and then set event counter to count event #x.
> 
> Even though in theory we may set raw even passing an index of desired
> event 

That is what I was thinking of, until I read:

> but given my explanation above each particular CPU may have the
> same event with different index in events list.

...

> Fortunately there's already a patch series floating in LKML that
> attempts to simplify usage of architecture-specific events, see
> http://www.spinics.net/lists/kernel/msg2010232.html

So you _can_ know a priory in which order the events are for a
particular CPU ? Say through /proc/cpuinfo.

I would much prefer the raw thing to remain a number; it puts you in
pretty much the same place as most other archs, including x86.

On x86 we have a huge event list (see the Intel SDM for example) and the
only way to access those (currently, without the above patch series) is
to look in the PDF under the right model and enter the numbers by hand.


The only way in which your hardware appears different is in that it
seems to include these names in hardware; which to me seems a waste of
perfectly fine silicon, but hey not my call.


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/8] ARC: perf: support RAW events
  2015-06-17 13:33       ` Peter Zijlstra
@ 2015-06-17 14:10         ` Vineet Gupta
  2015-06-22 14:41           ` Peter Zijlstra
  0 siblings, 1 reply; 26+ messages in thread
From: Vineet Gupta @ 2015-06-17 14:10 UTC (permalink / raw)
  To: Peter Zijlstra, Alexey Brodkin
  Cc: linux-arch, linux-kernel, arnd, arc-linux-dev,
	Arnaldo Carvalho de Melo, Vineet Gupta

On Wednesday 17 June 2015 07:03 PM, Peter Zijlstra wrote:
>> But in case of raw events we need to set a counter with index of a
>> > particular event. For example we need to count "myevnt0" events. For
>> > this we need first to find-out what's an index in events list of
>> > "myevnt0" event and then set event counter to count event #x.
>> > 
>> > Even though in theory we may set raw even passing an index of desired
>> > event 
> That is what I was thinking of, until I read:
> 
>> > but given my explanation above each particular CPU may have the
>> > same event with different index in events list.
> ...
> 
>> > Fortunately there's already a patch series floating in LKML that
>> > attempts to simplify usage of architecture-specific events, see
>> > http://www.spinics.net/lists/kernel/msg2010232.html
> So you _can_ know a priory in which order the events are for a
> particular CPU ? Say through /proc/cpuinfo.
> 
> I would much prefer the raw thing to remain a number; it puts you in
> pretty much the same place as most other archs, including x86.

Sure, but that doesn't mean we start using the index of event as a raw ID. There
are zillion ways to configure cores and the index will certainly start varying.
Which means that user has to determine at run time (using whatever /proc/xxx) what
crun corresponds to. Why inflict such pain on poor guy.

The current raw event, despite representing an ASCII string is still a u64 number.
So it is not more "raw" than what others have. We can get rid of the swapping
business when setting up a raw event, by making sure that cached values from probe
are already in same format.

But using index as a event id is no go sorry...

> 
> On x86 we have a huge event list (see the Intel SDM for example) and the
> only way to access those (currently, without the above patch series) is
> to look in the PDF under the right model and enter the numbers by hand.

It is not much different for us !

> The only way in which your hardware appears different is in that it
> seems to include these names in hardware; which to me seems a waste of
> perfectly fine silicon, but hey not my call.

Yeah sins of the past.... :-)



^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/8] ARC: perf: support RAW events
  2015-06-17 14:10         ` Vineet Gupta
@ 2015-06-22 14:41           ` Peter Zijlstra
  2015-06-23 12:20             ` Vineet Gupta
  0 siblings, 1 reply; 26+ messages in thread
From: Peter Zijlstra @ 2015-06-22 14:41 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: Alexey Brodkin, linux-arch, linux-kernel, arnd, arc-linux-dev,
	Arnaldo Carvalho de Melo, jolsa

On Wed, Jun 17, 2015 at 07:40:37PM +0530, Vineet Gupta wrote:
> > I would much prefer the raw thing to remain a number; it puts you in
> > pretty much the same place as most other archs, including x86.
> 
> Sure, but that doesn't mean we start using the index of event as a raw ID. There
> are zillion ways to configure cores and the index will certainly start varying.
> Which means that user has to determine at run time (using whatever /proc/xxx) what
> crun corresponds to. Why inflict such pain on poor guy.
> 
> The current raw event, despite representing an ASCII string is still a u64 number.
> So it is not more "raw" than what others have. We can get rid of the swapping
> business when setting up a raw event, by making sure that cached values from probe
> are already in same format.
> 
> But using index as a event id is no go sorry...

Well, you're still stuck converting an 8 char ASCII string to hex, which
arguably isn't too hard, but still rather ugly.

Furthermore, the 'raw' interface is what is used to pass in hardware
configuration otherwise not exposed. If all you currently have is event
idx that's not too interesting.

However, your patch 6 already introduces event modifiers:

+#define ARC_REG_PCT_CONFIG_USER        (1 << 18)       /* count in user mode */
+#define ARC_REG_PCT_CONFIG_KERN        (1 << 19)       /* count in kernel mode */

Those should also be available through the raw interface.

That is, your perf_event_attr::config should pretty much end up in your
hardware unmodified -- with the obvious exception of things like
'interrupt enable' because we want the kernel to be in control of that.

So if you 'overload' your TYPE_RAW to mean something else entirely, you
also loose the ability to specify event modifiers not otherwise modelled
in perf.


There are things you could do though; you could for instance interpret a
!0 perf_event_attr::config1 as the name field and replace the
perf_event_attr::config's event idx with whatever comes out of that
name->idx map -- and/or require perf_event_attr::config's event idx to
be 0 in that case.

This of course assumes there will never be an other valid use for
::config1.

Alternatively you can register a second pmu "cpu_name" and interpret its
::config as the name.


Also, ideally you'd convince acme/jolsa to extend the event parser with
this 8-char ASCII format so you can do all the text munging in userspace
and not have to do the ugly you propose here.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/8] ARCv2: perf: implement "event_set_period" for future use with interrupts
  2015-06-15 15:38   ` Peter Zijlstra
@ 2015-06-22 15:26     ` Alexey Brodkin
  0 siblings, 0 replies; 26+ messages in thread
From: Alexey Brodkin @ 2015-06-22 15:26 UTC (permalink / raw)
  To: peterz; +Cc: Vineet.Gupta1, linux-arch, linux-kernel, arnd, acme, arc-linux-dev

Hi Peter,

On Mon, 2015-06-15 at 17:38 +0200, Peter Zijlstra wrote:
> On Tue, Jun 09, 2015 at 05:49:27PM +0530, Vineet Gupta wrote:
> > @@ -99,8 +99,7 @@ static void arc_perf_event_update(struct 
> > perf_event *event,
> >     } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
> >                              new_raw_count) != 
> > prev_raw_count);
> >  
> > -   delta = (new_raw_count - prev_raw_count) &
> > -           ((1ULL << arc_pmu->counter_size) - 1ULL);
> > +   delta = (new_raw_count - prev_raw_count) & arc_pmu
> > ->max_period;
> 
> I don't know how your PMU works, but you seem to be assuming new_raw
> prev_raw, which implies its counting up.
> 
> Now, typically these things trigger when they reach 0, so when we're
> counting up that would mean your values are negative.
> 
> In that case, where's the sign extension?

Our HW even counters work that way:
Each counter counts from programmed start value (set in
ARC_REG_PCT_COUNT) to a limit value (set in ARC_REG_PCT_INT_CNT) and
once limit value is reached this timer generates an interrupt.

Even though this HW implementation allows for more flexibility in Linux
kernel we decided to mimic behavior of other architectures in this way:

 [1] Set limit value as half of counter's max value:
 ---------->8-----------
 arc_pmu->max_period = (1ULL << counter_size) / 2 - 1ULL;
 ---------->8-----------

 [2] Set start value as "arc_pmu->max_period - sample_period" and then
count up to the limit

Our event counters don't stop on reaching max value (the one we set in
ARC_REG_PCT_INT_CNT) but continue to count until kernel explicitly
stops each of them.

And setting a limit as half of counter capacity is done to allow
capturing of additional events in between moment when interrupt was
triggered until we're actually processing PMU interrupts. That way
we're trying to be more precise.

For example if we count CPU cycles we keep track of cycles while
running through generic IRQ handling code:

 [1] We set counter period as say 100_000 events of type "crun"
 [2] Counter reaches that limit and raises its interrupt
 [3] Once we get in PMU IRQ handler we read current counter value from
ARC_REG_PCT_SNAP ans see there something like 105_000.

If counters stop on reaching a limit value then we would miss
additional 5000 cycles.

> 
> 
> > @@ -182,6 +181,13 @@ static int arc_pmu_event_init(struct 
> > perf_event *event)
> >     struct hw_perf_event *hwc = &event->hw;
> >     int ret;
> >  
> > +   if (!is_sampling_event(event)) {
> > +           hwc->sample_period  = arc_pmu->max_period;
> > +           hwc->last_period = hwc->sample_period;
> > +           local64_set(&hwc->period_left, hwc
> > ->sample_period);
> > +   } else
> > +           return -ENOENT;
> 
> -ENOENT is wrong for is_sampling_event().
> 
> Either the event is for this PMU, in which case you should return a
> fatal error, or its not (-ENOENT is correct in that case).

Frankly I didn't quite understand that comment.

What is meant in that code - our hardware may have support of
interrupts in HW counters or not. And that is not only dependent on ARC
core version (in fact ARC 700 may have only interrupt-less PMU) but
could be configured during designing of ASIC (i.e. ARC HS38 may have
PMU with or without interrupts).

That's why we check for event type and if we cannot handle it due to
limitation of current HW then we return -ENOENT.

-Alexey
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts
  2015-06-15 15:48   ` Peter Zijlstra
@ 2015-06-22 15:57     ` Alexey Brodkin
  0 siblings, 0 replies; 26+ messages in thread
From: Alexey Brodkin @ 2015-06-22 15:57 UTC (permalink / raw)
  To: peterz; +Cc: Vineet.Gupta1, linux-arch, linux-kernel, arnd, acme, arc-linux-dev

Hi Peter,

On Mon, 2015-06-15 at 17:48 +0200, Peter Zijlstra wrote:
> On Tue, Jun 09, 2015 at 05:49:28PM +0530, Vineet Gupta wrote:
> > From: Alexey Brodkin <abrodkin@synopsys.com>
> 
> -ENOCHANGELOG
> 
> > Cc: Peter Zijlstra <peterz@infradead.org>
> > Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> > Signed-off-by: Alexey Brodkin <abrodkin@synopsys.com>
> > Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
> > ---
> 
> >  struct arc_pmu {
> >     struct pmu      pmu;
> > +   int             has_interrupts;
> 
> we have pmu::flags & PERF_PMU_CAP_NO_INTERRUPT

Ah... if we set that flag perf_event_open() won't allow user to use
sampling events anyways so we may drop "arc_pmu.has_interrupts"
completely, right?

> 
> > @@ -186,7 +189,8 @@ static int arc_pmu_event_init(struct perf_event 
> > *event)
> >             hwc->last_period = hwc->sample_period;
> >             local64_set(&hwc->period_left, hwc
> > ->sample_period);
> >     } else
> > -           return -ENOENT;
> > +           if (!arc_pmu->has_interrupts)
> > +                   return -ENOENT;
> 
> Same as before, first determine if the event is yours, then return a
> fatal error.

Indeed with my note above that check makes no sense - perf framework
will do that same check instead.

> > @@ -307,6 +311,17 @@ static void arc_pmu_stop(struct perf_event 
> > *event, int flags)
> >     struct hw_perf_event *hwc = &event->hw;
> >     int idx = hwc->idx;
> >  
> > +   /* Disable interrupt for this counter */
> > +   if (is_sampling_event(event)) {
> 
> but but but, a sampling event needs the interrupt enabled?

Indeed sampling event needs the interrupt enabled. What's wrong with
that fact? Or I'm missing something?

> > +           /*
> > +            * Reset interrupt flag by writing of 1. This is 
> > required
> > +            * to make sure pending interrupt was not left.
> > +            */
> 
> Would not typically the interrupt latch be a property of the 
> interrupt
> controller, not the device generating it?
> 
> That is, how can the device programming affect pending interrupts?

The point here is our hardware counters are built in CPU core and
interrupt line from PMU block is wired directly to the top-level INTC.

Moreover that one IRQ line from PMU (or HW event counters how we call
them) is a logical OR of interrupts from each even counter (we may have
from 1 to 32 counters built-in). That means to clear a pending
interrupt from PMU block we need to clear states of individual
interrupts (per counter) in PMU.

> > +           write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
> > +           write_aux_reg(ARC_REG_PCT_INT_CTRL,
> > +                    
> >      read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~(1 << idx));
> > +   }
> > +
> 
> > +   if (is_sampling_event(event)) {
> > +           /* Mimic full counter overflow as other arches do 
> > */
> 
> With this you mean the pretending we have 63bit of overflow counter?

Correct. In more details it is covered in my comments in [PATCH 3/8].

> > +           write_aux_reg(ARC_REG_PCT_INT_CNTL, arc_pmu
> > ->max_period &
> > +                                               0xffffffff);
> 
> Would not (u32)arc_pmu->max_period, be clearer?

True, makes sense.

> > +           write_aux_reg(ARC_REG_PCT_INT_CNTH,
> > +                         (arc_pmu->max_period >> 32));
> 
> But should you not program: min(period, max_period) instead? If the
> requested period is shorter than your max period you do not want to
> program the max. Or are you missing a negative somewhere?

Here we just program the limit which is used for triggering an
interrupt. We don't care about "period" being > than "max_period"
because in arc_pmu_start()->arc_pmu_event_set_period() we do that check
when actually setting start value of a counter.

> That is, program the max_period for !sampling events to deal with
> overflow folding.

Once again we deal with overflow folding in arc_pmu_event_set_period()
even for !sampling events. But there's no need to program max_period in
PMU registers because hardware doesn't care about it - we just use that
value in software. Moreover if HW lacks PMU IRQ support then attempt to
access missing registers (for example ARC_REG_PCT_INT_CNT) will
inevitably lead to instruction error exception.

-Alexey--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/8] ARC: perf: support RAW events
  2015-06-22 14:41           ` Peter Zijlstra
@ 2015-06-23 12:20             ` Vineet Gupta
  0 siblings, 0 replies; 26+ messages in thread
From: Vineet Gupta @ 2015-06-23 12:20 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Alexey Brodkin, linux-arch, linux-kernel, arnd, arc-linux-dev,
	Arnaldo Carvalho de Melo, jolsa

On Monday 22 June 2015 08:11 PM, Peter Zijlstra wrote:
> On Wed, Jun 17, 2015 at 07:40:37PM +0530, Vineet Gupta wrote:
>>> I would much prefer the raw thing to remain a number; it puts you in
>>> pretty much the same place as most other archs, including x86.
>>
>> Sure, but that doesn't mean we start using the index of event as a raw ID. There
>> are zillion ways to configure cores and the index will certainly start varying.
>> Which means that user has to determine at run time (using whatever /proc/xxx) what
>> crun corresponds to. Why inflict such pain on poor guy.
>>
>> The current raw event, despite representing an ASCII string is still a u64 number.
>> So it is not more "raw" than what others have. We can get rid of the swapping
>> business when setting up a raw event, by making sure that cached values from probe
>> are already in same format.
>>
>> But using index as a event id is no go sorry...
> 
> Well, you're still stuck converting an 8 char ASCII string to hex, which
> arguably isn't too hard, but still rather ugly.

I agree that it might not be pretty, but using the h/w index as raw event ID is
not feasible since it is not ABI stable. ARC cores are highly configurable and if
u strip out a component, the related counters vanish, so the index of same counter
can change across h/w builds for say 16k vs. 32k L1 dcache builds.

Arguably we could setup a /proc or sysfs entry for mapping which user would have
to lookup. But it is not as clean/obvious as him looking up the Processor Manual
which describes the conditions with a human readable name - after all our
designers went to a stretch, to really call them out by names and not some obscure
numbers :-)

So I presume that we agree with not using h/w index itself for ID and need to look
for on/more solutions you allude to below.

> Furthermore, the 'raw' interface is what is used to pass in hardware
> configuration otherwise not exposed. If all you currently have is event
> idx that's not too interesting.
> 
> However, your patch 6 already introduces event modifiers:
> 
> +#define ARC_REG_PCT_CONFIG_USER        (1 << 18)       /* count in user mode */
> +#define ARC_REG_PCT_CONFIG_KERN        (1 << 19)       /* count in kernel mode */
> 
> Those should also be available through the raw interface.
> 
> That is, your perf_event_attr::config should pretty much end up in your
> hardware unmodified -- with the obvious exception of things like
> 'interrupt enable' because we want the kernel to be in control of that.

The value which goes in hardware is h/w index, which we can't pass from userspace
due to ABI reasons I describe above. Some alteration has to be made to any value
we pass from userspace, before it goes into the pct itself.

> 
> So if you 'overload' your TYPE_RAW to mean something else entirely, you
> also loose the ability to specify event modifiers not otherwise modelled
> in perf.

Just like normal events, raw event specification also allows :u or :k suffix,
which are passed additionally as event->attr.exclude_{user,kernel}
But I understand you POV here.

> There are things you could do though; you could for instance interpret a
> !0 perf_event_attr::config1 as the name field and replace the
> perf_event_attr::config's event idx with whatever comes out of that
> name->idx map -- and/or require perf_event_attr::config's event idx to
> be 0 in that case.
> 
> This of course assumes there will never be an other valid use for
> ::config1.

Indeed that could be done, I don't think ARC PCT will have more use of config1.
And perhaps if it does, then there's config2 for future needs !


> Alternatively you can register a second pmu "cpu_name" and interpret its
> ::config as the name.
> 
> 
> Also, ideally you'd convince acme/jolsa to extend the event parser with
> this 8-char ASCII format so you can do all the text munging in userspace
> and not have to do the ugly you propose here.

So lets say such parsing facility did exist, what would it pass down to kernel. It
can't be the h/w index itself, so it has to be some other number which we then map
to the h/w index when setting up the event - so again it helps if that number is
what is present in prog ref manual.

FWIW, last time I'd proposed that we can stop the ugly looking string conversion
in raw event setup code, but it still won't be the exact raw value which goes into
h/w. Something like completely untested below:
--------------->

+static int arc_pmu_raw_event(u64 config)
+{
+       int i;
+
+       for (i = 0; i < arc_pmu->n_events; i++) {
+               if (config == arc_pmu->raw_events[i])
+                       return i;
+       }
+
+       return -ENOENT;
+}
+

@@ -309,6 +334,21 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
                cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);

+               /*
+                * In PCT register CC_NAME{0,1} event name string[] is saved
+                * from LSB side:
+                * e.g. cycles corresponds to "crun" and is saved as 0x6e757263
+                *                                                     n u r c
+                * However in perf cmdline they are specified in human order as
+                * r6372756e
+                *
+                * Thus save a 64bit swapped value for quick cross check at the
+                * time of raw event request
+                */
+               arc_pmu->raw_events[j] = ((u64)cc_name.indiv.word1 << 32) |
+                                               cc_name.indiv.word0;
+               arc_pmu->raw_events[j] = __swab64(arc_pmu->raw_events[j]);


^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2015-06-23 12:21 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-09 12:19 [PATCH 0/8] ARCv2 port to Linux - (C) perf Vineet Gupta
2015-06-09 12:19 ` [PATCH 1/8] ARC: perf: support RAW events Vineet Gupta
2015-06-15 15:30   ` Peter Zijlstra
2015-06-16 11:45     ` Alexey Brodkin
2015-06-17 13:33       ` Peter Zijlstra
2015-06-17 14:10         ` Vineet Gupta
2015-06-22 14:41           ` Peter Zijlstra
2015-06-23 12:20             ` Vineet Gupta
2015-06-17 12:32     ` Vineet Gupta
2015-06-09 12:19 ` [PATCH 2/8] ARC: perf: cap the number of counters to hardware max of 32 Vineet Gupta
2015-06-09 12:19 ` [PATCH 3/8] ARCv2: perf: implement "event_set_period" for future use with interrupts Vineet Gupta
2015-06-15 15:38   ` Peter Zijlstra
2015-06-22 15:26     ` Alexey Brodkin
2015-06-09 12:19 ` [PATCH 4/8] ARCv2: perf: Support sampling events using overflow interrupts Vineet Gupta
2015-06-15 15:48   ` Peter Zijlstra
2015-06-22 15:57     ` Alexey Brodkin
2015-06-15 16:25   ` Peter Zijlstra
2015-06-16  5:37     ` Vineet Gupta
2015-06-16  9:07       ` Peter Zijlstra
2015-06-16  9:33         ` Vineet Gupta
2015-06-17 11:48         ` Vineet Gupta
2015-06-17 12:44           ` Peter Zijlstra
2015-06-09 12:19 ` [PATCH 5/8] ARCv2: perf: set usable max period as a half of real max period Vineet Gupta
2015-06-09 12:19 ` [PATCH 6/8] ARCv2: perf: implement exclusion of event counting in user or kernel mode Vineet Gupta
2015-06-09 12:19 ` [PATCH 7/8] ARCv2: perf: SMP support Vineet Gupta
2015-06-09 12:19 ` [PATCH 8/8] ARCv2: perf: Finally introduce HS perf unit Vineet Gupta

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).