diff options
author | Paul Mundt <lethal@linux-sh.org> | 2009-06-24 13:30:10 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-06-24 13:30:10 -0400 |
commit | 7433ab770327b471399f7b5baacad78e160b5393 (patch) | |
tree | aad14b4baa2f3e39e4116a72244f03c886cdc49e /arch | |
parent | d94d4adb7dd05b4e25f3c317a1b932ec74272a12 (diff) |
sh: Hook up page fault events for software perf counters.
This adds page fault instrumentation for the software performance
counters. Follows the x86 and powerpc changes.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/mm/fault_32.c | 61 |
1 files changed, 32 insertions, 29 deletions
diff --git a/arch/sh/mm/fault_32.c b/arch/sh/mm/fault_32.c index cc8ddbdf3d7a..71925946f1e1 100644 --- a/arch/sh/mm/fault_32.c +++ b/arch/sh/mm/fault_32.c | |||
@@ -15,12 +15,28 @@ | |||
15 | #include <linux/mm.h> | 15 | #include <linux/mm.h> |
16 | #include <linux/hardirq.h> | 16 | #include <linux/hardirq.h> |
17 | #include <linux/kprobes.h> | 17 | #include <linux/kprobes.h> |
18 | #include <linux/marker.h> | 18 | #include <linux/perf_counter.h> |
19 | #include <asm/io_trapped.h> | 19 | #include <asm/io_trapped.h> |
20 | #include <asm/system.h> | 20 | #include <asm/system.h> |
21 | #include <asm/mmu_context.h> | 21 | #include <asm/mmu_context.h> |
22 | #include <asm/tlbflush.h> | 22 | #include <asm/tlbflush.h> |
23 | 23 | ||
24 | static inline int notify_page_fault(struct pt_regs *regs, int trap) | ||
25 | { | ||
26 | int ret = 0; | ||
27 | |||
28 | #ifdef CONFIG_KPROBES | ||
29 | if (!user_mode(regs)) { | ||
30 | preempt_disable(); | ||
31 | if (kprobe_running() && kprobe_fault_handler(regs, trap)) | ||
32 | ret = 1; | ||
33 | preempt_enable(); | ||
34 | } | ||
35 | #endif | ||
36 | |||
37 | return ret; | ||
38 | } | ||
39 | |||
24 | /* | 40 | /* |
25 | * This routine handles page faults. It determines the address, | 41 | * This routine handles page faults. It determines the address, |
26 | * and the problem, and then passes it off to one of the appropriate | 42 | * and the problem, and then passes it off to one of the appropriate |
@@ -87,13 +103,16 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
87 | return; | 103 | return; |
88 | } | 104 | } |
89 | 105 | ||
106 | mm = tsk->mm; | ||
107 | |||
108 | if (unlikely(notify_page_fault(regs, lookup_exception_vector()))) | ||
109 | return; | ||
110 | |||
90 | /* Only enable interrupts if they were on before the fault */ | 111 | /* Only enable interrupts if they were on before the fault */ |
91 | if ((regs->sr & SR_IMASK) != SR_IMASK) { | 112 | if ((regs->sr & SR_IMASK) != SR_IMASK) |
92 | trace_hardirqs_on(); | ||
93 | local_irq_enable(); | 113 | local_irq_enable(); |
94 | } | ||
95 | 114 | ||
96 | mm = tsk->mm; | 115 | perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS, 1, 0, regs, address); |
97 | 116 | ||
98 | /* | 117 | /* |
99 | * If we're in an interrupt or have no user | 118 | * If we're in an interrupt or have no user |
@@ -141,10 +160,15 @@ survive: | |||
141 | goto do_sigbus; | 160 | goto do_sigbus; |
142 | BUG(); | 161 | BUG(); |
143 | } | 162 | } |
144 | if (fault & VM_FAULT_MAJOR) | 163 | if (fault & VM_FAULT_MAJOR) { |
145 | tsk->maj_flt++; | 164 | tsk->maj_flt++; |
146 | else | 165 | perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0, |
166 | regs, address); | ||
167 | } else { | ||
147 | tsk->min_flt++; | 168 | tsk->min_flt++; |
169 | perf_swcounter_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0, | ||
170 | regs, address); | ||
171 | } | ||
148 | 172 | ||
149 | up_read(&mm->mmap_sem); | 173 | up_read(&mm->mmap_sem); |
150 | return; | 174 | return; |
@@ -245,22 +269,6 @@ do_sigbus: | |||
245 | goto no_context; | 269 | goto no_context; |
246 | } | 270 | } |
247 | 271 | ||
248 | static inline int notify_page_fault(struct pt_regs *regs, int trap) | ||
249 | { | ||
250 | int ret = 0; | ||
251 | |||
252 | #ifdef CONFIG_KPROBES | ||
253 | if (!user_mode(regs)) { | ||
254 | preempt_disable(); | ||
255 | if (kprobe_running() && kprobe_fault_handler(regs, trap)) | ||
256 | ret = 1; | ||
257 | preempt_enable(); | ||
258 | } | ||
259 | #endif | ||
260 | |||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | /* | 272 | /* |
265 | * Called with interrupts disabled. | 273 | * Called with interrupts disabled. |
266 | */ | 274 | */ |
@@ -273,12 +281,7 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, | |||
273 | pmd_t *pmd; | 281 | pmd_t *pmd; |
274 | pte_t *pte; | 282 | pte_t *pte; |
275 | pte_t entry; | 283 | pte_t entry; |
276 | int ret = 0; | 284 | int ret = 1; |
277 | |||
278 | if (notify_page_fault(regs, lookup_exception_vector())) | ||
279 | goto out; | ||
280 | |||
281 | ret = 1; | ||
282 | 285 | ||
283 | /* | 286 | /* |
284 | * We don't take page faults for P1, P2, and parts of P4, these | 287 | * We don't take page faults for P1, P2, and parts of P4, these |