From: Harvey Harrison <harvey.harrison@gmail.com>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: LKML <linux-kernel@vger.kernel.org>,
Masami Hiramatsu <mhiramat@redhat.com>,
Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
David Miller <davem@davemloft.net>,
hskinnemoen@atmel.com, schwidefsky@de.ibm.com,
heiko.carstens@de.ibm.com, tony.luck@intel.com,
Ingo Molnar <mingo@elte.hu>, Paul Mackerras <paulus@samba.org>
Subject: [PATCHv3] kprobes: Introduce kprobe_handle_fault()
Date: Tue, 08 Jan 2008 20:19:20 -0800 [thread overview]
Message-ID: <1199852360.6424.39.camel@brick> (raw)
In-Reply-To: <1199833324.6424.12.camel@brick>
Use a central kprobe_handle_fault() inline in kprobes.h to remove
all of the arch-dependant, practically identical implementations in
avr32, ia64, powerpc, s390, sparc64, and x86.
avr32 was the only arch without the preempt_disable/enable pair
in its notify_page_fault implementation.
This uncovered a possible bug in the s390 version as that purely
copied the x86 version unconditionally passing 14 as the trapnr
rather than the error_code parameter.
powerpc:
Tested-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
X86-64
Acked-by: Masami Hiramatsu <mhiramat@redhat.com>
Signed-off-by: Harvey Harrison <harvey.harrison@gmail.com>
---
arch/avr32/mm/fault.c | 21 +--------------------
arch/ia64/mm/fault.c | 24 +-----------------------
arch/powerpc/mm/fault.c | 25 +------------------------
arch/s390/mm/fault.c | 25 +------------------------
arch/sparc64/mm/fault.c | 23 +----------------------
arch/x86/mm/fault_64.c | 26 ++------------------------
include/linux/kprobes.h | 19 +++++++++++++++++++
7 files changed, 26 insertions(+), 137 deletions(-)
diff --git a/arch/avr32/mm/fault.c b/arch/avr32/mm/fault.c
index 6560cb1..e41953e 100644
--- a/arch/avr32/mm/fault.c
+++ b/arch/avr32/mm/fault.c
@@ -20,25 +20,6 @@
#include <asm/tlb.h>
#include <asm/uaccess.h>
-#ifdef CONFIG_KPROBES
-static inline int notify_page_fault(struct pt_regs *regs, int trap)
-{
- int ret = 0;
-
- if (!user_mode(regs)) {
- if (kprobe_running() && kprobe_fault_handler(regs, trap))
- ret = 1;
- }
-
- return ret;
-}
-#else
-static inline int notify_page_fault(struct pt_regs *regs, int trap)
-{
- return 0;
-}
-#endif
-
int exception_trace = 1;
/*
@@ -66,7 +47,7 @@ asmlinkage void do_page_fault(unsigned long ecr, struct pt_regs *regs)
int code;
int fault;
- if (notify_page_fault(regs, ecr))
+ if (kprobe_handle_fault(regs, ecr))
return;
address = sysreg_read(TLBEAR);
diff --git a/arch/ia64/mm/fault.c b/arch/ia64/mm/fault.c
index 7571076..bfc83e8 100644
--- a/arch/ia64/mm/fault.c
+++ b/arch/ia64/mm/fault.c
@@ -18,28 +18,6 @@
extern void die (char *, struct pt_regs *, long);
-#ifdef CONFIG_KPROBES
-static inline int notify_page_fault(struct pt_regs *regs, int trap)
-{
- int ret = 0;
-
- if (!user_mode(regs)) {
- /* kprobe_running() needs smp_processor_id() */
- preempt_disable();
- if (kprobe_running() && kprobes_fault_handler(regs, trap))
- ret = 1;
- preempt_enable();
- }
-
- return ret;
-}
-#else
-static inline int notify_page_fault(struct pt_regs *regs, int trap)
-{
- return 0;
-}
-#endif
-
/*
* Return TRUE if ADDRESS points at a page in the kernel's mapped segment
* (inside region 5, on ia64) and that page is present.
@@ -106,7 +84,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
/*
* This is to handle the kprobes on user space access instructions
*/
- if (notify_page_fault(regs, TRAP_BRKPT))
+ if (kprobe_handle_fault(regs, TRAP_BRKPT))
return;
down_read(&mm->mmap_sem);
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 8135da0..ff64bd3 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -39,29 +39,6 @@
#include <asm/tlbflush.h>
#include <asm/siginfo.h>
-
-#ifdef CONFIG_KPROBES
-static inline int notify_page_fault(struct pt_regs *regs)
-{
- int ret = 0;
-
- /* kprobe_running() needs smp_processor_id() */
- if (!user_mode(regs)) {
- preempt_disable();
- if (kprobe_running() && kprobe_fault_handler(regs, 11))
- ret = 1;
- preempt_enable();
- }
-
- return ret;
-}
-#else
-static inline int notify_page_fault(struct pt_regs *regs)
-{
- return 0;
-}
-#endif
-
/*
* Check whether the instruction at regs->nip is a store using
* an update addressing form which will update r1.
@@ -164,7 +141,7 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
is_write = error_code & ESR_DST;
#endif /* CONFIG_4xx || CONFIG_BOOKE */
- if (notify_page_fault(regs))
+ if (kprobe_handle_fault(regs, 11))
return 0;
if (trap == 0x300) {
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 2456b52..a9033cf 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -51,29 +51,6 @@ extern int sysctl_userprocess_debug;
extern void die(const char *,struct pt_regs *,long);
-#ifdef CONFIG_KPROBES
-static inline int notify_page_fault(struct pt_regs *regs, long err)
-{
- int ret = 0;
-
- /* kprobe_running() needs smp_processor_id() */
- if (!user_mode(regs)) {
- preempt_disable();
- if (kprobe_running() && kprobe_fault_handler(regs, 14))
- ret = 1;
- preempt_enable();
- }
-
- return ret;
-}
-#else
-static inline int notify_page_fault(struct pt_regs *regs, long err)
-{
- return 0;
-}
-#endif
-
-
/*
* Unlock any spinlocks which will prevent us from getting the
* message out.
@@ -309,7 +286,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int write)
int si_code;
int fault;
- if (notify_page_fault(regs, error_code))
+ if (kprobe_handle_fault(regs, 14))
return;
tsk = current;
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c
index e2027f2..8467dd6 100644
--- a/arch/sparc64/mm/fault.c
+++ b/arch/sparc64/mm/fault.c
@@ -31,27 +31,6 @@
#include <asm/sections.h>
#include <asm/mmu_context.h>
-#ifdef CONFIG_KPROBES
-static inline int notify_page_fault(struct pt_regs *regs)
-{
- int ret = 0;
-
- /* kprobe_running() needs smp_processor_id() */
- if (!user_mode(regs)) {
- preempt_disable();
- if (kprobe_running() && kprobe_fault_handler(regs, 0))
- ret = 1;
- preempt_enable();
- }
- return ret;
-}
-#else
-static inline int notify_page_fault(struct pt_regs *regs)
-{
- return 0;
-}
-#endif
-
/*
* To debug kernel to catch accesses to certain virtual/physical addresses.
* Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints.
@@ -280,7 +259,7 @@ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
fault_code = get_thread_fault_code();
- if (notify_page_fault(regs))
+ if (kprobe_handle_fault(regs, 0))
return;
si_code = SEGV_MAPERR;
diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c
index 0e26230..c29e462 100644
--- a/arch/x86/mm/fault_64.c
+++ b/arch/x86/mm/fault_64.c
@@ -41,28 +41,6 @@
#define PF_RSVD (1<<3)
#define PF_INSTR (1<<4)
-#ifdef CONFIG_KPROBES
-static inline int notify_page_fault(struct pt_regs *regs)
-{
- int ret = 0;
-
- /* kprobe_running() needs smp_processor_id() */
- if (!user_mode(regs)) {
- preempt_disable();
- if (kprobe_running() && kprobe_fault_handler(regs, 14))
- ret = 1;
- preempt_enable();
- }
-
- return ret;
-}
-#else
-static inline int notify_page_fault(struct pt_regs *regs)
-{
- return 0;
-}
-#endif
-
/* Sometimes the CPU reports invalid exceptions on prefetch.
Check that here and ignore.
Opcode checker based on code by Richard Brunner */
@@ -343,7 +321,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
if (vmalloc_fault(address) >= 0)
return;
}
- if (notify_page_fault(regs))
+ if (kprobe_handle_fault(regs, 14))
return;
/*
* Don't take the mm semaphore here. If we fixup a prefetch
@@ -352,7 +330,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
goto bad_area_nosemaphore;
}
- if (notify_page_fault(regs))
+ if (kprobe_handle_fault(regs, 14))
return;
if (likely(regs->eflags & X86_EFLAGS_IF))
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 8189158..a1ca019 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -36,6 +36,7 @@
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <linux/mutex.h>
+#include <linux/hardirq.h>
#ifdef CONFIG_KPROBES
#include <asm/kprobes.h>
@@ -203,6 +204,20 @@ static inline struct kprobe *kprobe_running(void)
return (__get_cpu_var(current_kprobe));
}
+/*
+ * If it is a kprobe pagefault we can not be premptible so return before
+ * calling kprobe_running() as it will assert on smp_processor_id if
+ * preemption is enabled.
+ */
+static inline int kprobe_handle_fault(struct pt_regs *regs, int trapnr)
+{
+ if (!user_mode(regs) && !preemptible() && kprobe_running() &&
+ kprobe_fault_handler(regs, trapnr))
+ return 1;
+ else
+ return 0;
+}
+
static inline void reset_current_kprobe(void)
{
__get_cpu_var(current_kprobe) = NULL;
@@ -237,6 +252,10 @@ static inline struct kprobe *kprobe_running(void)
{
return NULL;
}
+static inline int kprobe_handle_fault(struct pt_regs *regs, int trapnr)
+{
+ return 0;
+}
static inline int register_kprobe(struct kprobe *p)
{
return -ENOSYS;
--
1.5.4.rc2.1164.g6451
next prev parent reply other threads:[~2008-01-09 4:19 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-01-07 20:24 [PATCHv2] kprobes: Introduce is_kprobe_fault() Harvey Harrison
2008-01-08 5:37 ` Ananth N Mavinakayanahalli
2008-01-08 17:03 ` Masami Hiramatsu
2008-01-08 22:45 ` Paul Mackerras
2008-01-08 23:02 ` Harvey Harrison
2008-01-09 4:19 ` Harvey Harrison [this message]
2008-01-09 6:14 ` [PATCHv3] kprobes: Introduce kprobe_handle_fault() Heiko Carstens
2008-01-09 6:22 ` Harvey Harrison
2008-01-09 22:01 ` [PATCHv4] " Harvey Harrison
2008-01-09 23:16 ` Heiko Carstens
2008-01-10 0:25 ` Harvey Harrison
2008-01-10 0:44 ` [PATCH 1/2] " Harvey Harrison
2008-01-10 3:15 ` Masami Hiramatsu
2008-01-10 12:50 ` Ingo Molnar
2008-01-10 0:45 ` [PATCH 2/2] kprobe: remove preempt_enable/disable from kprobe_handle_fault() Harvey Harrison
2008-01-10 3:15 ` Masami Hiramatsu
2008-01-09 23:31 ` [PATCHv4] kprobes: Introduce kprobe_handle_fault() Masami Hiramatsu
2008-01-09 7:58 ` [PATCHv3] " Christoph Hellwig
2008-01-09 7:57 ` Christoph Hellwig
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=1199852360.6424.39.camel@brick \
--to=harvey.harrison@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=ananth@in.ibm.com \
--cc=davem@davemloft.net \
--cc=heiko.carstens@de.ibm.com \
--cc=hskinnemoen@atmel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mhiramat@redhat.com \
--cc=mingo@elte.hu \
--cc=paulus@samba.org \
--cc=schwidefsky@de.ibm.com \
--cc=tony.luck@intel.com \
/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.