+static int get_from_target(struct task_struct *target, unsigned long uaddr,
+ void *kbuf, int len)
+{
+ if (target == current) {
+ if (copy_from_user(kbuf, (void __user *) uaddr, len))
+ return -EFAULT;
+ } else {
+ int len2 = access_process_vm(target, uaddr, kbuf, len, 0);
+ if (len2 != len)
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int set_to_target(struct task_struct *target, unsigned long uaddr,
+ void *kbuf, int len)
+{
+ if (target == current) {
+ if (copy_to_user((void __user *) uaddr, kbuf, len))
+ return -EFAULT;
+ } else {
+ int len2 = access_process_vm(target, uaddr, kbuf, len, 1);
+ if (len2 != len)
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int regwindow64_get(struct task_struct *target,
+ const struct pt_regs *regs,
+ struct reg_window *wbuf)
+{
+ unsigned long rw_addr = regs->u_regs[UREG_I6];
+
+ if (test_tsk_thread_flag(current, TIF_32BIT)) {
+ struct reg_window32 win32;
+ int i;
+
+ if (get_from_target(target, rw_addr, &win32, sizeof(win32)))
+ return -EFAULT;
+ for (i = 0; i < 8; i++)
+ wbuf->locals[i] = win32.locals[i];
+ for (i = 0; i < 8; i++)
+ wbuf->ins[i] = win32.ins[i];
+ } else {
+ rw_addr += STACK_BIAS;
+ if (get_from_target(target, rw_addr, wbuf, sizeof(*wbuf)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int regwindow64_set(struct task_struct *target,
+ const struct pt_regs *regs,
+ struct reg_window *wbuf)
+{
+ unsigned long rw_addr = regs->u_regs[UREG_I6];
+
+ if (test_tsk_thread_flag(current, TIF_32BIT)) {
+ struct reg_window32 win32;
+ int i;
+
+ for (i = 0; i < 8; i++)
+ win32.locals[i] = wbuf->locals[i];
+ for (i = 0; i < 8; i++)
+ win32.ins[i] = wbuf->ins[i];
+
+ if (set_to_target(target, rw_addr, &win32, sizeof(win32)))
+ return -EFAULT;
+ } else {
+ rw_addr += STACK_BIAS;
+ if (set_to_target(target, rw_addr, wbuf, sizeof(*wbuf)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+