Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
[linux-drm-fsl-dcu.git] / arch / s390 / kernel / kprobes.c
index 67914fe7f317cb6be4b9e864816e3020f8596e4f..a466bab6677e15f506da1fb3d8168d5792170167 100644 (file)
@@ -155,15 +155,34 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
 static int __kprobes swap_instruction(void *aref)
 {
        struct ins_replace_args *args = aref;
+       u32 *addr;
+       u32 instr;
        int err = -EFAULT;
 
+       /*
+        * Text segment is read-only, hence we use stura to bypass dynamic
+        * address translation to exchange the instruction. Since stura
+        * always operates on four bytes, but we only want to exchange two
+        * bytes do some calculations to get things right. In addition we
+        * shall not cross any page boundaries (vmalloc area!) when writing
+        * the new instruction.
+        */
+       addr = (u32 *)ALIGN((unsigned long)args->ptr, 4);
+       if ((unsigned long)args->ptr & 2)
+               instr = ((*addr) & 0xffff0000) | args->new;
+       else
+               instr = ((*addr) & 0x0000ffff) | args->new << 16;
+
        asm volatile(
-               "0: mvc  0(2,%2),0(%3)\n"
-               "1: la   %0,0\n"
+               "       lra     %1,0(%1)\n"
+               "0:     stura   %2,%1\n"
+               "1:     la      %0,0\n"
                "2:\n"
                EX_TABLE(0b,2b)
-               : "+d" (err), "=m" (*args->ptr)
-               : "a" (args->ptr), "a" (&args->new), "m" (args->new));
+               : "+d" (err)
+               : "a" (addr), "d" (instr)
+               : "memory", "cc");
+
        return err;
 }
 
@@ -200,7 +219,7 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p)
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
        mutex_lock(&kprobe_mutex);
-       free_insn_slot(p->ainsn.insn);
+       free_insn_slot(p->ainsn.insn, 0);
        mutex_unlock(&kprobe_mutex);
 }
 
@@ -356,7 +375,7 @@ no_kprobe:
  *     - When the probed function returns, this probe
  *             causes the handlers to fire
  */
-void __kprobes kretprobe_trampoline_holder(void)
+void kretprobe_trampoline_holder(void)
 {
        asm volatile(".global kretprobe_trampoline\n"
                     "kretprobe_trampoline: bcr 0,0\n");
@@ -365,7 +384,8 @@ void __kprobes kretprobe_trampoline_holder(void)
 /*
  * Called when the probe at kretprobe trampoline is hit
  */
-int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+static int __kprobes trampoline_probe_handler(struct kprobe *p,
+                                             struct pt_regs *regs)
 {
        struct kretprobe_instance *ri = NULL;
        struct hlist_head *head, empty_rp;