linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Robert Richter <robert.richter@amd.com>
To: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: "Stephane Eranian" <eranian@google.com>,
	"Ingo Molnar" <mingo@elte.hu>,
	"Arnaldo Carvalho de Melo" <acme@infradead.org>,
	"Frédéric Weisbecker" <fweisbec@gmail.com>,
	"Paul Mackerras" <paulus@samba.org>,
	LKML <linux-kernel@vger.kernel.org>
Subject: [RFC PATCH] perf: align raw sample data on 64-bit boundaries
Date: Tue, 18 May 2010 17:12:27 +0200	[thread overview]
Message-ID: <20100518151227.GJ21799@erda.amd.com> (raw)
In-Reply-To: <n2wbd4cb8901004190519m9c939c26wbe49701fdfd2379a@mail.gmail.com>

On 19.04.10 14:19:57, Stephane Eranian wrote:
> > +       perf_sample_data_init(&data, 0);
> > +       if (event->attr.sample_type & PERF_SAMPLE_RAW) {
> > +               for (i = 1; i < size; i++)
> > +                       rdmsrl(msr++, *buf++);
> > +               raw.size = sizeof(u64) * size;
> > +               raw.data = buffer;
> > +               data.raw = &raw;
> > +       }
> > +
> 
> Need to add the padding: raw.size = sizeof(u64) * size + sizeof(u32);

When thinking about this I was wondering if it wouldn't make sense to
better fix the alignment and move the data buffer to a 64 bit
boundary. So take a look at the enclosed RFC patch. Though it breaks
the ABI it would solve some problems. I think more than it introduces.
Hopefully I found all effected code locations using it.

-Robert

--

>From 2427dda67b072f27ecff678f8829b9e2fc537988 Mon Sep 17 00:00:00 2001
From: Robert Richter <robert.richter@amd.com>
Date: Fri, 7 May 2010 15:32:45 +0200
Subject: [PATCH] perf: align raw sample data on 64-bit boundaries

In the current implementation 64 bit raw sample data values are not
aligned due to the 32 bit size header. The size header is located
before the data buffer on a 64 bit boundary. This leads to unaligned
memory access to the data buffer for arrays or structures containing
64 bit values. To avoid this, the patch adds a 32 bit reserved value
to the raw sample data header. The data buffer starts then at a 64 bit
boundary.

This changes the ABI and requires changes in the userland tools. For
tools/perf this is at a single location in event.c only. This could
also introduce some overhead on smaller architectures, but currently
this is only used on x86 or for transferring raw tracepoint
data. Though an ABI change should be avoided, it is worth to align raw
sample data on 64-bit boundaries as the change fixes unaligned memory
access, eases the implementation for raw sample data and reduces the
risk of data corruption due to different pad structures inserted by
the compiler.

Signed-off-by: Robert Richter <robert.richter@amd.com>
---
 include/linux/perf_event.h    |    1 +
 kernel/perf_event.c           |   21 ++++++++++-----------
 kernel/trace/trace_kprobe.c   |    6 ++----
 kernel/trace/trace_syscalls.c |    6 ++----
 tools/perf/util/event.c       |    4 ++--
 5 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 3fd5c82..016969c 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -431,6 +431,7 @@ enum perf_event_type {
 	 *	#
 	 *
 	 *	{ u32			size;
+	 *	  u32			reserved;
 	 *	  char                  data[size];}&& PERF_SAMPLE_RAW
 	 * };
 	 */
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
index a4fa381..12bb53d 100644
--- a/kernel/perf_event.c
+++ b/kernel/perf_event.c
@@ -3252,18 +3252,19 @@ void perf_output_sample(struct perf_output_handle *handle,
 	}
 
 	if (sample_type & PERF_SAMPLE_RAW) {
+		struct {
+			u32	size;
+			u32	reserved;
+		} raw = {
+			.size = 0,
+			.reserved = 0,
+		};
 		if (data->raw) {
-			perf_output_put(handle, data->raw->size);
+			raw.size = data->raw->size;
+			perf_output_put(handle, raw);
 			perf_output_copy(handle, data->raw->data,
 					 data->raw->size);
 		} else {
-			struct {
-				u32	size;
-				u32	data;
-			} raw = {
-				.size = sizeof(u32),
-				.data = 0,
-			};
 			perf_output_put(handle, raw);
 		}
 	}
