From: Matt Fleming <matt@console-pimps.org>
To: Deng-Cheng Zhu <dengcheng.zhu@gmail.com>
Cc: linux-mips@linux-mips.org, ralf@linux-mips.org,
a.p.zijlstra@chello.nl, paulus@samba.org, mingo@elte.hu,
acme@redhat.com, jamie.iles@picochip.com
Subject: Re: [PATCH v6 4/7] MIPS: add support for hardware performance events (skeleton)
Date: Wed, 22 Sep 2010 13:27:11 +0100 [thread overview]
Message-ID: <20100922122711.GB6392@console-pimps.org> (raw)
In-Reply-To: <1276058130-25851-5-git-send-email-dengcheng.zhu@gmail.com>
On Wed, Jun 09, 2010 at 12:35:27PM +0800, Deng-Cheng Zhu wrote:
[...]
> +static void mipspmu_event_update(struct perf_event *event,
> + struct hw_perf_event *hwc,
> + int idx)
> +{
> + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
> + unsigned long flags;
> + int shift = 64 - TOTAL_BITS;
> + s64 prev_raw_count, new_raw_count;
> + s64 delta;
> +
> +again:
> + prev_raw_count = atomic64_read(&hwc->prev_count);
> + local_irq_save(flags);
> + /* Make the counter value be a "real" one. */
> + new_raw_count = mipspmu->read_counter(idx);
> + if (new_raw_count & (test_bit(idx, cpuc->msbs) << HIGHEST_BIT)) {
> + new_raw_count &= VALID_COUNT;
> + clear_bit(idx, cpuc->msbs);
> + } else
> + new_raw_count |= (test_bit(idx, cpuc->msbs) << HIGHEST_BIT);
> + local_irq_restore(flags);
I'm probably just being stupid but I can't figure out what this snippet
of code is doing. You're checking to see if the counter has overflowed,
and if it has then you just clear the overflow bit? I would have
expected you to reset the counter to 0.
> + if (atomic64_cmpxchg(&hwc->prev_count, prev_raw_count,
> + new_raw_count) != prev_raw_count)
> + goto again;
> +
> + delta = (new_raw_count << shift) - (prev_raw_count << shift);
> + delta >>= shift;
> +
> + atomic64_add(delta, &event->count);
> + atomic64_sub(delta, &hwc->period_left);
> +
> + return;
> +}
> +
> +static void mipspmu_disable(struct perf_event *event)
> +{
> + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
> + struct hw_perf_event *hwc = &event->hw;
> + int idx = hwc->idx;
> +
> +
> + WARN_ON(idx < 0 || idx >= mipspmu->num_counters);
> +
> + /* We are working on a local event. */
> + mipspmu->disable_event(idx);
> +
> + barrier();
> +
> + mipspmu_event_update(event, hwc, idx);
> + cpuc->events[idx] = NULL;
> + clear_bit(idx, cpuc->used_mask);
Shouldn't you also clear the overflow bit in ->msbs here?
> +
> + perf_event_update_userpage(event);
> +}
> +
> +static void mipspmu_unthrottle(struct perf_event *event)
> +{
> + struct hw_perf_event *hwc = &event->hw;
> +
> + mipspmu->enable_event(hwc, hwc->idx);
> +}
> +
> +static void mipspmu_read(struct perf_event *event)
> +{
> + struct hw_perf_event *hwc = &event->hw;
> +
> + /* Don't read disabled counters! */
> + if (hwc->idx < 0)
> + return;
> +
> + mipspmu_event_update(event, hwc, hwc->idx);
> +}
> +
> +static struct pmu pmu = {
> + .enable = mipspmu_enable,
> + .disable = mipspmu_disable,
> + .unthrottle = mipspmu_unthrottle,
> + .read = mipspmu_read,
> +};
> +
> +static atomic_t active_events = ATOMIC_INIT(0);
> +static DEFINE_MUTEX(pmu_reserve_mutex);
> +static int mips_pmu_irq = -1;
> +static int (*save_perf_irq)(void);
> +
> +static int mipspmu_get_irq(void)
> +{
> + int err;
> +
> + if (cpu_has_veic) {
> + /*
> + * Using platform specific interrupt controller defines.
> + */
> +#ifdef MSC01E_INT_BASE
> + mips_pmu_irq = MSC01E_INT_BASE + MSC01E_INT_PERFCTR;
> +#endif
> + } else if (cp0_perfcount_irq >= 0) {
> + /*
> + * Some CPUs have explicitly defined their perfcount irq.
> + */
> +#if defined(CONFIG_CPU_RM9000)
> + mips_pmu_irq = rm9000_perfcount_irq;
> +#elif defined(CONFIG_CPU_LOONGSON2)
> + mips_pmu_irq = LOONGSON2_PERFCNT_IRQ;
> +#else
> + mips_pmu_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
> +#endif
> + }
Having conditional code like this is a pretty sure sign that you haven't
separated support for the various performance hardware properly. Have
you had a look at how SH uses a registration interface to register
sh_pmus? Ideally all the internals for each type of perfcounter
hardware should be in their own file.
> +
> + if (mips_pmu_irq >= 0) {
> + /* Request my own irq handler. */
> + err = request_irq(mips_pmu_irq, mipspmu->handle_irq,
> + IRQF_DISABLED | IRQF_NOBALANCING,
> + "mips_perf_pmu", NULL);
> + if (err) {
> + pr_warning("Unable to request IRQ%d for MIPS "
> + "performance counters!\n", mips_pmu_irq);
> + }
> + } else if (cp0_perfcount_irq < 0) {
> + /*
> + * We are sharing the irq number with the timer interrupt.
> + */
> + save_perf_irq = perf_irq;
> + perf_irq = mipspmu->handle_shared_irq;
> + err = 0;
SH also has this problem that it doesn't have any sort of performance
counter interrupt and so can't check for overflow. This lack of
interrupt really needs to be solved generically in perf as it's a
problem that effects quite a few architectures. I suspect that using a
hrtimer instead of piggy-backing the timer interrupt would make the core
perf guys happier. Writing support for this is on my ever-growing list
of things todo. I've already started on some patches for the perf tool
so that it's possible to sample counters even though there is no
periodic interrupt (but that's a different problem).
next prev parent reply other threads:[~2010-09-22 12:27 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-06-09 4:35 [PATCH v6 0/7] MIPS performance event support v6 Deng-Cheng Zhu
2010-06-09 4:35 ` [PATCH v6 1/7] MIPS/Oprofile: extract PMU defines/helper functions for sharing Deng-Cheng Zhu
2010-06-09 4:35 ` [PATCH v6 2/7] MIPS: use generic atomic64 in non-64bit kernels Deng-Cheng Zhu
2010-06-09 16:58 ` David Daney
2010-08-06 16:45 ` Ralf Baechle
2010-06-09 4:35 ` [PATCH v6 3/7] MIPS: add support for software performance events Deng-Cheng Zhu
2010-09-22 11:38 ` Matt Fleming
2010-06-09 4:35 ` [PATCH v6 4/7] MIPS: add support for hardware performance events (skeleton) Deng-Cheng Zhu
2010-09-22 12:27 ` Matt Fleming [this message]
2010-09-23 7:39 ` Deng-Cheng Zhu
2010-09-24 8:36 ` Matt Fleming
2010-09-25 2:53 ` Deng-Cheng Zhu
2010-06-09 4:35 ` [PATCH v6 5/7] MIPS/Perf-events: add callchain support Deng-Cheng Zhu
2010-06-09 4:35 ` [PATCH v6 6/7] MIPS: add support for hardware performance events (mipsxx) Deng-Cheng Zhu
2010-06-09 4:35 ` [PATCH v6 7/7] MIPS: define local_xchg from xchg_local to atomic_long_xchg Deng-Cheng Zhu
2010-09-22 12:32 ` Matt Fleming
2010-09-23 7:56 ` Deng-Cheng Zhu
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=20100922122711.GB6392@console-pimps.org \
--to=matt@console-pimps.org \
--cc=a.p.zijlstra@chello.nl \
--cc=acme@redhat.com \
--cc=dengcheng.zhu@gmail.com \
--cc=jamie.iles@picochip.com \
--cc=linux-mips@linux-mips.org \
--cc=mingo@elte.hu \
--cc=paulus@samba.org \
--cc=ralf@linux-mips.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