aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/kprobes.c
diff options
context:
space:
mode:
authorPrasanna S Panchamukhi <prasanna@in.ibm.com>2005-09-06 18:19:30 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-07 19:58:00 -0400
commit05e14cb3bafabbf08216ab5566f3cd687eba9723 (patch)
tree6320a3e9193c474571401b2c279b1ee176c29c27 /arch/sparc64/kernel/kprobes.c
parent1f7ad57b75ab0fba27455c7344a6ab7aa6bd90c5 (diff)
[PATCH] Kprobes: prevent possible race conditions sparc64 changes
This patch contains the sparc64 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/sparc64/kernel/kprobes.c')
-rw-r--r--arch/sparc64/kernel/kprobes.c36
1 files changed, 20 insertions, 16 deletions
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index bbf11f85dab1..0d66d07c8c6e 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -8,6 +8,7 @@
8#include <linux/kprobes.h> 8#include <linux/kprobes.h>
9#include <asm/kdebug.h> 9#include <asm/kdebug.h>
10#include <asm/signal.h> 10#include <asm/signal.h>
11#include <asm/cacheflush.h>
11 12
12/* We do not have hardware single-stepping on sparc64. 13/* We do not have hardware single-stepping on sparc64.
13 * So we implement software single-stepping with breakpoint 14 * So we implement software single-stepping with breakpoint
@@ -37,31 +38,31 @@
37 * - Mark that we are no longer actively in a kprobe. 38 * - Mark that we are no longer actively in a kprobe.
38 */ 39 */
39 40
40int arch_prepare_kprobe(struct kprobe *p) 41int __kprobes arch_prepare_kprobe(struct kprobe *p)
41{ 42{
42 return 0; 43 return 0;
43} 44}
44 45
45void arch_copy_kprobe(struct kprobe *p) 46void __kprobes arch_copy_kprobe(struct kprobe *p)
46{ 47{
47 p->ainsn.insn[0] = *p->addr; 48 p->ainsn.insn[0] = *p->addr;
48 p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2; 49 p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2;
49 p->opcode = *p->addr; 50 p->opcode = *p->addr;
50} 51}
51 52
52void arch_arm_kprobe(struct kprobe *p) 53void __kprobes arch_arm_kprobe(struct kprobe *p)
53{ 54{
54 *p->addr = BREAKPOINT_INSTRUCTION; 55 *p->addr = BREAKPOINT_INSTRUCTION;
55 flushi(p->addr); 56 flushi(p->addr);
56} 57}
57 58
58void arch_disarm_kprobe(struct kprobe *p) 59void __kprobes arch_disarm_kprobe(struct kprobe *p)
59{ 60{
60 *p->addr = p->opcode; 61 *p->addr = p->opcode;
61 flushi(p->addr); 62 flushi(p->addr);
62} 63}
63 64
64void arch_remove_kprobe(struct kprobe *p) 65void __kprobes arch_remove_kprobe(struct kprobe *p)
65{ 66{
66} 67}
67 68
@@ -111,7 +112,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
111 } 112 }
112} 113}
113 114
114static int kprobe_handler(struct pt_regs *regs) 115static int __kprobes kprobe_handler(struct pt_regs *regs)
115{ 116{
116 struct kprobe *p; 117 struct kprobe *p;
117 void *addr = (void *) regs->tpc; 118 void *addr = (void *) regs->tpc;
@@ -191,8 +192,9 @@ no_kprobe:
191 * The original INSN location was REAL_PC, it actually 192 * The original INSN location was REAL_PC, it actually
192 * executed at PC and produced destination address NPC. 193 * executed at PC and produced destination address NPC.
193 */ 194 */
194static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc, 195static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc,
195 unsigned long pc, unsigned long npc) 196 unsigned long pc,
197 unsigned long npc)
196{ 198{
197 /* Branch not taken, no mods necessary. */ 199 /* Branch not taken, no mods necessary. */
198 if (npc == pc + 0x4UL) 200 if (npc == pc + 0x4UL)
@@ -217,7 +219,8 @@ static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc,
217/* If INSN is an instruction which writes it's PC location 219/* If INSN is an instruction which writes it's PC location
218 * into a destination register, fix that up. 220 * into a destination register, fix that up.
219 */ 221 */
220static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc) 222static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn,
223 unsigned long real_pc)
221{ 224{
222 unsigned long *slot = NULL; 225 unsigned long *slot = NULL;
223 226
@@ -257,7 +260,7 @@ static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc)
257 * This function prepares to return from the post-single-step 260 * This function prepares to return from the post-single-step
258 * breakpoint trap. 261 * breakpoint trap.
259 */ 262 */
260static void resume_execution(struct kprobe *p, struct pt_regs *regs) 263static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs)
261{ 264{
262 u32 insn = p->ainsn.insn[0]; 265 u32 insn = p->ainsn.insn[0];
263 266
@@ -315,8 +318,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
315/* 318/*
316 * Wrapper routine to for handling exceptions. 319 * Wrapper routine to for handling exceptions.
317 */ 320 */
318int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, 321int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
319 void *data) 322 unsigned long val, void *data)
320{ 323{
321 struct die_args *args = (struct die_args *)data; 324 struct die_args *args = (struct die_args *)data;
322 switch (val) { 325 switch (val) {
@@ -344,7 +347,8 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val,
344 return NOTIFY_DONE; 347 return NOTIFY_DONE;
345} 348}
346 349
347asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs) 350asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
351 struct pt_regs *regs)
348{ 352{
349 BUG_ON(trap_level != 0x170 && trap_level != 0x171); 353 BUG_ON(trap_level != 0x170 && trap_level != 0x171);
350 354
@@ -368,7 +372,7 @@ static struct pt_regs jprobe_saved_regs;
368static struct pt_regs *jprobe_saved_regs_location; 372static struct pt_regs *jprobe_saved_regs_location;
369static struct sparc_stackf jprobe_saved_stack; 373static struct sparc_stackf jprobe_saved_stack;
370 374
371int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) 375int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
372{ 376{
373 struct jprobe *jp = container_of(p, struct jprobe, kp); 377 struct jprobe *jp = container_of(p, struct jprobe, kp);
374 378
@@ -390,7 +394,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
390 return 1; 394 return 1;
391} 395}
392 396
393void jprobe_return(void) 397void __kprobes jprobe_return(void)
394{ 398{
395 preempt_enable_no_resched(); 399 preempt_enable_no_resched();
396 __asm__ __volatile__( 400 __asm__ __volatile__(
@@ -403,7 +407,7 @@ extern void jprobe_return_trap_instruction(void);
403 407
404extern void __show_regs(struct pt_regs * regs); 408extern void __show_regs(struct pt_regs * regs);
405 409
406int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) 410int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
407{ 411{
408 u32 *addr = (u32 *) regs->tpc; 412 u32 *addr = (u32 *) regs->tpc;
409 413