LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Pekka Paalanen <pq@iki.fi>
To: Ingo Molnar <mingo@elte.hu>
Cc: Harvey Harrison <harvey.harrison@gmail.com>,
	linux-kernel@vger.kernel.org, Jan Beulich <jbeulich@novell.com>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Pavel Roskin <proski@gnu.org>,
	pq@iki.fi, Arjan van de Ven <arjan@infradead.org>
Subject: [PATCH v2] x86: Add a list for custom page fault handlers.
Date: Thu, 31 Jan 2008 18:02:53 +0200	[thread overview]
Message-ID: <20080131180253.6c007852@daedalus.pq.iki.fi> (raw)
In-Reply-To: <20080131150746.GB11996@elte.hu>

> could you please send us a patch for the whole mmiotrace kernel-side 
> feature, so that we can have a look at the general structure of this? 
> (and the interaction with change_page_attr(), etc.) Even if it's not 
> functional (and wont even build/boot) at the moment. Thanks,

Very well, first the revised custom page fault handler patch.
Changes since the previous submit:
- use spin_lock_irqsave instead of spin_lock
- Harvey Harrison's clean-up with the #ifdefs
- handler call site moved earlier
- remove sync RCU call

I'm not aware of any functional problems with this one.

Arjan, you said you don't like this. May I ask why?
This is most convinient for mmiotrace as it is meant to be a module.
I'm also using this as an excuse to let other people to get into the
page fault handler with their out-of-tree-today modules.


>From adeb0f4f95f176d97c1157031b5dd01f49d4cb66 Mon Sep 17 00:00:00 2001
From: Pekka Paalanen <pq@iki.fi>
Date: Wed, 30 Jan 2008 21:49:52 +0200
Subject: [PATCH] x86: Add a list for custom page fault handlers.

Provides kernel modules a way to register custom page fault handlers.
On every page fault this will call a list of registered functions. The
functions may handle the fault and force do_page_fault() to return
immediately.

This functionality is similar to the now removed page fault notifiers.
Custom page fault handlers are used by debugging and reverse engineering
tools. Mmiotrace is one such tool and a patch to add it into the tree
will follow.

The custom page fault handlers are called earlier in do_page_fault()
than the page fault notifiers were.

Signed-off-by: Pekka Paalanen <pq@iki.fi>
---
 arch/x86/Kconfig.debug   |    8 ++++++
 arch/x86/mm/fault.c      |   56 ++++++++++++++++++++++++++++++++++++++++++++++
 include/asm-x86/kdebug.h |    9 +++++++
 3 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 2e1e3af..1185dcc 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -138,6 +138,14 @@ config IOMMU_LEAK
 	  Add a simple leak tracer to the IOMMU code. This is useful when you
 	  are debugging a buggy device driver that leaks IOMMU mappings.
 
+config PAGE_FAULT_HANDLERS
+	bool "Custom page fault handlers"
+	depends on DEBUG_KERNEL
+	help
+	  Allow the use of custom page fault handlers. A kernel module may
+	  register a function that is called on every page fault. Custom
+	  handlers are used by some debugging and reverse engineering tools.
+
 #
 # IO delay types:
 #
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index e28cc52..11feebd 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -49,6 +49,60 @@
 #define PF_RSVD		(1<<3)
 #define PF_INSTR	(1<<4)
 
