int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; int i; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; /* * Enforce that sigcontext is like pt_regs, and doesn't mess * up our stack alignment rules. */ BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs)); BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0); for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) err |= __get_user(regs->regs[i], &sc->gregs[i]); /* Ensure that the PL is always set to USER_PL. */ regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1)); regs->faultnum = INT_SWINT_1_SIGRETURN; return err; }
/* Put registers back to task. */ static void putregs(struct task_struct *child, struct pt_regs *uregs) { struct pt_regs *regs = task_pt_regs(child); /* Don't allow overwriting the kernel-internal flags word. */ uregs->flags = regs->flags; /* Only allow setting the ICS bit in the ex1 word. */ uregs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(uregs->ex1)); *regs = *uregs; }
/* Put registers back to task. */ static void putregs(struct task_struct *child, struct pt_regs *uregs) { struct pt_regs *regs = task_pt_regs(child); /* * Don't allow overwriting the kernel-internal flags word. * But do set PT_FLAGS_RESTORE_REGS so that the kernel will reload * all the callee-saved registers when returning to userspace. */ uregs->flags = regs->flags | PT_FLAGS_RESTORE_REGS; /* Only allow setting the ICS bit in the ex1 word. */ uregs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(uregs->ex1)); *regs = *uregs; }
int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err = 0; int i; current_thread_info()->restart_block.fn = do_no_restart_syscall; BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs)); BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0); for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) err |= __get_user(regs->regs[i], &sc->gregs[i]); regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1)); regs->faultnum = INT_SWINT_1_SIGRETURN; return err; }
int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) { int err; /* Always make any pending restarted system calls return -EINTR */ current->restart_block.fn = do_no_restart_syscall; /* * Enforce that sigcontext is like pt_regs, and doesn't mess * up our stack alignment rules. */ BUILD_BUG_ON(sizeof(struct sigcontext) != sizeof(struct pt_regs)); BUILD_BUG_ON(sizeof(struct sigcontext) % 8 != 0); err = __copy_from_user(regs, sc, sizeof(*regs)); /* Ensure that the PL is always set to USER_PL. */ regs->ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(regs->ex1)); regs->faultnum = INT_SWINT_1_SIGRETURN; return err; }
long arch_ptrace(struct task_struct *child, long request, unsigned long addr, unsigned long data) { unsigned long __user *datap = (long __user __force *)data; unsigned long tmp; long ret = -EIO; char *childreg; struct pt_regs copyregs; int ex1_offset; switch (request) { case PTRACE_PEEKUSR: /* */ if (addr >= PTREGS_SIZE) break; childreg = (char *)task_pt_regs(child) + addr; #ifdef CONFIG_COMPAT if (is_compat_task()) { if (addr & (sizeof(compat_long_t)-1)) break; ret = put_user(*(compat_long_t *)childreg, (compat_long_t __user *)datap); } else #endif { if (addr & (sizeof(long)-1)) break; ret = put_user(*(long *)childreg, datap); } break; case PTRACE_POKEUSR: /* */ if (addr >= PTREGS_SIZE) break; childreg = (char *)task_pt_regs(child) + addr; /* */ ex1_offset = PTREGS_OFFSET_EX1; #if defined(CONFIG_COMPAT) && defined(__BIG_ENDIAN) if (is_compat_task()) /* */ ex1_offset += sizeof(compat_long_t); #endif if (addr == ex1_offset) data = PL_ICS_EX1(USER_PL, EX1_ICS(data)); #ifdef CONFIG_COMPAT if (is_compat_task()) { if (addr & (sizeof(compat_long_t)-1)) break; *(compat_long_t *)childreg = data; } else #endif { if (addr & (sizeof(long)-1)) break; *(long *)childreg = data; } ret = 0; break; case PTRACE_GETREGS: /* */ if (copy_to_user(datap, task_pt_regs(child), sizeof(struct pt_regs)) == 0) { ret = 0; } break; case PTRACE_SETREGS: /* */ if (copy_from_user(©regs, datap, sizeof(struct pt_regs)) == 0) { copyregs.ex1 = PL_ICS_EX1(USER_PL, EX1_ICS(copyregs.ex1)); *task_pt_regs(child) = copyregs; ret = 0; } break; case PTRACE_GETFPREGS: /* */ case PTRACE_SETFPREGS: /* */ break; case PTRACE_SETOPTIONS: /* */ child->ptrace &= ~PT_TRACE_MASK_TILE; tmp = data & PTRACE_O_MASK_TILE; data &= ~PTRACE_O_MASK_TILE; ret = ptrace_request(child, request, addr, data); if (tmp & PTRACE_O_TRACEMIGRATE) child->ptrace |= PT_TRACE_MIGRATE; break; default: #ifdef CONFIG_COMPAT if (task_thread_info(current)->status & TS_COMPAT) { ret = compat_ptrace_request(child, request, addr, data); break; } #endif ret = ptrace_request(child, request, addr, data); break; } return ret; }