[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <1287774792-23123-2-git-send-regression-fweisbec@gmail.com>
Date: Fri, 22 Oct 2010 21:13:02 +0200
From: Frederic Weisbecker <fweisbec@...il.com>
To: LKML <linux-kernel@...r.kernel.org>
Cc: LKML <linux-kernel@...r.kernel.org>,
Frederic Weisbecker <fweisbec@...il.com>,
Ingo Molnar <mingo@...e.hu>,
Peter Zijlstra <a.p.zijlstra@...llo.nl>,
Arnaldo Carvalho de Melo <acme@...hat.com>,
Paul Mackerras <paulus@...ba.org>,
Stephane Eranian <eranian@...gle.com>,
Cyrill Gorcunov <gorcunov@...nvz.org>,
Tom Zanussi <tzanussi@...il.com>,
Masami Hiramatsu <mhiramat@...hat.com>,
Steven Rostedt <rostedt@...dmis.org>,
Robert Richter <robert.richter@....com>,
"Frank Ch. Eigler" <fche@...hat.com>
Subject: [RFC PATCH 01/11] uaccess: New copy_from_user_gup() API
This brings a get_user_page_fast() based copy_from_user() that can
do a best effort copy from any context.
In order to support user stack dump safely in perf samples from
generic code, rename x86 copy_from_user_nmi to copy_from_user_gup
and make it generally available. If the arch doesn't provide an
implementation it will map to copy_from_user_inatomic.
Since perf is the first user for now, let the overriden x86
implementation in the perf source file.
Signed-off-by: Frederic Weisbecker <fweisbec@...il.com>
Cc: Ingo Molnar <mingo@...e.hu>
Cc: Peter Zijlstra <a.p.zijlstra@...llo.nl>
Cc: Arnaldo Carvalho de Melo <acme@...hat.com>
Cc: Paul Mackerras <paulus@...ba.org>
Cc: Stephane Eranian <eranian@...gle.com>
Cc: Cyrill Gorcunov <gorcunov@...nvz.org>
Cc: Tom Zanussi <tzanussi@...il.com>
Cc: Masami Hiramatsu <mhiramat@...hat.com>
Cc: Steven Rostedt <rostedt@...dmis.org>
Cc: Robert Richter <robert.richter@....com>
Cc: Frank Ch. Eigler <fche@...hat.com>
---
arch/x86/include/asm/uaccess.h | 5 +++++
arch/x86/kernel/cpu/perf_event.c | 8 ++++----
arch/x86/kernel/cpu/perf_event_intel_ds.c | 2 +-
include/asm-generic/uaccess.h | 4 ++++
4 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index abd3e0e..d29f3ab 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -229,6 +229,11 @@ extern void __put_user_2(void);
extern void __put_user_4(void);
extern void __put_user_8(void);
+extern unsigned long
+__copy_from_user_gup(void *to, const void __user *from, unsigned long n);
+
+#define copy_from_user_gup(to, from, n) __copy_from_user_gup(to, from, n)
+
#ifdef CONFIG_X86_WP_WORKS_OK
/**
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index fe73c18..8747570 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -45,8 +45,8 @@ do { \
/*
* best effort, GUP based copy_from_user() that assumes IRQ or NMI context
*/
-static unsigned long
-copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
+unsigned long
+__copy_from_user_gup(void *to, const void __user *from, unsigned long n)
{
unsigned long offset, addr = (unsigned long)from;
int type = in_nmi() ? KM_NMI : KM_IRQ0;
@@ -1688,7 +1688,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry)
frame.next_frame = 0;
frame.return_address = 0;
- bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
+ bytes = copy_from_user_gup(&frame, fp, sizeof(frame));
if (bytes != sizeof(frame))
break;
@@ -1731,7 +1731,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
frame.next_frame = NULL;
frame.return_address = 0;
- bytes = copy_from_user_nmi(&frame, fp, sizeof(frame));
+ bytes = copy_from_user_gup(&frame, fp, sizeof(frame));
if (bytes != sizeof(frame))
break;
diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c
index 4977f9c..1642dee 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_ds.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c
@@ -426,7 +426,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
if (!kernel_ip(ip)) {
int bytes, size = MAX_INSN_SIZE;
- bytes = copy_from_user_nmi(buf, (void __user *)to, size);
+ bytes = copy_from_user_gup(buf, (void __user *)to, size);
if (bytes != size)
return 0;
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
index b218b85..00bc7d3 100644
--- a/include/asm-generic/uaccess.h
+++ b/include/asm-generic/uaccess.h
@@ -240,6 +240,10 @@ extern int __get_user_bad(void) __attribute__((noreturn));
#define __copy_to_user_inatomic __copy_to_user
#endif
+#ifndef copy_from_user_gup
+#define copy_from_user_gup __copy_from_user_inatomic
+#endif
+
static inline long copy_from_user(void *to,
const void __user * from, unsigned long n)
{
--
1.6.2.3
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists