aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm/fault.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-10 05:43:06 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-10 05:43:06 -0400
commit5373fdbdc1dba69aa956098650f71b731d471885 (patch)
tree8d9f07539896a696352818820c9c5f6612370882 /arch/x86/mm/fault.c
parentbac0c9103b31c3dd83ad9d731dd9834e2ba75e4f (diff)
parent4d51c7587bb13dbb2fafcad6c0b5231bd864b55f (diff)
Merge branch 'tracing/mmiotrace' into auto-ftrace-next
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r--arch/x86/mm/fault.c57
1 files changed, 7 insertions, 50 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 42394b353c..0a778e3c43 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -10,6 +10,7 @@
10#include <linux/string.h> 10#include <linux/string.h>
11#include <linux/types.h> 11#include <linux/types.h>
12#include <linux/ptrace.h> 12#include <linux/ptrace.h>
13#include <linux/mmiotrace.h>
13#include <linux/mman.h> 14#include <linux/mman.h>
14#include <linux/mm.h> 15#include <linux/mm.h>
15#include <linux/smp.h> 16#include <linux/smp.h>
@@ -49,58 +50,14 @@
49#define PF_RSVD (1<<3) 50#define PF_RSVD (1<<3)
50#define PF_INSTR (1<<4) 51#define PF_INSTR (1<<4)
51 52
52#ifdef CONFIG_PAGE_FAULT_HANDLERS 53static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
53static HLIST_HEAD(pf_handlers); /* protected by RCU */
54static DEFINE_SPINLOCK(pf_handlers_writer);
55
56void register_page_fault_handler(struct pf_handler *new_pfh)
57{
58 unsigned long flags;
59 spin_lock_irqsave(&pf_handlers_writer, flags);
60 hlist_add_head_rcu(&new_pfh->hlist, &pf_handlers);
61 spin_unlock_irqrestore(&pf_handlers_writer, flags);
62}
63EXPORT_SYMBOL_GPL(register_page_fault_handler);
64
65/**
66 * unregister_page_fault_handler:
67 * The caller must ensure @old_pfh is not in use anymore before freeing it.
68 * This function does not guarantee it. The list of handlers is protected by
69 * RCU, so you can do this by e.g. calling synchronize_rcu().
70 */
71void unregister_page_fault_handler(struct pf_handler *old_pfh)
72{ 54{
73 unsigned long flags; 55#ifdef CONFIG_MMIOTRACE_HOOKS
74 spin_lock_irqsave(&pf_handlers_writer, flags); 56 if (unlikely(is_kmmio_active()))
75 hlist_del_rcu(&old_pfh->hlist); 57 if (kmmio_handler(regs, addr) == 1)
76 spin_unlock_irqrestore(&pf_handlers_writer, flags); 58 return -1;
77}
78EXPORT_SYMBOL_GPL(unregister_page_fault_handler);
79#endif 59#endif
80
81/* returns non-zero if do_page_fault() should return */
82static int handle_custom_pf(struct pt_regs *regs, unsigned long error_code,
83 unsigned long address)
84{
85#ifdef CONFIG_PAGE_FAULT_HANDLERS
86 int ret = 0;
87 struct pf_handler *cur;
88 struct hlist_node *ncur;
89
90 if (hlist_empty(&pf_handlers))
91 return 0;
92
93 rcu_read_lock();
94 hlist_for_each_entry_rcu(cur, ncur, &pf_handlers, hlist) {
95 ret = cur->handler(regs, error_code, address);
96 if (ret)
97 break;
98 }
99 rcu_read_unlock();
100 return ret;
101#else
102 return 0; 60 return 0;
103#endif
104} 61}
105 62
106static inline int notify_page_fault(struct pt_regs *regs) 63static inline int notify_page_fault(struct pt_regs *regs)
@@ -660,7 +617,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
660 617
661 if (notify_page_fault(regs)) 618 if (notify_page_fault(regs))
662 return; 619 return;
663 if (handle_custom_pf(regs, error_code, address)) 620 if (unlikely(kmmio_fault(regs, address)))
664 return; 621 return;
665 622
666 /* 623 /*