@@ -3344,12 +3345,10 @@ void perf_prepare_sample(struct perf_event_header *header,
 	}
 
 	if (sample_type & PERF_SAMPLE_RAW) {
-		int size = sizeof(u32);
+		int size = sizeof(u64);
 
 		if (data->raw)
 			size += data->raw->size;
-		else
-			size += sizeof(u32);
 
 		WARN_ON_ONCE(size & (sizeof(u64)-1));
 		header->size += size;
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index a751432..00172b0 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1347,8 +1347,7 @@ static __kprobes void kprobe_perf_func(struct kprobe *kp,
 	int rctx;
 
 	__size = sizeof(*entry) + tp->size;
-	size = ALIGN(__size + sizeof(u32), sizeof(u64));
-	size -= sizeof(u32);
+	size = ALIGN(__size, sizeof(u64));
 	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
 		     "profile buffer not large enough"))
 		return;
@@ -1378,8 +1377,7 @@ static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri,
 	int rctx;
 
 	__size = sizeof(*entry) + tp->size;
-	size = ALIGN(__size + sizeof(u32), sizeof(u64));
-	size -= sizeof(u32);
+	size = ALIGN(__size, sizeof(u64));
 	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
 		     "profile buffer not large enough"))
 		return;
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index 4d6d711..ad7e713 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -453,8 +453,7 @@ static void perf_syscall_enter(struct pt_regs *regs, long id)
 
 	/* get the size after alignment with the u32 buffer size field */
 	size = sizeof(unsigned long) * sys_data->nb_args + sizeof(*rec);
-	size = ALIGN(size + sizeof(u32), sizeof(u64));
-	size -= sizeof(u32);
+	size = ALIGN(size, sizeof(u64));
 
 	if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE,
 		      "perf buffer not large enough"))
@@ -524,8 +523,7 @@ static void perf_syscall_exit(struct pt_regs *regs, long ret)
 		return;
 
 	/* We can probably do that at build time */
