diff mbox

[[PATCH,v6,09/10] powerpc/perf/hv-24x7: Use PMU_TXN_READ interface

Message ID 1441336073-22750-10-git-send-email-sukadev@linux.vnet.ibm.com
State Not Applicable
Delegated to: David Miller
Headers show

Commit Message

Sukadev Bhattiprolu Sept. 4, 2015, 3:07 a.m. UTC
The 24x7 counters in Powerpc allow monitoring a large number of counters
simultaneously. They also allow reading several counters in a single
HCALL so we can get a more consistent snapshot of the system.

Use the PMU's transaction interface to monitor and read several event
counters at once. The idea is that users can group several 24x7 events
into a single group of events. We use the following logic to submit
the group of events to the PMU and read the values:

	pmu->start_txn()		// Initialize before first event

	for each event in group
		pmu->read(event);	// Queue each event to be read

	pmu->commit_txn()		// Read/update all queuedcounters

The ->commit_txn() also updates the event counts in the respective
perf_event objects.  The perf subsystem can then directly get the
event counts from the perf_event and can avoid submitting a new
->read() request to the PMU.

Thanks to input from Peter Zijlstra.

Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
---
Changelog[v6]
	[Peter Zijlstra] Change txn_flags to 'unsigned int'

Changelog[v3]
	- [Peter Zijlstra] Save the transaction state in ->start_txn() and
	  remove the flags parameter from ->commit_txn() and ->cancel_txn().
---
 arch/powerpc/perf/hv-24x7.c |  166 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 164 insertions(+), 2 deletions(-)

Comments

Michael Ellerman Sept. 8, 2015, 9:07 a.m. UTC | #1
On Thu, 2015-09-03 at 20:07 -0700, Sukadev Bhattiprolu wrote:
> The 24x7 counters in Powerpc allow monitoring a large number of counters
> simultaneously. They also allow reading several counters in a single
> HCALL so we can get a more consistent snapshot of the system.
> 
> Use the PMU's transaction interface to monitor and read several event
> counters at once. The idea is that users can group several 24x7 events
> into a single group of events. We use the following logic to submit
> the group of events to the PMU and read the values:
> 
> 	pmu->start_txn()		// Initialize before first event
> 
> 	for each event in group
> 		pmu->read(event);	// Queue each event to be read
> 
> 	pmu->commit_txn()		// Read/update all queuedcounters
> 
> The ->commit_txn() also updates the event counts in the respective
> perf_event objects.  The perf subsystem can then directly get the
> event counts from the perf_event and can avoid submitting a new
> ->read() request to the PMU.
> 
> Thanks to input from Peter Zijlstra.
> 
> Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> ---
>  arch/powerpc/perf/hv-24x7.c |  166 ++++++++++++++++++++++++++++++++++++++++++-

This looks fine to me from an arch perspective. I assume the whole series can
go via tip-something?

Acked-by: Michael Ellerman <mpe@ellerman.id.au>

cheers


--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Peter Zijlstra Sept. 8, 2015, 11:29 a.m. UTC | #2
On Tue, Sep 08, 2015 at 07:07:55PM +1000, Michael Ellerman wrote:
> On Thu, 2015-09-03 at 20:07 -0700, Sukadev Bhattiprolu wrote:
> > The 24x7 counters in Powerpc allow monitoring a large number of counters
> > simultaneously. They also allow reading several counters in a single
> > HCALL so we can get a more consistent snapshot of the system.
> > 
> > Use the PMU's transaction interface to monitor and read several event
> > counters at once. The idea is that users can group several 24x7 events
> > into a single group of events. We use the following logic to submit
> > the group of events to the PMU and read the values:
> > 
> > 	pmu->start_txn()		// Initialize before first event
> > 
> > 	for each event in group
> > 		pmu->read(event);	// Queue each event to be read
> > 
> > 	pmu->commit_txn()		// Read/update all queuedcounters
> > 
> > The ->commit_txn() also updates the event counts in the respective
> > perf_event objects.  The perf subsystem can then directly get the
> > event counts from the perf_event and can avoid submitting a new
> > ->read() request to the PMU.
> > 
> > Thanks to input from Peter Zijlstra.
> > 
> > Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> > ---
> >  arch/powerpc/perf/hv-24x7.c |  166 ++++++++++++++++++++++++++++++++++++++++++-
> 
> This looks fine to me from an arch perspective. I assume the whole series can
> go via tip-something?

Yeah, I've had it queued for a few days, there was one s390 compile
fail reported by the build-bot, which I've just fixed. So if nothing
weird happens, it should hit tip somewhere this week.

> Acked-by: Michael Ellerman <mpe@ellerman.id.au>

Thanks!
--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michael Ellerman Sept. 9, 2015, 2:15 a.m. UTC | #3
On Tue, 2015-09-08 at 13:29 +0200, Peter Zijlstra wrote:
> On Tue, Sep 08, 2015 at 07:07:55PM +1000, Michael Ellerman wrote:
> > On Thu, 2015-09-03 at 20:07 -0700, Sukadev Bhattiprolu wrote:
> > > The 24x7 counters in Powerpc allow monitoring a large number of counters
> > > simultaneously. They also allow reading several counters in a single
> > > HCALL so we can get a more consistent snapshot of the system.
> > > 
> > > Use the PMU's transaction interface to monitor and read several event
> > > counters at once. The idea is that users can group several 24x7 events
> > > into a single group of events. We use the following logic to submit
> > > the group of events to the PMU and read the values:
> > > 
> > > 	pmu->start_txn()		// Initialize before first event
> > > 
> > > 	for each event in group
> > > 		pmu->read(event);	// Queue each event to be read
> > > 
> > > 	pmu->commit_txn()		// Read/update all queuedcounters
> > > 
> > > The ->commit_txn() also updates the event counts in the respective
> > > perf_event objects.  The perf subsystem can then directly get the
> > > event counts from the perf_event and can avoid submitting a new
> > > ->read() request to the PMU.
> > > 
> > > Thanks to input from Peter Zijlstra.
> > > 
> > > Signed-off-by: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
> > > ---
> > >  arch/powerpc/perf/hv-24x7.c |  166 ++++++++++++++++++++++++++++++++++++++++++-
> > 
> > This looks fine to me from an arch perspective. I assume the whole series can
> > go via tip-something?
> 
> Yeah, I've had it queued for a few days, there was one s390 compile
> fail reported by the build-bot, which I've just fixed. So if nothing
> weird happens, it should hit tip somewhere this week.

Great, thanks.

Now Sukadev can focus on getting the JSON events support merged, hopefully it
won't require another 16 versions.

cheers


--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sukadev Bhattiprolu Sept. 9, 2015, 9:12 p.m. UTC | #4
Michael Ellerman [mpe@ellerman.id.au] wrote:
| > > This looks fine to me from an arch perspective. I assume the whole series can
| > > go via tip-something?
| > 
| > Yeah, I've had it queued for a few days, there was one s390 compile
| > fail reported by the build-bot, which I've just fixed. So if nothing
| > weird happens, it should hit tip somewhere this week.

Peter, thanks for fixing the typo.

| 
| Great, thanks.
| 
| Now Sukadev can focus on getting the JSON events support merged, hopefully it
| won't require another 16 versions.

:-) BTW, other than an occasional patch from Andi Kleen (on top of the v16), I
have not received any comments on the JSON file patch set, so I don't have a
v17 in the pipeline...

