ARM64: Port swap_msg_pack_args() to 64-bits 21/111121/5
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 1 Nov 2016 12:03:11 +0000 (15:03 +0300)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>
Tue, 31 Jan 2017 07:21:26 +0000 (10:21 +0300)
Change-Id: If990d2d7f0a61838b141d7f9db45f19b9630900e
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
uprobe/arch/arm64/swap-asm/swap_uprobes.h
writer/swap_msg.c

index 744c2e1..0976fb5 100644 (file)
@@ -62,28 +62,135 @@ struct arch_insn {
 
 typedef u32 uprobe_opcode_t;
 
+static inline u32 swap_get_float(struct pt_regs *regs, unsigned long n)
+{
+       u32 *ptr;
+       register unsigned long w0 asm ("w0");
+
+       switch (n) {
+       case 0:
+               asm volatile("fmov w0, s0");
+               break;
+       case 1:
+               asm volatile("fmov w0, s1");
+               break;
+       case 2:
+               asm volatile("fmov w0, s2");
+               break;
+       case 3:
+               asm volatile("fmov w0, s3");
+               break;
+       case 4:
+               asm volatile("fmov w0, s4");
+               break;
+       case 5:
+               asm volatile("fmov w0, s5");
+               break;
+       case 6:
+               asm volatile("fmov w0, s6");
+               break;
+       case 7:
+               asm volatile("fmov w0, s7");
+               break;
+       default:
+               w0 = 0;
+               ptr = (u32 *)((u64 *)regs->sp + n - 8);
+               if (get_user(w0, ptr))
+                       pr_err("failed to dereference a pointer\n");
+
+               break;
+       }
+
+       return w0;
+}
+
+static inline u64 swap_get_double(struct pt_regs *regs, unsigned long n)
+{
+       u64 *ptr;
+       register unsigned long x0 asm ("x0");
+
+       switch (n) {
+       case 0:
+               asm volatile("fmov x0, d0");
+               break;
+       case 1:
+               asm volatile("fmov x0, d1");
+               break;
+       case 2:
+               asm volatile("fmov x0, d2");
+               break;
+       case 3:
+               asm volatile("fmov x0, d3");
+               break;
+       case 4:
+               asm volatile("fmov x0, d4");
+               break;
+       case 5:
+               asm volatile("fmov x0, d5");
+               break;
+       case 6:
+               asm volatile("fmov x0, d6");
+               break;
+       case 7:
+               asm volatile("fmov x0, d7");
+               break;
+       default:
+               x0 = 0;
+               ptr = (u64 *)regs->sp + n - 8;
+               if (get_user(x0, ptr))
+                       pr_err("failed to dereference a pointer\n");
+
+               break;
+       }
+
+       return x0;
+}
+
 static inline u32 swap_get_urp_float(struct pt_regs *regs)
 {
-       WARN(1, "not implemented"); /* FIXME: to implement */
-       return 0;
+       return swap_get_float(regs, 0);
 }
 
 static inline u64 swap_get_urp_double(struct pt_regs *regs)
 {
-       WARN(1, "not implemented"); /* FIXME: to implement */
-       return 0;
+       return swap_get_double(regs, 0);
 }
 
-static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
+static inline unsigned long swap_get_uarg_arm64(struct pt_regs *regs,
+                                               unsigned long n)
 {
-       if (compat_user_mode(regs)) {
-               return swap_get_uarg_arm(regs, n);
+       u64 *ptr, val;
+
+       if (n < 8)
+               return regs->regs[n];
+
+       ptr = (u64 *)regs->sp + n - 8;
+       if (get_user(val, ptr))
+               pr_err("failed to dereference a pointer, ptr=%p\n", ptr);
+
+       return val;
+}
+
+static inline void swap_put_uarg_arm64(struct pt_regs *regs, unsigned long n,
+                                      unsigned long val)
+{
+       if (n < 8) {
+               regs->regs[n] = val;
        } else {
-               WARN(1, "not implemented"); /* FIXME: to implement */
-               return 0x12345678;
+               u64 *ptr = (u64 *)regs->sp + n - 8;
+               if (put_user(val, ptr))
+                       pr_err("Failed to dereference a pointer, ptr=%p\n", ptr);
        }
 }
 
+static inline unsigned long swap_get_uarg(struct pt_regs *regs, unsigned long n)
+{
+       if (compat_user_mode(regs))
+               return swap_get_uarg_arm(regs, n);
+       else
+               return swap_get_uarg_arm64(regs, n);
+}
+
 static inline void swap_put_uarg(struct pt_regs *regs, unsigned long n,
                                 unsigned long val)
 {
index 81b3f0d..a965ee1 100644 (file)
@@ -338,6 +338,17 @@ int swap_msg_pack_args(char *buf, int len,
                        len -= 1;
                        break;
                case 'f': /* 4 byte(float) */
+#ifdef CONFIG_ARM64
+                       if (len < 4)
+                               return -ENOMEM;
+
+                       tmp_u32 = (u32 *)buf;
+                       *tmp_u32 = swap_get_float(regs, i);
+                       buf += 4;
+                       len -= 4;
+                       break;
+#endif /* CONFIG_ARM64 */
+                       /* For others case f == d */
                case 'd': /* 4 byte(int) */
                        if (len < 4)
                                return -ENOMEM;
@@ -359,9 +370,13 @@ int swap_msg_pack_args(char *buf, int len,
                        if (len < 8)
                                return -ENOMEM;
                        tmp_u64 = (u64 *)buf;
+#ifdef CONFIG_ARM64
+                       *tmp_u64 = swap_get_double(regs, i);
+#else /* CONFIG_ARM64 */
                        *tmp_u64 = get_arg(regs, i);
                        ++i;
                        *tmp_u64 |= (u64)get_arg(regs, i) << 32;
+#endif /* CONFIG_ARM64 */
                        buf += 8;
                        len -= 8;
                        break;