From: Vineet Gupta <Vineet.Gupta1@synopsys.com>
To: <linux-arch@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Cc: <arnd@arndb.de>, Alexey Brodkin <Alexey.Brodkin@synopsys.com>,
<arc-linux-dev@synopsys.com>,
Peter Zijlstra <peterz@infradead.org>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Vineet Gupta <Vineet.Gupta1@synopsys.com>
Subject: [PATCH 7/8] ARCv2: perf: SMP support
Date: Tue, 9 Jun 2015 17:49:31 +0530 [thread overview]
Message-ID: <1433852372-29494-8-git-send-email-vgupta@synopsys.com> (raw)
In-Reply-To: <1433852372-29494-1-git-send-email-vgupta@synopsys.com>
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
next prev parent reply other threads:[~2015-06-09 12:22 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Vineet Gupta [this message]
2015-06-09 12:19 ` [PATCH 8/8] ARCv2: perf: Finally introduce HS perf unit Vineet Gupta
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1433852372-29494-8-git-send-email-vgupta@synopsys.com \
--to=vineet.gupta1@synopsys.com \
--cc=Alexey.Brodkin@synopsys.com \
--cc=acme@kernel.org \
--cc=arc-linux-dev@synopsys.com \
--cc=arnd@arndb.de \
--cc=linux-arch@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome