aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64
diff options
context:
space:
mode:
authorPrasanna S Panchamukhi <prasanna@in.ibm.com>2005-09-06 18:19:29 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:58:00 -0400
commitbb144a85c70a65730424ad1a9dc50fef66e5cafe (patch)
treeeecffdc773b84cd1da172117354c3ade600608d1 /arch/ppc64
parent0f2fbdcbb041f9087da42f8ac2e81f2817098d2a (diff)
[PATCH] Kprobes: prevent possible race conditions ppc64 changes
This patch contains the ppc64 architecture specific changes to prevent the possible race conditions. Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ppc64')
-rw-r--r--arch/ppc64/kernel/kprobes.c29
-rw-r--r--arch/ppc64/kernel/misc.S4
-rw-r--r--arch/ppc64/kernel/traps.c5
-rw-r--r--arch/ppc64/kernel/vmlinux.lds.S1
-rw-r--r--arch/ppc64/mm/fault.c5
5 files changed, 24 insertions, 20 deletions
diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
index a3d519518fb8..591e4b67b5a5 100644
--- a/arch/ppc64/kernel/kprobes.c
+++ b/arch/ppc64/kernel/kprobes.c
@@ -44,7 +44,7 @@ static struct kprobe *kprobe_prev;
44static unsigned long kprobe_status_prev, kprobe_saved_msr_prev; 44static unsigned long kprobe_status_prev, kprobe_saved_msr_prev;
45static struct pt_regs jprobe_saved_regs; 45static struct pt_regs jprobe_saved_regs;
46 46
47int arch_prepare_kprobe(struct kprobe *p) 47int __kprobes arch_prepare_kprobe(struct kprobe *p)
48{ 48{
49 int ret = 0; 49 int ret = 0;
50 kprobe_opcode_t insn = *p->addr; 50 kprobe_opcode_t insn = *p->addr;
@@ -68,27 +68,27 @@ int arch_prepare_kprobe(struct kprobe *p)
68 return ret; 68 return ret;
69} 69}
70 70
71void arch_copy_kprobe(struct kprobe *p) 71void __kprobes arch_copy_kprobe(struct kprobe *p)
72{ 72{
73 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); 73 memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
74 p->opcode = *p->addr; 74 p->opcode = *p->addr;
75} 75}
76 76
77void arch_arm_kprobe(struct kprobe *p) 77void __kprobes arch_arm_kprobe(struct kprobe *p)
78{ 78{
79 *p->addr = BREAKPOINT_INSTRUCTION; 79 *p->addr = BREAKPOINT_INSTRUCTION;
80 flush_icache_range((unsigned long) p->addr, 80 flush_icache_range((unsigned long) p->addr,
81 (unsigned long) p->addr + sizeof(kprobe_opcode_t)); 81 (unsigned long) p->addr + sizeof(kprobe_opcode_t));
82} 82}
83 83
84void arch_disarm_kprobe(struct kprobe *p) 84void __kprobes arch_disarm_kprobe(struct kprobe *p)
85{ 85{
86 *p->addr = p->opcode; 86 *p->addr = p->opcode;
87 flush_icache_range((unsigned long) p->addr, 87 flush_icache_range((unsigned long) p->addr,
88 (unsigned long) p->addr + sizeof(kprobe_opcode_t)); 88 (unsigned long) p->addr + sizeof(kprobe_opcode_t));
89} 89}
90 90
91void arch_remove_kprobe(struct kprobe *p) 91void __kprobes arch_remove_kprobe(struct kprobe *p)
92{ 92{
93 up(&kprobe_mutex); 93 up(&kprobe_mutex);
94 free_insn_slot(p->ainsn.insn); 94 free_insn_slot(p->ainsn.insn);
@@ -122,7 +122,8 @@ static inline void restore_previous_kprobe(void)
122 kprobe_saved_msr = kprobe_saved_msr_prev; 122 kprobe_saved_msr = kprobe_saved_msr_prev;
123} 123}
124 124
125void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs) 125void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
126 struct pt_regs *regs)
126{ 127{
127 struct kretprobe_instance *ri; 128 struct kretprobe_instance *ri;
128 129
@@ -244,7 +245,7 @@ void kretprobe_trampoline_holder(void)
244/* 245/*
245 * Called when the probe at kretprobe trampoline is hit 246 * Called when the probe at kretprobe trampoline is hit
246 */ 247 */
247int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) 248int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
248{ 249{
249 struct kretprobe_instance *ri = NULL; 250 struct kretprobe_instance *ri = NULL;
250 struct hlist_head *head; 251 struct hlist_head *head;
@@ -308,7 +309,7 @@ int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
308 * single-stepped a copy of the instruction. The address of this 309 * single-stepped a copy of the instruction. The address of this
309 * copy is p->ainsn.insn. 310 * copy is p->ainsn.insn.
310 */ 311 */
311static void resume_execution(struct kprobe *p, struct pt_regs *regs) 312static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
312{ 313{
313 int ret; 314 int ret;
314 unsigned int insn = *p->ainsn.insn; 315 unsigned int insn = *p->ainsn.insn;
@@ -373,8 +374,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
373/* 374/*
374 * Wrapper routine to for handling exceptions. 375 * Wrapper routine to for handling exceptions.
375 */ 376 */
376int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, 377int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
377 void *data) 378 unsigned long val, void *data)
378{ 379{
379 struct die_args *args = (struct die_args *)data; 380 struct die_args *args = (struct die_args *)data;
380 int ret = NOTIFY_DONE; 381 int ret = NOTIFY_DONE;
@@ -406,7 +407,7 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
406 return ret; 407 return ret;
407} 408}
408 409
409int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) 410int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
410{ 411{
411 struct jprobe *jp = container_of(p, struct jprobe, kp); 412 struct jprobe *jp = container_of(p, struct jprobe, kp);
412 413
@@ -419,16 +420,16 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
419 return 1; 420 return 1;
420} 421}
421 422
422void jprobe_return(void) 423void __kprobes jprobe_return(void)
423{ 424{
424 asm volatile("trap" ::: "memory"); 425 asm volatile("trap" ::: "memory");
425} 426}
426 427
427void jprobe_return_end(void) 428void __kprobes jprobe_return_end(void)
428{ 429{
429}; 430};
430 431
431int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) 432int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
432{ 433{
433 /* 434 /*
434 * FIXME - we should ideally be validating that we got here 'cos 435 * FIXME - we should ideally be validating that we got here 'cos
diff --git a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
index 2164bd7b4ef6..6d860c1d9fa0 100644
--- a/arch/ppc64/kernel/misc.S
+++ b/arch/ppc64/kernel/misc.S
@@ -183,7 +183,7 @@ PPC64_CACHES:
183 * flush all bytes from start through stop-1 inclusive 183 * flush all bytes from start through stop-1 inclusive
184 */ 184 */
185 185
186_GLOBAL(__flush_icache_range) 186_KPROBE(__flush_icache_range)
187 187
188/* 188/*
189 * Flush the data cache to memory 189 * Flush the data cache to memory
@@ -223,7 +223,7 @@ _GLOBAL(__flush_icache_range)
223 bdnz 2b 223 bdnz 2b
224 isync 224 isync
225 blr 225 blr
226 226 .previous .text
227/* 227/*
228 * Like above, but only do the D-cache. 228 * Like above, but only do the D-cache.
229 * 229 *
diff --git a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
index a8d5e83ee89f..7467ae508e6e 100644
--- a/arch/ppc64/kernel/traps.c
+++ b/arch/ppc64/kernel/traps.c
@@ -30,6 +30,7 @@
30#include <linux/init.h> 30#include <linux/init.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/kprobes.h>
33#include <asm/kdebug.h> 34#include <asm/kdebug.h>
34 35
35#include <asm/pgtable.h> 36#include <asm/pgtable.h>
@@ -220,7 +221,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)
220 _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip); 221 _exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
221} 222}
222 223
223void single_step_exception(struct pt_regs *regs) 224void __kprobes single_step_exception(struct pt_regs *regs)
224{ 225{
225 regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ 226 regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */
226 227
@@ -398,7 +399,7 @@ check_bug_trap(struct pt_regs *regs)
398 return 0; 399 return 0;
399} 400}
400 401
401void program_check_exception(struct pt_regs *regs) 402void __kprobes program_check_exception(struct pt_regs *regs)
402{ 403{
403 if (debugger_fault_handler(regs)) 404 if (debugger_fault_handler(regs))
404 return; 405 return;
diff --git a/arch/ppc64/kernel/vmlinux.lds.S b/arch/ppc64/kernel/vmlinux.lds.S
index 4103cc13f8d6..0306510bc4ff 100644
--- a/arch/ppc64/kernel/vmlinux.lds.S
+++ b/arch/ppc64/kernel/vmlinux.lds.S
@@ -15,6 +15,7 @@ SECTIONS
15 *(.text .text.*) 15 *(.text .text.*)
16 SCHED_TEXT 16 SCHED_TEXT
17 LOCK_TEXT 17 LOCK_TEXT
18 KPROBES_TEXT
18 *(.fixup) 19 *(.fixup)
19 . = ALIGN(4096); 20 . = ALIGN(4096);
20 _etext = .; 21 _etext = .;
diff --git a/arch/ppc64/mm/fault.c b/arch/ppc64/mm/fault.c
index 20b0f37e8bf8..772f0714a5b7 100644
--- a/arch/ppc64/mm/fault.c
+++ b/arch/ppc64/mm/fault.c
@@ -29,6 +29,7 @@
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/smp_lock.h> 30#include <linux/smp_lock.h>
31#include <linux/module.h> 31#include <linux/module.h>
32#include <linux/kprobes.h>
32 33
33#include <asm/page.h> 34#include <asm/page.h>
34#include <asm/pgtable.h> 35#include <asm/pgtable.h>
@@ -84,8 +85,8 @@ static int store_updates_sp(struct pt_regs *regs)
84 * The return value is 0 if the fault was handled, or the signal 85 * The return value is 0 if the fault was handled, or the signal
85 * number if this is a kernel fault that can't be handled here. 86 * number if this is a kernel fault that can't be handled here.
86 */ 87 */
87int do_page_fault(struct pt_regs *regs, unsigned long address, 88int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
88 unsigned long error_code) 89 unsigned long error_code)
89{ 90{
90 struct vm_area_struct * vma; 91 struct vm_area_struct * vma;
91 struct mm_struct *mm = current->mm; 92 struct mm_struct *mm = current->mm;