diff options
Diffstat (limited to 'arch')
-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 4edc1186f6a..d9b952faee7 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, |