perf: Correctly align perf event tracing buffer

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Linux Kernel Mailing List
Date: Sunday, April 4, 2010 - 12:59 pm

Gitweb:     http://git.kernel.org/linus/eb1e79611cc9bfe21978230e3521e77ea2d7874a
Commit:     eb1e79611cc9bfe21978230e3521e77ea2d7874a
Parent:     b72c40949b0f04728f2993a1434598d3bad094ea
Author:     Frederic Weisbecker <fweisbec@gmail.com>
AuthorDate: Tue Mar 23 00:08:59 2010 +0100
Committer:  Frederic Weisbecker <fweisbec@gmail.com>
CommitDate: Thu Apr 1 08:26:30 2010 +0200

    perf: Correctly align perf event tracing buffer
    
    The trace event buffer used by perf to record raw sample events
    is typed as an array of char and may then not be aligned to 8
    by alloc_percpu().
    
    But we need it to be aligned to 8 in sparc64 because we cast
    this buffer into a random structure type built by the TRACE_EVENT()
    macro to store the traces. So if a random 64 bits field is accessed
    inside, it may be not under an expected good alignment.
    
    Use an array of long instead to force the appropriate alignment, and
    perform a compile time check to ensure the size in byte of the buffer
    is a multiple of sizeof(long) so that its actual size doesn't get
    shrinked under us.
    
    This fixes unaligned accesses reported while using perf lock
    in sparc 64.
    
    Suggested-by: David Miller <davem@davemloft.net>
    Suggested-by: Tejun Heo <htejun@gmail.com>
    Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Paul Mackerras <paulus@samba.org>
    Cc: Ingo Molnar <mingo@elte.hu>
    Cc: David Miller <davem@davemloft.net>
    Cc: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace_event_perf.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index 81f691e..0565bb4 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -17,7 +17,12 @@ EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs);
 static char *perf_trace_buf;
 static char *perf_trace_buf_nmi;
 
-typedef typeof(char [PERF_MAX_TRACE_SIZE]) perf_trace_t ;
+/*
+ * Force it to be aligned to unsigned long to avoid misaligned accesses
+ * suprises
+ */
+typedef typeof(unsigned long [PERF_MAX_TRACE_SIZE / sizeof(unsigned long)])
+	perf_trace_t;
 
 /* Count the events in use (per event id, not per instance) */
 static int	total_ref_count;
@@ -130,6 +135,8 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
 	char *trace_buf, *raw_data;
 	int pc, cpu;
 
+	BUILD_BUG_ON(PERF_MAX_TRACE_SIZE % sizeof(unsigned long));
+
 	pc = preempt_count();
 
 	/* Protect the per cpu buffer, begin the rcu read side */
@@ -152,7 +159,7 @@ __kprobes void *perf_trace_buf_prepare(int size, unsigned short type,
 	raw_data = per_cpu_ptr(trace_buf, cpu);
 
 	/* zero the dead bytes from align to not leak stack to user */
-	*(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL;
+	memset(&raw_data[size - sizeof(u64)], 0, sizeof(u64));
 
 	entry = (struct trace_entry *)raw_data;
 	tracing_generic_entry_update(entry, *irq_flags, pc);
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
perf: Correctly align perf event tracing buffer, Linux Kernel Mailing ..., (Sun Apr 4, 12:59 pm)