-	size = ALIGN(sizeof(*rec) + sizeof(u32), sizeof(u64));
-	size -= sizeof(u32);
+	size = ALIGN(sizeof(*rec), sizeof(u64));
 
 	/*
 	 * Impossible, but be paranoid with the future
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 50771b5..6902b85 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -790,8 +790,8 @@ int event__parse_sample(event_t *event, u64 type, struct sample_data *data)
 	if (type & PERF_SAMPLE_RAW) {
 		u32 *p = (u32 *)array;
 		data->raw_size = *p;
-		p++;
-		data->raw_data = p;
+		array++;
+		data->raw_data = array;
 	}
 
 	return 0;
-- 
1.7.1

-- 
Advanced Micro Devices, Inc.
Operating System Research Center
email: robert.richter@amd.com


  parent reply	other threads:[~2010-05-18 15:12 UTC|newest]

Thread overview: 55+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-04-13 20:23 [PATCH 00/12] perf: introduce model specific events and AMD IBS Robert Richter
2010-04-13 20:23 ` [PATCH 01/12] perf, x86: move perfctr init code to x86_setup_perfctr() Robert Richter
2010-05-07 18:42   ` [tip:perf/core] perf, x86: Move " tip-bot for Robert Richter
2010-04-13 20:23 ` [PATCH 02/12] perf, x86: moving x86_setup_perfctr() Robert Richter
2010-05-07 18:42   ` [tip:perf/core] perf, x86: Move x86_setup_perfctr() tip-bot for Robert Richter
2010-04-13 20:23 ` [PATCH 03/12] perf, x86: call x86_setup_perfctr() from .hw_config() Robert Richter
2010-05-07 18:42   ` [tip:perf/core] perf, x86: Call " tip-bot for Robert Richter
2010-04-13 20:23 ` [PATCH 04/12] perf: introduce flag for model specific events Robert Richter
2010-04-13 20:23 ` [PATCH 05/12] perf, x86: pass enable bit mask to __x86_pmu_enable_event() Robert Richter
2010-05-07 18:43   ` [tip:perf/core] perf, x86: Pass " tip-bot for Robert Richter
2010-04-13 20:23 ` [PATCH 06/12] perf, x86: use weight instead of cmask in for_each_event_constraint() Robert Richter
2010-05-07 18:43   ` [tip:perf/core] perf, x86: Use " tip-bot for Robert Richter
2010-04-13 20:23 ` [PATCH 07/12] perf, x86: introduce bit range for special pmu events Robert Richter
2010-04-13 20:23 ` [PATCH 08/12] perf, x86: modify some code to allow the introduction of ibs events Robert Richter
2010-04-13 20:23 ` [PATCH 09/12] perf, x86: implement IBS feature detection Robert Richter
2010-04-13 20:23 ` [PATCH 10/12] perf, x86: setup NMI handler for IBS Robert Richter
2010-04-15 12:57   ` Peter Zijlstra
2010-04-15 13:11     ` Robert Richter
2010-04-19 16:04       ` Robert Richter
2010-04-13 20:23 ` [PATCH 11/12] perf, x86: implement AMD IBS event configuration Robert Richter
2010-04-19 13:46   ` Stephane Eranian
2010-04-20 10:31     ` Robert Richter
2010-04-20 16:05     ` Robert Richter
2010-04-21  8:47       ` Robert Richter
2010-04-21  9:02         ` Stephane Eranian
2010-04-21  9:21           ` Robert Richter
2010-04-21 10:54             ` Robert Richter
2010-04-21 11:37               ` Stephane Eranian
2010-04-21 16:58                 ` Robert Richter
2010-04-22 17:32                   ` Stephane Eranian
2010-05-11 13:57                 ` Robert Richter
2010-04-13 20:23 ` [PATCH 12/12] perf, x86: implement the ibs interrupt handler Robert Richter
2010-04-19 12:19   ` Stephane Eranian
2010-04-20 13:10     ` Robert Richter
2010-04-22 14:45     ` Robert Richter
2010-05-07 15:28     ` [PATCH] perf: fix raw sample size if no sampling data is attached Robert Richter
2010-05-07 15:41       ` Peter Zijlstra
2010-05-07 19:48       ` Robert Richter
2010-05-18 15:12     ` Robert Richter [this message]
2010-05-19  7:39       ` [RFC PATCH] perf: align raw sample data on 64-bit boundaries Frederic Weisbecker
2010-05-19  9:31         ` Robert Richter
2010-05-24 21:25           ` Frederic Weisbecker
2010-05-28 17:35             ` Robert Richter
2010-04-13 20:45 ` [osrc-patches] [PATCH 00/12] perf: introduce model specific events and AMD IBS Robert Richter
2010-04-14 12:31   ` Robert Richter
2010-04-15  7:41   ` Peter Zijlstra
2010-04-15  7:44 ` Peter Zijlstra
2010-04-15 15:16   ` Robert Richter
2010-04-21 12:11     ` Peter Zijlstra
2010-04-21 13:21       ` Stephane Eranian
2010-04-21 18:26         ` Robert Richter
2010-04-21 18:40           ` Stephane Eranian
2010-04-21 16:28       ` Robert Richter
2010-04-28 16:16 ` [osrc-patches] " Robert Richter
2010-05-04 14:18   ` Peter Zijlstra

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=20100518151227.GJ21799@erda.amd.com \
    --to=robert.richter@amd.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@infradead.org \
    --cc=eranian@google.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --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 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).