Merge branch 'for_tizen_2.4' into tizen_2.4_dev
[platform/kernel/swap-modules.git] / uprobe / arch / x86 / swap-asm / swap_uprobes.c
index 518c304..4aae5f1 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/kdebug.h>
 
 #include <kprobe/swap_slots.h>
+#include <kprobe/swap_td_raw.h>
 #include <uprobe/swap_uprobes.h>
 
 #include "swap_uprobes.h"
  */
 struct uprobe_ctlblk {
        unsigned long flags;            /**< Flags */
-       struct kprobe *p;               /**< Pointer to the uprobe's kprobe */
+       struct uprobe *p;               /**< Pointer to the uprobe */
 };
 
+
+static struct td_raw td_raw;
+
+
 static unsigned long trampoline_addr(struct uprobe *up)
 {
-       return (unsigned long)(up->kp.ainsn.insn +
+       return (unsigned long)(up->ainsn.insn +
                               UPROBES_TRAMP_RET_BREAK_IDX);
 }
 
@@ -61,16 +66,15 @@ unsigned long arch_tramp_by_ri(struct uretprobe_instance *ri)
 
 static struct uprobe_ctlblk *current_ucb(void)
 {
-       /* FIXME hardcoded offset */
-       return (struct uprobe_ctlblk *)(end_of_stack(current) + 20);
+       return (struct uprobe_ctlblk *)swap_td_raw(&td_raw, current);
 }
 
-static struct kprobe *get_current_probe(void)
+static struct uprobe *get_current_probe(void)
 {
        return current_ucb()->p;
 }
 
-static void set_current_probe(struct kprobe *p)
+static void set_current_probe(struct uprobe *p)
 {
        current_ucb()->p = p;
 }
@@ -93,11 +97,10 @@ static void restore_current_flags(struct pt_regs *regs, unsigned long flags)
  * @return 0 on success,\n
  * -1 on error.
  */
-int arch_prepare_uprobe(struct uprobe *up)
+int arch_prepare_uprobe(struct uprobe *p)
 {
-       struct kprobe *p = up2kp(up);
-       struct task_struct *task = up->task;
-       u8 *tramp = up->atramp.tramp;
+       struct task_struct *task = p->task;
+       u8 *tramp = p->atramp.tramp;
        enum { call_relative_opcode = 0xe8 };
 
        if (!read_proc_vm_atomic(task, (unsigned long)p->addr,
@@ -118,15 +121,15 @@ int arch_prepare_uprobe(struct uprobe *up)
 
        p->ainsn.boostable = swap_can_boost(tramp) ? 0 : -1;
 
-       p->ainsn.insn = swap_slot_alloc(up->sm);
+       p->ainsn.insn = swap_slot_alloc(p->sm);
        if (p->ainsn.insn == NULL) {
                printk(KERN_ERR "trampoline out of memory\n");
                return -ENOMEM;
        }
 
        if (!write_proc_vm_atomic(task, (unsigned long)p->ainsn.insn,
-                                 tramp, sizeof(up->atramp.tramp))) {
-               swap_slot_free(up->sm, p->ainsn.insn);
+                                 tramp, sizeof(p->atramp.tramp))) {
+               swap_slot_free(p->sm, p->ainsn.insn);
                printk(KERN_INFO "failed to write memory %p!\n", tramp);
                return -EINVAL;
        }
@@ -140,16 +143,15 @@ int arch_prepare_uprobe(struct uprobe *up)
 /**
  * @brief Jump pre-handler.
  *
- * @param p Pointer to the uprobe's 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);
-       kprobe_pre_entry_handler_t pre_entry =
-               (kprobe_pre_entry_handler_t)jp->pre_entry;
+       struct ujprobe *jp = container_of(p, struct ujprobe, up);
+       uprobe_pre_entry_handler_t pre_entry =
+               (uprobe_pre_entry_handler_t)jp->pre_entry;
        entry_point_t entry = (entry_point_t)jp->entry;
        unsigned long args[6];
 
@@ -167,7 +169,7 @@ int setjmp_upre_handler(struct kprobe *p, struct pt_regs *regs)
                       regs->sp + 4);
 
        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);
 
        if (entry)
@@ -194,7 +196,7 @@ int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
 
        if (get_user(ret_addr, (unsigned long *)regs->sp)) {
                pr_err("failed to read user space func ra %lx addr=%p!\n",
-                      regs->sp, ri->rp->up.kp.addr);
+                      regs->sp, ri->rp->up.addr);
                return -EINVAL;
        }
 
@@ -203,11 +205,25 @@ int arch_prepare_uretprobe(struct uretprobe_instance *ri, struct pt_regs *regs)
                return -EINVAL;
        }
 
-       ri->ret_addr = (kprobe_opcode_t *)ret_addr;
+       ri->ret_addr = (uprobe_opcode_t *)ret_addr;
 
        return 0;
 }
 
+static bool get_long(struct task_struct *task,
+                    unsigned long vaddr, unsigned long *val)
+{
+       return sizeof(*val) != read_proc_vm_atomic(task, vaddr,
+                                                  val, sizeof(*val));
+}
+
+static bool put_long(struct task_struct *task,
+                    unsigned long vaddr, unsigned long *val)
+{
+       return sizeof(*val) != write_proc_vm_atomic(task, vaddr,
+                                                   val, sizeof(*val));
+}
+
 /**
  * @brief Disarms uretprobe on x86 arch.
  *
@@ -228,14 +244,14 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri,
        else
                tramp_addr = tr; /* ri - invalid */
 
-       if (get_user(ret_addr, (unsigned long *)sp)) {
+       if (get_long(task, sp, &ret_addr)) {
                printk(KERN_INFO "---> %s (%d/%d): failed to read stack from %08lx\n",
                       task->comm, task->tgid, task->pid, sp);
                return -EFAULT;
        }
 
        if (tramp_addr == ret_addr) {
-               if (put_user((unsigned long)ri->ret_addr, (unsigned long *)sp)) {
+               if (put_long(task, sp, (unsigned long *)&ri->ret_addr)) {
                        printk(KERN_INFO "---> %s (%d/%d): failed to write "
                               "orig_ret_addr to %08lx",
                               task->comm, task->tgid, task->pid, sp);
@@ -253,13 +269,13 @@ int arch_disarm_urp_inst(struct uretprobe_instance *ri,
 /**
  * @brief Gets trampoline address.
  *
- * @param p Pointer to the uprobe's 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 trampoline_addr(kp2up(p));
+       return trampoline_addr(p);
 }
 
 /**
@@ -280,18 +296,16 @@ void arch_set_orig_ret_addr(unsigned long orig_ret_addr, struct pt_regs *regs)
  * @param up Pointer to the target uprobe.
  * @return Void.
  */
-void arch_remove_uprobe(struct uprobe *up)
+void arch_remove_uprobe(struct uprobe *p)
 {
-       struct kprobe *p = up2kp(up);
-
-       swap_slot_free(up->sm, p->ainsn.insn);
+       swap_slot_free(p->sm, p->ainsn.insn);
 }
 
 int arch_arm_uprobe(struct uprobe *p)
 {
        int ret;
-       kprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
-       unsigned long vaddr = (unsigned long)p->kp.addr;
+       uprobe_opcode_t insn = BREAKPOINT_INSTRUCTION;
+       unsigned long vaddr = (unsigned long)p->addr;
 
        ret = write_proc_vm_atomic(p->task, vaddr, &insn, sizeof(insn));
        if (!ret) {
@@ -304,7 +318,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;
        unsigned long vaddr = (unsigned long)p->addr;
@@ -331,14 +345,14 @@ static void set_user_jmp_op(void *from, void *to)
                pr_err("failed to write jump opcode to user space %p\n", from);
 }
 
-static void resume_execution(struct kprobe *p,
+static void resume_execution(struct uprobe *p,
                             struct pt_regs *regs,
                             unsigned long flags)
 {
        unsigned long *tos, tos_dword = 0;
        unsigned long copy_eip = (unsigned long)p->ainsn.insn;
        unsigned long orig_eip = (unsigned long)p->addr;
-       kprobe_opcode_t insns[2];
+       uprobe_opcode_t insns[2];
 
        regs->EREG(flags) &= ~TF_MASK;
 
@@ -438,7 +452,7 @@ no_change:
        return;
 }
 
-static bool prepare_ss_addr(struct kprobe *p, struct pt_regs *regs)
+static bool prepare_ss_addr(struct uprobe *p, struct pt_regs *regs)
 {
        unsigned long *ss_addr = (long *)&p->ss_addr[smp_processor_id()];
 
@@ -461,20 +475,20 @@ static void prepare_ss(struct pt_regs *regs)
 
 static int uprobe_handler(struct pt_regs *regs)
 {
-       struct kprobe *p;
-       kprobe_opcode_t *addr;
+       struct uprobe *p;
+       uprobe_opcode_t *addr;
        struct task_struct *task = current;
        pid_t tgid = task->tgid;
 
        save_current_flags(regs);
 
-       addr = (kprobe_opcode_t *)(regs->EREG(ip) - sizeof(kprobe_opcode_t));
-       p = get_ukprobe(addr, tgid);
+       addr = (uprobe_opcode_t *)(regs->EREG(ip) - sizeof(uprobe_opcode_t));
+       p = get_uprobe(addr, tgid);
 
        if (p == NULL) {
                void *tramp_addr = (void *)addr - UPROBES_TRAMP_RET_BREAK_IDX;
 
-               p = get_ukprobe_by_insn_slot(tramp_addr, tgid, regs);
+               p = get_uprobe_by_insn_slot(tramp_addr, tgid, regs);
                if (p == NULL) {
                        printk(KERN_INFO "no_uprobe\n");
                        return 0;
@@ -501,7 +515,7 @@ static int uprobe_handler(struct pt_regs *regs)
 
 static int post_uprobe_handler(struct pt_regs *regs)
 {
-       struct kprobe *p = get_current_probe();
+       struct uprobe *p = get_current_probe();
        unsigned long flags = current_ucb()->flags;
 
        if (p == NULL) {
@@ -561,7 +575,17 @@ static struct notifier_block uprobe_exceptions_nb = {
  */
 int swap_arch_init_uprobes(void)
 {
-       return register_die_notifier(&uprobe_exceptions_nb);
+       int ret;
+
+       ret = swap_td_raw_reg(&td_raw, sizeof(struct uprobe_ctlblk));
+       if (ret)
+               return ret;
+
+       ret = register_die_notifier(&uprobe_exceptions_nb);
+       if (ret)
+               swap_td_raw_unreg(&td_raw);
+
+       return ret;
 }
 
 /**
@@ -572,5 +596,6 @@ int swap_arch_init_uprobes(void)
 void swap_arch_exit_uprobes(void)
 {
        unregister_die_notifier(&uprobe_exceptions_nb);
+       swap_td_raw_unreg(&td_raw);
 }