diff options
author | Prasanna S Panchamukhi <prasanna@in.ibm.com> | 2005-09-06 15:19:30 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-07 16:58:00 -0700 |
commit | 05e14cb3bafabbf08216ab5566f3cd687eba9723 (patch) | |
tree | 6320a3e9193c474571401b2c279b1ee176c29c27 | |
parent | 1f7ad57b75ab0fba27455c7344a6ab7aa6bd90c5 (diff) | |
download | op-kernel-dev-05e14cb3bafabbf08216ab5566f3cd687eba9723.zip op-kernel-dev-05e14cb3bafabbf08216ab5566f3cd687eba9723.tar.gz |
[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>
-rw-r--r-- | arch/sparc64/kernel/kprobes.c | 36 | ||||
-rw-r--r-- | arch/sparc64/kernel/vmlinux.lds.S | 1 | ||||
-rw-r--r-- | arch/sparc64/mm/fault.c | 8 | ||||
-rw-r--r-- | arch/sparc64/mm/init.c | 3 | ||||
-rw-r--r-- | arch/sparc64/mm/ultra.S | 2 |
5 files changed, 30 insertions, 20 deletions
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index bbf11f8..0d66d07 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -8,6 +8,7 @@ #include <linux/kprobes.h> #include <asm/kdebug.h> #include <asm/signal.h> +#include <asm/cacheflush.h> /* We do not have hardware single-stepping on sparc64. * So we implement software single-stepping with breakpoint @@ -37,31 +38,31 @@ * - Mark that we are no longer actively in a kprobe. */ -int arch_prepare_kprobe(struct kprobe *p) +int __kprobes arch_prepare_kprobe(struct kprobe *p) { return 0; } -void arch_copy_kprobe(struct kprobe *p) +void __kprobes arch_copy_kprobe(struct kprobe *p) { p->ainsn.insn[0] = *p->addr; p->ainsn.insn[1] = BREAKPOINT_INSTRUCTION_2; p->opcode = *p->addr; } -void arch_arm_kprobe(struct kprobe *p) +void __kprobes arch_arm_kprobe(struct kprobe *p) { *p->addr = BREAKPOINT_INSTRUCTION; flushi(p->addr); } -void arch_disarm_kprobe(struct kprobe *p) +void __kprobes arch_disarm_kprobe(struct kprobe *p) { *p->addr = p->opcode; flushi(p->addr); } -void arch_remove_kprobe(struct kprobe *p) +void __kprobes arch_remove_kprobe(struct kprobe *p) { } @@ -111,7 +112,7 @@ static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) } } -static int kprobe_handler(struct pt_regs *regs) +static int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; void *addr = (void *) regs->tpc; @@ -191,8 +192,9 @@ no_kprobe: * The original INSN location was REAL_PC, it actually * executed at PC and produced destination address NPC. */ -static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc, - unsigned long pc, unsigned long npc) +static unsigned long __kprobes relbranch_fixup(u32 insn, unsigned long real_pc, + unsigned long pc, + unsigned long npc) { /* Branch not taken, no mods necessary. */ if (npc == pc + 0x4UL) @@ -217,7 +219,8 @@ static unsigned long relbranch_fixup(u32 insn, unsigned long real_pc, /* If INSN is an instruction which writes it's PC location * into a destination register, fix that up. */ -static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc) +static void __kprobes retpc_fixup(struct pt_regs *regs, u32 insn, + unsigned long real_pc) { unsigned long *slot = NULL; @@ -257,7 +260,7 @@ static void retpc_fixup(struct pt_regs *regs, u32 insn, unsigned long real_pc) * This function prepares to return from the post-single-step * breakpoint trap. */ -static void resume_execution(struct kprobe *p, struct pt_regs *regs) +static void __kprobes resume_execution(struct kprobe *p, struct pt_regs *regs) { u32 insn = p->ainsn.insn[0]; @@ -315,8 +318,8 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr) /* * Wrapper routine to for handling exceptions. */ -int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, - void *data) +int __kprobes kprobe_exceptions_notify(struct notifier_block *self, + unsigned long val, void *data) { struct die_args *args = (struct die_args *)data; switch (val) { @@ -344,7 +347,8 @@ int kprobe_exceptions_notify(struct notifier_block *self, unsigned long val, return NOTIFY_DONE; } -asmlinkage void kprobe_trap(unsigned long trap_level, struct pt_regs *regs) +asmlinkage void __kprobes kprobe_trap(unsigned long trap_level, + struct pt_regs *regs) { BUG_ON(trap_level != 0x170 && trap_level != 0x171); @@ -368,7 +372,7 @@ static struct pt_regs jprobe_saved_regs; static struct pt_regs *jprobe_saved_regs_location; static struct sparc_stackf jprobe_saved_stack; -int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct jprobe *jp = container_of(p, struct jprobe, kp); @@ -390,7 +394,7 @@ int setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs) return 1; } -void jprobe_return(void) +void __kprobes jprobe_return(void) { preempt_enable_no_resched(); __asm__ __volatile__( @@ -403,7 +407,7 @@ extern void jprobe_return_trap_instruction(void); extern void __show_regs(struct pt_regs * regs); -int longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) +int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) { u32 *addr = (u32 *) regs->tpc; diff --git a/arch/sparc64/kernel/vmlinux.lds.S b/arch/sparc64/kernel/vmlinux.lds.S index 950423d..f47d0be 100644 --- a/arch/sparc64/kernel/vmlinux.lds.S +++ b/arch/sparc64/kernel/vmlinux.lds.S @@ -17,6 +17,7 @@ SECTIONS *(.text) SCHED_TEXT LOCK_TEXT + KPROBES_TEXT *(.gnu.warning) } =0 _etext = .; diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 52e9375..db1e331 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c @@ -18,6 +18,7 @@ #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/interrupt.h> +#include <linux/kprobes.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -117,8 +118,9 @@ unsigned long __init prom_probe_memory (void) return tally; } -static void unhandled_fault(unsigned long address, struct task_struct *tsk, - struct pt_regs *regs) +static void __kprobes unhandled_fault(unsigned long address, + struct task_struct *tsk, + struct pt_regs *regs) { if ((unsigned long) address < PAGE_SIZE) { printk(KERN_ALERT "Unable to handle kernel NULL " @@ -304,7 +306,7 @@ cannot_handle: unhandled_fault (address, current, regs); } -asmlinkage void do_sparc64_fault(struct pt_regs *regs) +asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index 3fbaf34..fdb1ebb 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c @@ -19,6 +19,7 @@ #include <linux/pagemap.h> #include <linux/fs.h> #include <linux/seq_file.h> +#include <linux/kprobes.h> #include <asm/head.h> #include <asm/system.h> @@ -250,7 +251,7 @@ out: put_cpu(); } -void flush_icache_range(unsigned long start, unsigned long end) +void __kprobes flush_icache_range(unsigned long start, unsigned long end) { /* Cheetah has coherent I-cache. */ if (tlb_type == spitfire) { diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S index 8dfa825..78beff3 100644 --- a/arch/sparc64/mm/ultra.S +++ b/arch/sparc64/mm/ultra.S @@ -119,6 +119,7 @@ __spitfire_flush_tlb_mm_slow: #else #error unsupported PAGE_SIZE #endif + .section .kprobes.text .align 32 .globl __flush_icache_page __flush_icache_page: /* %o0 = phys_page */ @@ -201,6 +202,7 @@ dflush4:stxa %g0, [%o4] ASI_DCACHE_TAG nop #endif /* DCACHE_ALIASING_POSSIBLE */ + .previous .text .align 32 __prefill_dtlb: rdpr %pstate, %g7 |