Sukadev

--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Michael Ellerman Sept. 10, 2015, 12:43 a.m. UTC | #5
On Wed, 2015-09-09 at 14:12 -0700, Sukadev Bhattiprolu wrote:
> Michael Ellerman [mpe@ellerman.id.au] wrote:
> | > > This looks fine to me from an arch perspective. I assume the whole series can
> | > > go via tip-something?
> | > 
> | > Yeah, I've had it queued for a few days, there was one s390 compile
> | > fail reported by the build-bot, which I've just fixed. So if nothing
> | > weird happens, it should hit tip somewhere this week.
> 
> Peter, thanks for fixing the typo.
> 
> | 
> | Great, thanks.
> | 
> | Now Sukadev can focus on getting the JSON events support merged, hopefully it
> | won't require another 16 versions.
> 
> :-) BTW, other than an occasional patch from Andi Kleen (on top of the v16), I
> have not received any comments on the JSON file patch set, so I don't have a
> v17 in the pipeline...

Yeah. I assume everyone's happy with it and someone is going to pick it up for
the next merge window?

cheers


--
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index df95629..c268f9e 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -142,6 +142,15 @@  static struct attribute_group event_long_desc_group = {
 
 static struct kmem_cache *hv_page_cache;
 
+DEFINE_PER_CPU(int, hv_24x7_txn_flags);
+DEFINE_PER_CPU(int, hv_24x7_txn_err);
+
+struct hv_24x7_hw {
+	struct perf_event *events[255];
+};
+
+DEFINE_PER_CPU(struct hv_24x7_hw, hv_24x7_hw);
+
 /*
  * request_buffer and result_buffer are not required to be 4k aligned,
  * but are not allowed to cross any 4k boundary. Aligning them to 4k is
@@ -1233,9 +1242,48 @@  static void update_event_count(struct perf_event *event, u64 now)
 static void h_24x7_event_read(struct perf_event *event)
 {
 	u64 now;
+	struct hv_24x7_request_buffer *request_buffer;
+	struct hv_24x7_hw *h24x7hw;
+	int txn_flags;
+
+	txn_flags = __this_cpu_read(hv_24x7_txn_flags);
+
+	/*
+	 * If in a READ transaction, add this counter to the list of
+	 * counters to read during the next HCALL (i.e commit_txn()).
+	 * If not in a READ transaction, go ahead and make the HCALL
+	 * to read this counter by itself.
+	 */
+
+	if (txn_flags & PERF_PMU_TXN_READ) {
+		int i;
+		int ret;
 
-	now = h_24x7_get_value(event);
-	update_event_count(event, now);
+		if (__this_cpu_read(hv_24x7_txn_err))
+			return;
+
+		request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
+
+		ret = add_event_to_24x7_request(event, request_buffer);
+		if (ret) {
+			__this_cpu_write(hv_24x7_txn_err, ret);
+		} else {
+			/*
+			 * Assoicate the event with the HCALL request index,
+			 * so ->commit_txn() can quickly find/update count.
+			 */
+			i = request_buffer->num_requests - 1;
+
+			h24x7hw = &get_cpu_var(hv_24x7_hw);
+			h24x7hw->events[i] = event;
+			put_cpu_var(h24x7hw);
+		}
+
+		put_cpu_var(hv_24x7_reqb);
+	} else {
+		now = h_24x7_get_value(event);
+		update_event_count(event, now);
+	}
 }
 
 static void h_24x7_event_start(struct perf_event *event, int flags)
