diff options
| author | Roland McGrath <roland@redhat.com> | 2007-12-20 06:57:55 -0500 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2008-02-07 04:38:57 -0500 |
| commit | 44dd3f50d3848e332b49e83a142b39b960ec962e (patch) | |
| tree | 7ac549d6292129bb638106dac03eb938122a652b | |
| parent | 26f7713020129e556e494fd36b2db1e651e33ba3 (diff) | |
[POWERPC] Use user_regset accessors for GPRs
This implements user_regset-style accessors for the powerpc general
registers. In the future these functions will be the only place that
needs to understand the user_regset layout (core dump format) and how
it maps to the internal representation of user thread state.
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
| -rw-r--r-- | arch/powerpc/kernel/ptrace.c | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 4edc1186f6ac..d9b952faee73 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -119,6 +119,97 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data) | |||
| 119 | return -EIO; | 119 | return -EIO; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static int gpr_get(struct task_struct *target, const struct user_regset *regset, | ||
| 123 | unsigned int pos, unsigned int count, | ||
| 124 | void *kbuf, void __user *ubuf) | ||
| 125 | { | ||
| 126 | int ret; | ||
| 127 | |||
| 128 | if (target->thread.regs == NULL) | ||
| 129 | return -EIO; | ||
| 130 | |||
| 131 | CHECK_FULL_REGS(target->thread.regs); | ||
| 132 | |||
| 133 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
| 134 | target->thread.regs, | ||
| 135 | 0, offsetof(struct pt_regs, msr)); | ||
| 136 | if (!ret) { | ||
| 137 | unsigned long msr = get_user_msr(target); | ||
| 138 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr, | ||
| 139 | offsetof(struct pt_regs, msr), | ||
| 140 | offsetof(struct pt_regs, msr) + | ||
| 141 | sizeof(msr)); | ||
| 142 | } | ||
| 143 | |||
| 144 | BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != | ||
| 145 | offsetof(struct pt_regs, msr) + sizeof(long)); | ||
| 146 | |||
| 147 | if (!ret) | ||
| 148 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
| 149 | &target->thread.regs->orig_gpr3, | ||
| 150 | offsetof(struct pt_regs, orig_gpr3), | ||
| 151 | sizeof(struct pt_regs)); | ||
| 152 | if (!ret) | ||
| 153 | ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, | ||
| 154 | sizeof(struct pt_regs), -1); | ||
| 155 | |||
| 156 | return ret; | ||
| 157 | } | ||
| 158 | |||
| 159 | static int gpr_set(struct task_struct *target, const struct user_regset *regset, | ||
| 160 | unsigned int pos, unsigned int count, | ||
| 161 | const void *kbuf, const void __user *ubuf) | ||
| 162 | { | ||
| 163 | unsigned long reg; | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | if (target->thread.regs == NULL) | ||
| 167 | return -EIO; | ||
| 168 | |||
| 169 | CHECK_FULL_REGS(target->thread.regs); | ||
| 170 | |||
| 171 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
| 172 | target->thread.regs, | ||
| 173 | 0, PT_MSR * sizeof(reg)); | ||
| 174 | |||
| 175 | if (!ret && count > 0) { | ||
| 176 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, | ||
| 177 | PT_MSR * sizeof(reg), | ||
| 178 | (PT_MSR + 1) * sizeof(reg)); | ||
| 179 | if (!ret) | ||
| 180 | ret = set_user_msr(target, reg); | ||
| 181 | } | ||
| 182 | |||
| 183 | BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != | ||
| 184 | offsetof(struct pt_regs, msr) + sizeof(long)); | ||
| 185 | |||
| 186 | if (!ret) | ||
| 187 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
| 188 | &target->thread.regs->orig_gpr3, | ||
| 189 | PT_ORIG_R3 * sizeof(reg), | ||
| 190 | (PT_MAX_PUT_REG + 1) * sizeof(reg)); | ||
| 191 | |||
| 192 | if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret) | ||
| 193 | ret = user_regset_copyin_ignore( | ||
| 194 | &pos, &count, &kbuf, &ubuf, | ||
| 195 | (PT_MAX_PUT_REG + 1) * sizeof(reg), | ||
| 196 | PT_TRAP * sizeof(reg)); | ||
| 197 | |||
| 198 | if (!ret && count > 0) { | ||
| 199 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®, | ||
| 200 | PT_TRAP * sizeof(reg), | ||
| 201 | (PT_TRAP + 1) * sizeof(reg)); | ||
| 202 | if (!ret) | ||
| 203 | ret = set_user_trap(target, reg); | ||
| 204 | } | ||
| 205 | |||
| 206 | if (!ret) | ||
| 207 | ret = user_regset_copyin_ignore( | ||
| 208 | &pos, &count, &kbuf, &ubuf, | ||
| 209 | (PT_TRAP + 1) * sizeof(reg), -1); | ||
| 210 | |||
| 211 | return ret; | ||
| 212 | } | ||
| 122 | 213 | ||
| 123 | static int fpr_get(struct task_struct *target, const struct user_regset *regset, | 214 | static int fpr_get(struct task_struct *target, const struct user_regset *regset, |
| 124 | unsigned int pos, unsigned int count, | 215 | unsigned int pos, unsigned int count, |
