summaryrefslogtreecommitdiff
path: root/arch/arm/kernel/uprobes.c
diff options
context:
space:
mode:
authorWang Nan <wangnan0@huawei.com>2015-01-09 10:19:49 +0800
committerJon Medhurst <tixy@linaro.org>2015-01-09 09:36:50 +0000
commitfca08f326ae0423f03b097ff54de432fe77b95d0 (patch)
tree40d680c04ec5ec613c0b8bb9ec9ff8b5821bc237 /arch/arm/kernel/uprobes.c
parentb1940cd21c0f4abdce101253e860feff547291b0 (diff)
ARM: probes: move all probe code to dedicate directory
In discussion on LKML (https://lkml.org/lkml/2014/11/28/158), Russell King suggests to move all probe related code to arch/arm/probes. This patch does the work. Due to dependency on 'arch/arm/kernel/patch.h', this patch also moves patch.h to 'arch/arm/include/asm/patch.h', and related '#include' directives are also midified to '#include <asm/patch.h>'. Following is an overview of this patch: ./arch/arm/kernel/ ./arch/arm/probes/ |-- Makefile |-- Makefile |-- probes-arm.c ==> |-- decode-arm.c |-- probes-arm.h ==> |-- decode-arm.h |-- probes-thumb.c ==> |-- decode-thumb.c |-- probes-thumb.h ==> |-- decode-thumb.h |-- probes.c ==> |-- decode.c |-- probes.h ==> |-- decode.h | |-- kprobes | | |-- Makefile |-- kprobes-arm.c ==> | |-- actions-arm.c |-- kprobes-common.c ==> | |-- actions-common.c |-- kprobes-thumb.c ==> | |-- actions-thumb.c |-- kprobes.c ==> | |-- core.c |-- kprobes.h ==> | |-- core.h |-- kprobes-test-arm.c ==> | |-- test-arm.c |-- kprobes-test.c ==> | |-- test-core.c |-- kprobes-test.h ==> | |-- test-core.h |-- kprobes-test-thumb.c ==> | `-- test-thumb.c | `-- uprobes | |-- Makefile |-- uprobes-arm.c ==> |-- actions-arm.c |-- uprobes.c ==> |-- core.c |-- uprobes.h ==> `-- core.h | `-- patch.h ==> arch/arm/include/asm/patch.h Signed-off-by: Wang Nan <wangnan0@huawei.com> Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Jon Medhurst <tixy@linaro.org>
Diffstat (limited to 'arch/arm/kernel/uprobes.c')
-rw-r--r--arch/arm/kernel/uprobes.c230
1 files changed, 0 insertions, 230 deletions
diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c
deleted file mode 100644
index 56adf9c1fde0..000000000000
--- a/arch/arm/kernel/uprobes.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * Copyright (C) 2012 Rabin Vincent <rabin at rab.in>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/errno.h>
-#include <linux/highmem.h>
-#include <linux/sched.h>
-#include <linux/uprobes.h>
-#include <linux/notifier.h>
-
-#include <asm/opcodes.h>
-#include <asm/traps.h>
-
-#include "probes.h"
-#include "probes-arm.h"
-#include "uprobes.h"
-
-#define UPROBE_TRAP_NR UINT_MAX
-
-bool is_swbp_insn(uprobe_opcode_t *insn)
-{
- return (__mem_to_opcode_arm(*insn) & 0x0fffffff) ==
- (UPROBE_SWBP_ARM_INSN & 0x0fffffff);
-}
-
-int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
- unsigned long vaddr)
-{
- return uprobe_write_opcode(mm, vaddr,
- __opcode_to_mem_arm(auprobe->bpinsn));
-}
-
-bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs)
-{
- if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) {
- regs->ARM_pc += 4;
- return true;
- }
-
- return false;
-}
-
-bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
-{
- probes_opcode_t opcode;
-
- if (!auprobe->simulate)
- return false;
-
- opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn);
-
- auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs);
-
- return true;
-}
-
-unsigned long
-arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
- struct pt_regs *regs)
-{
- unsigned long orig_ret_vaddr;
-
- orig_ret_vaddr = regs->ARM_lr;
- /* Replace the return addr with trampoline addr */
- regs->ARM_lr = trampoline_vaddr;
- return orig_ret_vaddr;
-}
-
-int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
- unsigned long addr)
-{
- unsigned int insn;
- unsigned int bpinsn;
- enum probes_insn ret;
-
- /* Thumb not yet support */
- if (addr & 0x3)
- return -EINVAL;
-
- insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn);
- auprobe->ixol[0] = __opcode_to_mem_arm(insn);
- auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN);
-
- ret = arm_probes_decode_insn(insn, &auprobe->asi, false,
- uprobes_probes_actions);
- switch (ret) {
- case INSN_REJECTED:
- return -EINVAL;
-
- case INSN_GOOD_NO_SLOT:
- auprobe->simulate = true;
- break;
-
- case INSN_GOOD:
- default:
- break;
- }
-
- bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff;
- if (insn >= 0xe0000000)
- bpinsn |= 0xe0000000; /* Unconditional instruction */
- else
- bpinsn |= insn & 0xf0000000; /* Copy condition from insn */
-
- auprobe->bpinsn = bpinsn;
-
- return 0;
-}
-
-void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
- void *src, unsigned long len)
-{
- void *xol_page_kaddr = kmap_atomic(page);
- void *dst = xol_page_kaddr + (vaddr & ~PAGE_MASK);
-
- preempt_disable();
-
- /* Initialize the slot */
- memcpy(dst, src, len);
-
- /* flush caches (dcache/icache) */
- flush_uprobe_xol_access(page, vaddr, dst, len);
-
- preempt_enable();
-
- kunmap_atomic(xol_page_kaddr);
-}
-
-
-int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
-{
- struct uprobe_task *utask = current->utask;
-
- if (auprobe->prehandler)
- auprobe->prehandler(auprobe, &utask->autask, regs);
-
- utask->autask.saved_trap_no = current->thread.trap_no;
- current->thread.trap_no = UPROBE_TRAP_NR;
- regs->ARM_pc = utask->xol_vaddr;
-
- return 0;
-}
-
-int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
-{
- struct uprobe_task *utask = current->utask;
-
- WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR);
-
- current->thread.trap_no = utask->autask.saved_trap_no;
- regs->ARM_pc = utask->vaddr + 4;
-
- if (auprobe->posthandler)
- auprobe->posthandler(auprobe, &utask->autask, regs);
-
- return 0;
-}
-
-bool arch_uprobe_xol_was_trapped(struct task_struct *t)
-{
- if (t->thread.trap_no != UPROBE_TRAP_NR)
- return true;
-
- return false;
-}
-
-void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
-{
- struct uprobe_task *utask = current->utask;
-
- current->thread.trap_no = utask->autask.saved_trap_no;
- instruction_pointer_set(regs, utask->vaddr);
-}
-
-int arch_uprobe_exception_notify(struct notifier_block *self,
- unsigned long val, void *data)
-{
- return NOTIFY_DONE;
-}
-
-static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- instr &= 0x0fffffff;
- if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff))
- uprobe_pre_sstep_notifier(regs);
- else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff))
- uprobe_post_sstep_notifier(regs);
- local_irq_restore(flags);
-
- return 0;
-}
-
-unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
-{
- return instruction_pointer(regs);
-}
-
-static struct undef_hook uprobes_arm_break_hook = {
- .instr_mask = 0x0fffffff,
- .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff),
- .cpsr_mask = MODE_MASK,
- .cpsr_val = USR_MODE,
- .fn = uprobe_trap_handler,
-};
-
-static struct undef_hook uprobes_arm_ss_hook = {
- .instr_mask = 0x0fffffff,
- .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff),
- .cpsr_mask = MODE_MASK,
- .cpsr_val = USR_MODE,
- .fn = uprobe_trap_handler,
-};
-
-static int arch_uprobes_init(void)
-{
- register_undef_hook(&uprobes_arm_break_hook);
- register_undef_hook(&uprobes_arm_ss_hook);
-
- return 0;
-}
-device_initcall(arch_uprobes_init);