+#ifdef CONFIG_PAGE_FAULT_HANDLERS
+static HLIST_HEAD(pf_handlers); /* protected by RCU */
+static DEFINE_SPINLOCK(pf_handlers_writer);
+
+void register_page_fault_handler(struct pf_handler *new_pfh)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&pf_handlers_writer, flags);
+	hlist_add_head_rcu(&new_pfh->hlist, &pf_handlers);
+	spin_unlock_irqrestore(&pf_handlers_writer, flags);
+}
+EXPORT_SYMBOL_GPL(register_page_fault_handler);
+
+/**
+ * unregister_page_fault_handler:
+ * The caller must ensure @old_pfh is not in use anymore before freeing it.
+ * This function does not guarantee it. The list of handlers is protected by
+ * RCU, so you can do this by e.g. calling synchronize_rcu().
+ */
+void unregister_page_fault_handler(struct pf_handler *old_pfh)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&pf_handlers_writer, flags);
+	hlist_del_rcu(&old_pfh->hlist);
+	spin_unlock_irqrestore(&pf_handlers_writer, flags);
+}
+EXPORT_SYMBOL_GPL(unregister_page_fault_handler);
+#endif
+
+/* returns non-zero if do_page_fault() should return */
+static int handle_custom_pf(struct pt_regs *regs, unsigned long error_code,
+							unsigned long address)
+{
+#ifdef CONFIG_PAGE_FAULT_HANDLERS
+	int ret = 0;
+	struct pf_handler *cur;
+	struct hlist_node *ncur;
+
+	if (hlist_empty(&pf_handlers))
+		return 0;
+
+	rcu_read_lock();
+	hlist_for_each_entry_rcu(cur, ncur, &pf_handlers, hlist) {
+		ret = cur->handler(regs, error_code, address);
+		if (ret)
+			break;
+	}
+	rcu_read_unlock();
+	return ret;
+#else
+	return 0;
+#endif
+}
+
 static inline int notify_page_fault(struct pt_regs *regs)
 {
 #ifdef CONFIG_KPROBES
@@ -587,6 +641,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
 
 	if (notify_page_fault(regs))
 		return;
+	if (handle_custom_pf(regs, error_code, address))
+		return;
 
 	/*
 	 * We fault-in kernel-space virtual memory on-demand. The
diff --git a/include/asm-x86/kdebug.h b/include/asm-x86/kdebug.h
index dd442a1..7ae2118 100644
--- a/include/asm-x86/kdebug.h
+++ b/include/asm-x86/kdebug.h
@@ -35,4 +35,13 @@ extern void dump_pagetable(unsigned long);
 extern unsigned long oops_begin(void);
 extern void oops_end(unsigned long, struct pt_regs *, int signr);
 
+struct pf_handler {
+	struct hlist_node hlist;
+	int (*handler)(struct pt_regs *regs, unsigned long error_code,
+						unsigned long address);
+};
+
+extern void register_page_fault_handler(struct pf_handler *new_pfh);
+extern void unregister_page_fault_handler(struct pf_handler *old_pfh);
+
 #endif
-- 
1.5.3.7


  reply	other threads:[~2008-01-31 16:03 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-01-27 16:52 [PATCH] " Pekka Paalanen
2008-01-27 17:55 ` [RFC PATCH] x86: mmiotrace - trace memory mapped IO Pekka Paalanen
2008-01-30 22:39   ` Pekka Paalanen
2008-01-27 19:29 ` [PATCH] x86: Add a list for custom page fault handlers Ingo Molnar
2008-01-27 21:03 ` Peter Zijlstra
2008-01-30  2:28 ` Harvey Harrison
2008-01-30  2:34   ` Harvey Harrison
2008-01-30 18:08     ` Pekka Paalanen
2008-01-31 15:07       ` Ingo Molnar
2008-01-31 16:02         ` Pekka Paalanen [this message]
2008-01-31 16:15           ` [PATCH v2] " Arjan van de Ven
2008-02-03  6:55             ` Pekka Paalanen
2008-02-03  7:03               ` Ingo Molnar
2008-02-03 21:40                 ` Pekka Paalanen
2008-02-05 20:28                 ` [PATCH 1/4] x86 mmiotrace: use lookup_address() Pekka Paalanen
2008-02-05 20:30                   ` [PATCH 2/4] x86 mmiotrace: fix relay-buffer-full flag for SMP Pekka Paalanen
2008-02-05 20:44                     ` Eric Dumazet
2008-02-05 21:14                       ` Pekka Paalanen
2008-02-05 21:35                         ` Eric Dumazet
2008-02-09 17:53                           ` [PATCH] x86 mmiotrace: Use percpu instead of arrays Pekka Paalanen
2008-02-05 20:31                   ` [PATCH 3/4] x86 mmiotrace: comment about user space ABI Pekka Paalanen
2008-02-05 20:39                   ` [PATCH 4/4] x86 mmiotrace: move files into arch/x86/mm/ Pekka Paalanen
2008-02-06  3:02                     ` Randy Dunlap
2008-02-09 11:21                       ` Pekka Paalanen
2008-02-07 12:53                     ` Ingo Molnar
2008-02-07 12:56                       ` Christoph Hellwig
2008-02-09 17:52                         ` [RFC PATCH] x86: explicit call to mmiotrace in do_page_fault() Pekka Paalanen
2008-02-09 18:01                           ` Arjan van de Ven
2008-02-09 18:23                             ` Pekka Paalanen
2008-02-09 18:56                               ` Pekka Enberg
2008-02-09 19:11                                 ` Pekka Paalanen
2008-02-09 19:19                                   ` Pekka Enberg
2008-02-09 18:39                             ` Peter Zijlstra
2008-02-09 18:39                           ` Peter Zijlstra
2008-02-10 18:05                             ` [RFC PATCH v2] " Pekka Paalanen
2008-02-11  2:12                               ` Pavel Roskin
2008-02-11 18:04                                 ` Pekka Paalanen
2008-02-06  5:00                   ` [PATCH 1/4] x86 mmiotrace: use lookup_address() Christoph Hellwig
2008-02-07 12:52                     ` Ingo Molnar
2008-01-31 16:16           ` [RFC PATCH v2] x86: mmiotrace - trace memory mapped IO Pekka Paalanen
2008-01-31 16:29             ` Arjan van de Ven
2008-02-03  7:21               ` Pekka Paalanen
2008-01-30 18:20 ` [PATCH] x86: Add a list for custom page fault handlers Arjan van de Ven

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=20080131180253.6c007852@daedalus.pq.iki.fi \
    --to=pq@iki.fi \
    --cc=a.p.zijlstra@chello.nl \
    --cc=arjan@infradead.org \
    --cc=harvey.harrison@gmail.com \
    --cc=jbeulich@novell.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=proski@gnu.org \
    --subject='Re: [PATCH v2] x86: Add a list for custom page fault handlers.' \
    /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

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).