All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <peterz@infradead.org>
To: Christophe Leroy <christophe.leroy@c-s.fr>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>,
	Paul Mackerras <paulus@samba.org>,
	Michael Ellerman <mpe@ellerman.id.au>,
	Scott Wood <oss@buserror.net>, Ingo Molnar <mingo@redhat.com>,
	Arnaldo Carvalho de Melo <acme@kernel.org>,
	linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org,
	Alexander Shishkin <alexander.shishkin@linux.intel.com>
Subject: Re: [RFC 2/2] powerpc/8xx: Perf events on PPC 8xx
Date: Wed, 14 Dec 2016 10:16:29 +0100	[thread overview]
Message-ID: <20161214091629.GP3124@twins.programming.kicks-ass.net> (raw)
In-Reply-To: <8f8cb2298b929e0db5181c273b638ea6f5bf41e0.1481652710.git.christophe.leroy@c-s.fr>

On Tue, Dec 13, 2016 at 07:19:43PM +0100, Christophe Leroy wrote:
> +int mpc8xx_pmu_event_init(struct perf_event *event)
> +{
> +	int type = event_type(event);
> +
> +	switch (type) {
> +	case PERF_8xx_ID_CPU_CYCLES:
> +	case PERF_8xx_ID_ITLB_LOAD_MISS:
> +	case PERF_8xx_ID_DTLB_LOAD_MISS:
> +		break;
> +	case PERF_8xx_ID_HW_INSTRUCTIONS:
> +		mtspr(SPRN_CMPA, 0);

Should that not live in init_mpc8xx_pmu() ?

Afaict its a one time setup thing.

> +		break;
> +	default:
> +		return type;
> +	}
> +	return 0;
> +}
> +
> +int mpc8xx_pmu_add(struct perf_event *event, int flags)
> +{
> +	int type = event_type(event);
> +	s64 val;
> +
> +	switch (type) {
> +	case PERF_8xx_ID_CPU_CYCLES:
> +		val = get_tb();
> +		break;
> +	case PERF_8xx_ID_HW_INSTRUCTIONS:
> +		val = (instruction_counter << 16) | 0xffff;
> +		mtspr(SPRN_COUNTA, 0xffff0001);
> +		mtspr(SPRN_ICTRL, 0xc0080007);
> +		break;

So this sets up the counter and starts counting, right?

What happens if someone adds two events of this type?

Also, typical implementations would do:

	if (flags & PERF_EF_START)
		mpc8xx_pmu_start(event, flags);


> +	case PERF_8xx_ID_ITLB_LOAD_MISS:
> +		val = itlb_miss_counter;
> +		break;
> +	case PERF_8xx_ID_DTLB_LOAD_MISS:
> +		val = dtlb_miss_counter;
> +		break;
> +	default:
> +		break;
> +	}
> +	local64_set(&event->hw.prev_count, val);

Right, so aside from that INSTRUCTION event, the rest is treated like
freerunning counters which is fine.

> +	return 0;
> +}
> +
> +void mpc8xx_pmu_read(struct perf_event *event)
> +{
> +	int type = event_type(event);
> +	s64 prev, val, delta;
> +
> +	prev = local64_read(&event->hw.prev_count);
> +	switch (type) {
> +	case PERF_8xx_ID_CPU_CYCLES:
> +		val = get_tb();
> +		delta = 16 * (val - prev);
> +		break;
> +	case PERF_8xx_ID_HW_INSTRUCTIONS:
> +		mtspr(SPRN_ICTRL, 7);
> +		val = (instruction_counter << 16) | (0xffff - (mfspr(SPRN_COUNTA) >> 16));
> +		mtspr(SPRN_ICTRL, 0xc0080007);
> +		delta = val - prev;
> +		break;
> +	case PERF_8xx_ID_ITLB_LOAD_MISS:
> +		val = itlb_miss_counter;
> +		delta = val - prev;
> +		break;
> +	case PERF_8xx_ID_DTLB_LOAD_MISS:
> +		val = dtlb_miss_counter;
> +		delta = val - prev;
> +		break;
> +	default:
> +		break;
> +	}
> +	local64_set(&event->hw.prev_count, val);
> +	local64_add(delta, &event->count);
> +}

So there is one case, where we group this event with a software hrtimer
event and the hrtimer would call ::read() from interrupt context while
you're already in ::read().

This seems to suggest you still need a cmpxchg() loop to update, no?

> +void mpc8xx_pmu_del(struct perf_event *event, int flags)
> +{
> +	int type = event_type(event);
> +	s64 prev, val;
> +
> +	prev = local64_read(&event->hw.prev_count);
> +	switch (type) {
> +	case PERF_8xx_ID_HW_INSTRUCTIONS:
> +		mtspr(SPRN_ICTRL, 7);
> +		val = (instruction_counter << 16) | (0xffff - (mfspr(SPRN_COUNTA) >> 16));
> +		local64_add(val - prev, &event->count);
> +		break;
> +	case PERF_8xx_ID_CPU_CYCLES:
> +	case PERF_8xx_ID_ITLB_LOAD_MISS:
> +	case PERF_8xx_ID_DTLB_LOAD_MISS:
> +		mpc8xx_pmu_read(event);
> +		break;
> +	default:
> +		break;
> +	}

Right, so you make all del()'s imply PERF_EF_UPDATE, which is fine.

> +}
> +
> +void mpc8xx_pmu_start(struct perf_event *event, int flags)
> +{
> +}
> +
> +void mpc8xx_pmu_stop(struct perf_event *event, int flags)
> +{
> +}

So I think you can get away with doing this because the PMU doesn't do
sampling, which is what would normally start/stop already programmed
counters.

> +static struct pmu mpc8xx_pmu = {
> +	.event_init	= mpc8xx_pmu_event_init,
> +	.add		= mpc8xx_pmu_add,
> +	.del		= mpc8xx_pmu_del,
> +	.start		= mpc8xx_pmu_start,
> +	.stop		= mpc8xx_pmu_stop,
> +	.read		= mpc8xx_pmu_read,

	.capabilities	= PERF_PMU_CAP_NO_INTERRUPT |
			  PERF_PMU_CAP_NO_NMI,

> +};
> +
> +static int init_mpc8xx_pmu(void)
> +{
> +	return perf_pmu_register(&mpc8xx_pmu, "cpu", PERF_TYPE_RAW);
> +}
> +
> +early_initcall(init_mpc8xx_pmu);

      reply	other threads:[~2016-12-14  9:16 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <cover.1481652710.git.christophe.leroy@c-s.fr>
2016-12-13 18:19 ` [RFC 1/2] powerpc/32: Unset MSR RI in exception epilogs Christophe Leroy
2016-12-13 19:15   ` Segher Boessenkool
2016-12-13 20:39     ` christophe leroy
2016-12-13 22:54       ` Segher Boessenkool
2016-12-14  8:40         ` Peter Zijlstra
2016-12-13 18:19 ` [RFC 2/2] powerpc/8xx: Perf events on PPC 8xx Christophe Leroy
2016-12-14  9:16   ` Peter Zijlstra [this message]

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=20161214091629.GP3124@twins.programming.kicks-ass.net \
    --to=peterz@infradead.org \
    --cc=acme@kernel.org \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=benh@kernel.crashing.org \
    --cc=christophe.leroy@c-s.fr \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=mingo@redhat.com \
    --cc=mpe@ellerman.id.au \
    --cc=oss@buserror.net \
    --cc=paulus@samba.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.