diff options
author | Pekka Paalanen <pq@iki.fi> | 2008-05-12 15:20:57 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2008-05-24 05:21:55 -0400 |
commit | 10c43d2eb50c9a5ad60388b9d3c41c31150049e6 (patch) | |
tree | d5a15fe0661a880366b89d0f15cb79740a7302bb /arch/x86/mm/fault.c | |
parent | 63ffa3e456c1a9884a3ebac997d91e3fdae18d78 (diff) |
x86: explicit call to mmiotrace in do_page_fault()
The custom page fault handler list is replaced with a single function
pointer. All related functions and variables are renamed for
mmiotrace.
Signed-off-by: Pekka Paalanen <pq@iki.fi>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Arjan van de Ven <arjan@infradead.org>
Cc: pq@iki.fi
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/mm/fault.c')
-rw-r--r-- | arch/x86/mm/fault.c | 66 |
1 files changed, 34 insertions, 32 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 343f5c1aacc8..e9a086a1a9ff 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -49,53 +49,55 @@ | |||
49 | #define PF_RSVD (1<<3) | 49 | #define PF_RSVD (1<<3) |
50 | #define PF_INSTR (1<<4) | 50 | #define PF_INSTR (1<<4) |
51 | 51 | ||
52 | #ifdef CONFIG_PAGE_FAULT_HANDLERS | 52 | #ifdef CONFIG_MMIOTRACE_HOOKS |
53 | static HLIST_HEAD(pf_handlers); /* protected by RCU */ | 53 | static pf_handler_func mmiotrace_pf_handler; /* protected by RCU */ |
54 | static DEFINE_SPINLOCK(pf_handlers_writer); | 54 | static DEFINE_SPINLOCK(mmiotrace_handler_lock); |
55 | 55 | ||
56 | void register_page_fault_handler(struct pf_handler *new_pfh) | 56 | int mmiotrace_register_pf(pf_handler_func new_pfh) |
57 | { | 57 | { |
58 | int ret = 0; | ||
58 | unsigned long flags; | 59 | unsigned long flags; |
59 | spin_lock_irqsave(&pf_handlers_writer, flags); | 60 | spin_lock_irqsave(&mmiotrace_handler_lock, flags); |
60 | hlist_add_head_rcu(&new_pfh->hlist, &pf_handlers); | 61 | if (mmiotrace_pf_handler) |
61 | spin_unlock_irqrestore(&pf_handlers_writer, flags); | 62 | ret = -EBUSY; |
63 | else | ||
64 | mmiotrace_pf_handler = new_pfh; | ||
65 | spin_unlock_irqrestore(&mmiotrace_handler_lock, flags); | ||
66 | return ret; | ||
62 | } | 67 | } |
63 | EXPORT_SYMBOL_GPL(register_page_fault_handler); | 68 | EXPORT_SYMBOL_GPL(mmiotrace_register_pf); |
64 | 69 | ||
65 | /** | 70 | /** |
66 | * unregister_page_fault_handler: | 71 | * mmiotrace_unregister_pf: |
67 | * The caller must ensure @old_pfh is not in use anymore before freeing it. | 72 | * 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 | 73 | * This function does not guarantee it. The handler function pointer is |
69 | * RCU, so you can do this by e.g. calling synchronize_rcu(). | 74 | * protected by RCU, so you can do this by e.g. calling synchronize_rcu(). |
70 | */ | 75 | */ |
71 | void unregister_page_fault_handler(struct pf_handler *old_pfh) | 76 | int mmiotrace_unregister_pf(pf_handler_func old_pfh) |
72 | { | 77 | { |
78 | int ret = 0; | ||
73 | unsigned long flags; | 79 | unsigned long flags; |
74 | spin_lock_irqsave(&pf_handlers_writer, flags); | 80 | spin_lock_irqsave(&mmiotrace_handler_lock, flags); |
75 | hlist_del_rcu(&old_pfh->hlist); | 81 | if (mmiotrace_pf_handler != old_pfh) |
76 | spin_unlock_irqrestore(&pf_handlers_writer, flags); | 82 | ret = -EPERM; |
83 | else | ||
84 | mmiotrace_pf_handler = NULL; | ||
85 | spin_unlock_irqrestore(&mmiotrace_handler_lock, flags); | ||
86 | return ret; | ||
77 | } | 87 | } |
78 | EXPORT_SYMBOL_GPL(unregister_page_fault_handler); | 88 | EXPORT_SYMBOL_GPL(mmiotrace_unregister_pf); |
79 | #endif | 89 | #endif /* CONFIG_MMIOTRACE_HOOKS */ |
80 | 90 | ||
81 | /* returns non-zero if do_page_fault() should return */ | 91 | /* returns non-zero if do_page_fault() should return */ |
82 | static int handle_custom_pf(struct pt_regs *regs, unsigned long error_code, | 92 | static inline int call_mmiotrace(struct pt_regs *regs, |
83 | unsigned long address) | 93 | unsigned long error_code, |
94 | unsigned long address) | ||
84 | { | 95 | { |
85 | #ifdef CONFIG_PAGE_FAULT_HANDLERS | 96 | #ifdef CONFIG_MMIOTRACE_HOOKS |
86 | int ret = 0; | 97 | 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(); | 98 | rcu_read_lock(); |
94 | hlist_for_each_entry_rcu(cur, ncur, &pf_handlers, hlist) { | 99 | if (mmiotrace_pf_handler) |
95 | ret = cur->handler(regs, error_code, address); | 100 | ret = mmiotrace_pf_handler(regs, error_code, address); |
96 | if (ret) | ||
97 | break; | ||
98 | } | ||
99 | rcu_read_unlock(); | 101 | rcu_read_unlock(); |
100 | return ret; | 102 | return ret; |
101 | #else | 103 | #else |
@@ -655,7 +657,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
655 | 657 | ||
656 | if (notify_page_fault(regs)) | 658 | if (notify_page_fault(regs)) |
657 | return; | 659 | return; |
658 | if (handle_custom_pf(regs, error_code, address)) | 660 | if (call_mmiotrace(regs, error_code, address)) |
659 | return; | 661 | return; |
660 | 662 | ||
661 | /* | 663 | /* |