Merge branch 'tizen_2.4' into tizen_2.4_dev
[kernel/swap-modules.git] / uprobe / arch / arm / swap-asm / swap_uprobes.c
index 1250c44..43315b7 100644 (file)
        flush_icache_range((unsigned long)(addr),               \
                           (unsigned long)(addr) + (size))
 
-static inline long branch_t16_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long branch_t16_dest(uprobe_opcode_t insn, unsigned int insn_addr)
 {
        long offset = insn & 0x3ff;
        offset -= insn & 0x400;
        return insn_addr + 4 + offset * 2;
 }
 
-static inline long branch_cond_t16_dest(kprobe_opcode_t insn,
+static inline long branch_cond_t16_dest(uprobe_opcode_t insn,
                                        unsigned int insn_addr)
 {
        long offset = insn & 0x7f;
@@ -75,7 +75,7 @@ static inline long branch_cond_t16_dest(kprobe_opcode_t insn,
        return insn_addr + 4 + offset * 2;
 }
 
-static inline long branch_t32_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long branch_t32_dest(uprobe_opcode_t insn, unsigned int insn_addr)
 {
        unsigned int poff = insn & 0x3ff;
        unsigned int offset = (insn & 0x07fe0000) >> 17;
@@ -88,7 +88,7 @@ static inline long branch_t32_dest(kprobe_opcode_t insn, unsigned int insn_addr)
        return (insn_addr + 4 + (poff << 12) + offset * 4) & ~3;
 }
 
-static inline long cbz_t16_dest(kprobe_opcode_t insn, unsigned int insn_addr)
+static inline long cbz_t16_dest(uprobe_opcode_t insn, unsigned int insn_addr)
 {
        unsigned int i = (insn & 0x200) >> 3;
        unsigned int offset = (insn & 0xf8) >> 2;
@@ -96,7 +96,7 @@ static inline long cbz_t16_dest(kprobe_opcode_t insn, unsigned int insn_addr)
 }
 
 /* is instruction Thumb2 and NOT a branch, etc... */
-static int is_thumb2(kprobe_opcode_t insn)
+static int is_thumb2(uprobe_opcode_t insn)
 {
        return ((insn & 0xf800) == 0xe800 ||
                (insn & 0xf800) == 0xf000 ||
@@ -163,8 +163,8 @@ static int arch_check_insn_thumb(unsigned long insn)
        return ret;
 }
 
-static int prep_pc_dep_insn_execbuf_thumb(kprobe_opcode_t *insns,
-                                         kprobe_opcode_t insn, int uregs)
+static int prep_pc_dep_insn_execbuf_thumb(uprobe_opcode_t *insns,
+                                         uprobe_opcode_t insn, int uregs)
 {
        unsigned char mreg = 0;
        unsigned char reg = 0;
@@ -586,11 +586,10 @@ static int arch_make_trampoline_thumb(unsigned long vaddr, unsigned long insn,
  * @return 0 on success,\n
  * negative error code on error.
  */
-int arch_prepare_uprobe(struct uprobe *up)
+int arch_prepare_uprobe(struct uprobe *p)
 {
        int ret;
-       struct kprobe *p = up2kp(up);
-       struct task_struct *task = up->task;
+       struct task_struct *task = p->task;
        unsigned long vaddr = (unsigned long)p->addr & ~((unsigned long)1);
        unsigned long insn;
        int thumb_mode = (unsigned long)p->addr & 1;
@@ -612,17 +611,17 @@ int arch_prepare_uprobe(struct uprobe *up)
                return ret;
        }
 
-       utramp = swap_slot_alloc(up->sm);
+       utramp = swap_slot_alloc(p->sm);
        if (utramp == NULL) {
                printk(KERN_INFO "Error: swap_slot_alloc failed (%08lx)\n",
                       vaddr);
                return -ENOMEM;
        }
 
-       if (!write_proc_vm_atomic(up->task, (unsigned long)utramp, tramp,
+       if (!write_proc_vm_atomic(p->task, (unsigned long)utramp, tramp,
                                  tramp_len)) {
                pr_err("failed to write memory tramp=%p!\n", utramp);
-               swap_slot_free(up->sm, utramp);
+               swap_slot_free(p->sm, utramp);
                return -EINVAL;
        }
 
@@ -645,13 +644,13 @@ int arch_prepare_uprobe(struct uprobe *up)
 void arch_opcode_analysis_uretprobe(struct uretprobe *rp)
 {
        /* Remove retprobe if first insn overwrites lr */
-       rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.kp.opcode) ||
-                            THUMB2_INSN_MATCH(BLX1, rp->up.kp.opcode) ||
-                            THUMB_INSN_MATCH(BLX2, rp->up.kp.opcode));
+       rp->thumb_noret = !!(THUMB2_INSN_MATCH(BL, rp->up.opcode) ||
+                            THUMB2_INSN_MATCH(BLX1, rp->up.opcode) ||
+                            THUMB_INSN_MATCH(BLX2, rp->up.opcode));
 
-       rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.kp.opcode) ||
-                          ARM_INSN_MATCH(BLX1, rp->up.kp.opcode) ||
-                          ARM_INSN_MATCH(BLX2, rp->up.kp.opcode));
+       rp->arm_noret = !!(ARM_INSN_MATCH(BL, rp->up.opcode) ||
+                          ARM_INSN_MATCH(BLX1, rp->up.opcode) ||
+                          ARM_INSN_MATCH(BLX2, rp->up.opcode));
 }
 
 /**
@@ -663,19 +662,19 @@ void arch_opcode_analysis_uretprobe(struct uretprobe *rp)
  */
 int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
 {
-       ri->ret_addr = (kprobe_opcode_t *)regs->ARM_lr;
-       ri->sp = (kprobe_opcode_t *)regs->ARM_sp;
+       ri->ret_addr = (uprobe_opcode_t *)regs->ARM_lr;
+       ri->sp = (uprobe_opcode_t *)regs->ARM_sp;
 
        /* Set flag of current mode */
-       ri->sp = (kprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
+       ri->sp = (uprobe_opcode_t *)((long)ri->sp | !!thumb_mode(regs));
 
        if (ri->preload_thumb) {
-               regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
+               regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
        } else {
                if (thumb_mode(regs))
-                       regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn) + 0x1b;
+                       regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn) + 0x1b;
                else
-                       regs->ARM_lr = (unsigned long)(ri->rp->up.kp.ainsn.insn +
+                       regs->ARM_lr = (unsigned long)(ri->rp->up.ainsn.insn +
                                                       UPROBES_TRAMP_RET_BREAK_IDX);
        }
 
@@ -686,8 +685,8 @@ unsigned long arch_tramp_by_ri(struct uretprobe_instance *ri)
 {
        /* Understand function mode */
        return ((unsigned long)ri->sp & 1) ?
-                       ((unsigned long)ri->rp->up.kp.ainsn.insn + 0x1b) :
-                       (unsigned long)(ri->rp->up.kp.ainsn.insn +
+                       ((unsigned long)ri->rp->up.ainsn.insn + 0x1b) :
+                       (unsigned long)(ri->rp->up.ainsn.insn +
                                        UPROBES_TRAMP_RET_BREAK_IDX);
 }
 
@@ -713,7 +712,7 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri,
        int i, retval;
 
        if (tr == 0) {
-               vaddr = (unsigned long)ri->rp->up.kp.addr;
+               vaddr = (unsigned long)ri->rp->up.addr;
                tramp = (unsigned long *)arch_tramp_by_ri(ri);
        } else {
                /* ri - invalid */
@@ -783,21 +782,20 @@ check_lr: /* check lr anyway */
 /**
  * @brief Jump pre-handler.
  *
- * @param p Pointer to the kprobe.
+ * @param p Pointer to the uprobe.
  * @param regs Pointer to CPU register data.
  * @return 0.
  */
-int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
+int setjmp_upre_handler(struct uprobe *p, struct pt_regs *regs)
 {
-       struct uprobe *up = container_of(p, struct uprobe, kp);
-       struct ujprobe *jp = container_of(up, struct ujprobe, up);
+       struct ujprobe *jp = container_of(p, struct ujprobe, up);
 
-       kprobe_pre_entry_handler_t pre_entry =
-               (kprobe_pre_entry_handler_t)jp->pre_entry;
+       uprobe_pre_entry_handler_t pre_entry =
+               (uprobe_pre_entry_handler_t)jp->pre_entry;
        entry_point_t entry = (entry_point_t)jp->entry;
 
        if (pre_entry) {
-               p->ss_addr[smp_processor_id()] = (kprobe_opcode_t *)
+               p->ss_addr[smp_processor_id()] = (uprobe_opcode_t *)
                                                 pre_entry(jp->priv_arg, regs);
        }
 
@@ -814,11 +812,11 @@ int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
 /**
  * @brief Gets trampoline address.
  *
- * @param p Pointer to the kprobe.
+ * @param p Pointer to the uprobe.
  * @param regs Pointer to CPU register data.
  * @return Trampoline address.
  */
-unsigned long arch_get_trampoline_addr(struct kprobe *p, struct pt_regs *regs)
+unsigned long arch_get_trampoline_addr(struct uprobe *p, struct pt_regs *regs)
 {
        return thumb_mode(regs) ?
                        (unsigned long)(p->ainsn.insn) + 0x1b :
@@ -852,14 +850,14 @@ void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
  */
 void arch_remove_uprobe(struct uprobe *up)
 {
-       swap_slot_free(up->sm, up->kp.ainsn.insn);
+       swap_slot_free(up->sm, up->ainsn.insn);
 }
 
 int arch_arm_uprobe(struct uprobe *p)
 {
        int ret;
-       unsigned long vaddr = (unsigned long)p->kp.addr & ~((unsigned long)1);
-       int thumb_mode = (unsigned long)p->kp.addr & 1;
+       unsigned long vaddr = (unsigned long)p->addr & ~((unsigned long)1);
+       int thumb_mode = (unsigned long)p->addr & 1;
        int len = 4 >> thumb_mode;      /* if thumb_mode then len = 2 */
        unsigned long insn = thumb_mode ? UBP_THUMB : UBP_ARM;
 
@@ -876,7 +874,7 @@ int arch_arm_uprobe(struct uprobe *p)
        return 0;
 }
 
-void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task)
+void arch_disarm_uprobe(struct uprobe *p, struct task_struct *task)
 {
        int ret;
 
@@ -895,14 +893,14 @@ void arch_disarm_uprobe(struct kprobe *p, struct task_struct *task)
 
 static int urp_handler(struct pt_regs *regs, pid_t tgid)
 {
-       struct kprobe *p;
+       struct uprobe *p;
        unsigned long vaddr = regs->ARM_pc;
        unsigned long offset_bp = thumb_mode(regs) ?
                                  0x1a :
                                  4 * UPROBES_TRAMP_RET_BREAK_IDX;
        unsigned long tramp_addr = vaddr - offset_bp;
 
-       p = get_ukprobe_by_insn_slot((void *)tramp_addr, tgid, regs);
+       p = get_uprobe_by_insn_slot((void *)tramp_addr, tgid, regs);
        if (p == NULL) {
                printk(KERN_INFO
                       "no_uprobe: Not one of ours: let kernel handle it %lx\n",
@@ -914,6 +912,24 @@ static int urp_handler(struct pt_regs *regs, pid_t tgid)
 
        return 0;
 }
+/**
+ * @brief Prepares singlestep for current CPU.
+ *
+ * @param p Pointer to kprobe.
+ * @param regs Pointer to CPU registers data.
+ * @return Void.
+ */
+static void arch_prepare_singlestep(struct uprobe *p, struct pt_regs *regs)
+{
+       int cpu = smp_processor_id();
+
+       if (p->ss_addr[cpu]) {
+               regs->ARM_pc = (unsigned long)p->ss_addr[cpu];
+               p->ss_addr[cpu] = NULL;
+       } else {
+               regs->ARM_pc = (unsigned long)p->ainsn.insn;
+       }
+}
 
 /**
  * @brief Breakpoint instruction handler.
@@ -925,7 +941,7 @@ static int urp_handler(struct pt_regs *regs, pid_t tgid)
 int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
 {
        int ret = 0;
-       struct kprobe *p;
+       struct uprobe *p;
        unsigned long flags;
        unsigned long vaddr = regs->ARM_pc | !!thumb_mode(regs);
        pid_t tgid = current->tgid;
@@ -933,12 +949,11 @@ int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
        local_irq_save(flags);
        preempt_disable();
 
-       p = get_ukprobe((kprobe_opcode_t *)vaddr, tgid);
+       p = get_uprobe((uprobe_opcode_t *)vaddr, tgid);
        if (p) {
-               struct uprobe *up = kp2up(p);
                bool prepare = false;
 
-               if (up->atomic_ctx) {
+               if (p->atomic_ctx) {
                        if (!p->pre_handler || !p->pre_handler(p, regs))
                                prepare = true;
                } else {
@@ -953,14 +968,14 @@ int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
                }
 
                if (prepare)
-                       prepare_singlestep(p, regs);
+                       arch_prepare_singlestep(p, regs);
        } else {
                ret = urp_handler(regs, tgid);
 
                /* check ARM/THUMB mode on correct */
                if (ret) {
                        vaddr ^= 1;
-                       p = get_ukprobe((kprobe_opcode_t *)vaddr, tgid);
+                       p = get_uprobe((uprobe_opcode_t *)vaddr, tgid);
                        if (p) {
                                pr_err("invalid mode: thumb=%d addr=%p insn=%08lx\n",
                                       !!thumb_mode(regs), p->addr, p->opcode);