@@ -1257,6 +1305,117 @@  static int h_24x7_event_add(struct perf_event *event, int flags)
 	return 0;
 }
 
+/*
+ * 24x7 counters only support READ transactions. They are
+ * always counting and dont need/support ADD transactions.
+ * Cache the flags, but otherwise ignore transactions that
+ * are not PERF_PMU_TXN_READ.
+ */
+static void h_24x7_event_start_txn(struct pmu *pmu, unsigned int flags)
+{
+	struct hv_24x7_request_buffer *request_buffer;
+	struct hv_24x7_data_result_buffer *result_buffer;
+
+	/* We should not be called if we are already in a txn */
+	WARN_ON_ONCE(__this_cpu_read(hv_24x7_txn_flags));
+
+	__this_cpu_write(hv_24x7_txn_flags, flags);
+	if (flags & ~PERF_PMU_TXN_READ)
+		return;
+
+	request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
+	result_buffer = (void *)get_cpu_var(hv_24x7_resb);
+
+	init_24x7_request(request_buffer, result_buffer);
+
+	put_cpu_var(hv_24x7_resb);
+	put_cpu_var(hv_24x7_reqb);
+}
+
+/*
+ * Clean up transaction state.
+ *
+ * NOTE: Ignore state of request and result buffers for now.
+ *	 We will initialize them during the next read/txn.
+ */
+static void reset_txn(void)
+{
+	__this_cpu_write(hv_24x7_txn_flags, 0);
+	__this_cpu_write(hv_24x7_txn_err, 0);
+}
+
+/*
+ * 24x7 counters only support READ transactions. They are always counting
+ * and dont need/support ADD transactions. Clear ->txn_flags but otherwise
+ * ignore transactions that are not of type PERF_PMU_TXN_READ.
+ *
+ * For READ transactions, submit all pending 24x7 requests (i.e requests
+ * that were queued by h_24x7_event_read()), to the hypervisor and update
+ * the event counts.
+ */
+static int h_24x7_event_commit_txn(struct pmu *pmu)
+{
+	struct hv_24x7_request_buffer *request_buffer;
+	struct hv_24x7_data_result_buffer *result_buffer;
+	struct hv_24x7_result *resb;
+	struct perf_event *event;
+	u64 count;
+	int i, ret, txn_flags;
+	struct hv_24x7_hw *h24x7hw;
+
+	txn_flags = __this_cpu_read(hv_24x7_txn_flags);
+	WARN_ON_ONCE(!txn_flags);
+
+	ret = 0;
+	if (txn_flags & ~PERF_PMU_TXN_READ)
+		goto out;
+
+	ret = __this_cpu_read(hv_24x7_txn_err);
+	if (ret)
+		goto out;
+
+	request_buffer = (void *)get_cpu_var(hv_24x7_reqb);
+	result_buffer = (void *)get_cpu_var(hv_24x7_resb);
+
+	ret = make_24x7_request(request_buffer, result_buffer);
+	if (ret) {
+		log_24x7_hcall(request_buffer, result_buffer, ret);
+		goto put_reqb;
+	}
+
+	h24x7hw = &get_cpu_var(hv_24x7_hw);
+
+	/* Update event counts from hcall */
+	for (i = 0; i < request_buffer->num_requests; i++) {
+		resb = &result_buffer->results[i];
+		count = be64_to_cpu(resb->elements[0].element_data[0]);
+		event = h24x7hw->events[i];
+		h24x7hw->events[i] = NULL;
+		update_event_count(event, count);
+	}
+
+	put_cpu_var(hv_24x7_hw);
+
+put_reqb:
+	put_cpu_var(hv_24x7_resb);
+	put_cpu_var(hv_24x7_reqb);
+out:
+	reset_txn();
+	return ret;
+}
+
+/*
+ * 24x7 counters only support READ transactions. They are always counting
+ * and dont need/support ADD transactions. However, regardless of type
+ * of transaction, all we need to do is cleanup, so we don't have to check
+ * the type of transaction.
+ */
+static void h_24x7_event_cancel_txn(struct pmu *pmu)
+{
+	WARN_ON_ONCE(!__this_cpu_read(hv_24x7_txn_flags));
+	reset_txn();
+}
+
 static struct pmu h_24x7_pmu = {
 	.task_ctx_nr = perf_invalid_context,
 
@@ -1268,6 +1427,9 @@  static struct pmu h_24x7_pmu = {
 	.start       = h_24x7_event_start,
 	.stop        = h_24x7_event_stop,
 	.read        = h_24x7_event_read,
+	.start_txn   = h_24x7_event_start_txn,
+	.commit_txn  = h_24x7_event_commit_txn,
+	.cancel_txn  = h_24x7_event_cancel_txn,
 };
 
 static int hv_24x7_init(void)