hc
2024-05-10 748e4f3d702def1a4bff191e0cf93b6a05340f01
kernel/arch/sparc/kernel/ptrace_32.c
....@@ -23,7 +23,6 @@
2323 #include <linux/elf.h>
2424 #include <linux/tracehook.h>
2525
26
-#include <asm/pgtable.h>
2726 #include <linux/uaccess.h>
2827 #include <asm/cacheflush.h>
2928
....@@ -84,41 +83,25 @@
8483
8584 static int genregs32_get(struct task_struct *target,
8685 const struct user_regset *regset,
87
- unsigned int pos, unsigned int count,
88
- void *kbuf, void __user *ubuf)
86
+ struct membuf to)
8987 {
9088 const struct pt_regs *regs = target->thread.kregs;
9189 u32 uregs[16];
92
- int ret;
9390
9491 if (target == current)
9592 flush_user_windows();
9693
97
- ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
98
- regs->u_regs,
99
- 0, 16 * sizeof(u32));
100
- if (ret || !count)
101
- return ret;
102
-
103
- if (pos < 32 * sizeof(u32)) {
104
- if (regwindow32_get(target, regs, uregs))
105
- return -EFAULT;
106
- ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
107
- uregs,
108
- 16 * sizeof(u32), 32 * sizeof(u32));
109
- if (ret || !count)
110
- return ret;
111
- }
112
-
113
- uregs[0] = regs->psr;
114
- uregs[1] = regs->pc;
115
- uregs[2] = regs->npc;
116
- uregs[3] = regs->y;
117
- uregs[4] = 0; /* WIM */
118
- uregs[5] = 0; /* TBR */
119
- return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
120
- uregs,
121
- 32 * sizeof(u32), 38 * sizeof(u32));
94
+ membuf_write(&to, regs->u_regs, 16 * sizeof(u32));
95
+ if (!to.left)
96
+ return 0;
97
+ if (regwindow32_get(target, regs, uregs))
98
+ return -EFAULT;
99
+ membuf_write(&to, uregs, 16 * sizeof(u32));
100
+ membuf_store(&to, regs->psr);
101
+ membuf_store(&to, regs->pc);
102
+ membuf_store(&to, regs->npc);
103
+ membuf_store(&to, regs->y);
104
+ return membuf_zero(&to, 2 * sizeof(u32));
122105 }
123106
124107 static int genregs32_set(struct task_struct *target,
....@@ -140,19 +123,18 @@
140123 if (ret || !count)
141124 return ret;
142125
143
- if (pos < 32 * sizeof(u32)) {
144
- if (regwindow32_get(target, regs, uregs))
145
- return -EFAULT;
146
- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
147
- uregs,
148
- 16 * sizeof(u32), 32 * sizeof(u32));
149
- if (ret)
150
- return ret;
151
- if (regwindow32_set(target, regs, uregs))
152
- return -EFAULT;
153
- if (!count)
154
- return 0;
155
- }
126
+ if (regwindow32_get(target, regs, uregs))
127
+ return -EFAULT;
128
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
129
+ uregs,
130
+ 16 * sizeof(u32), 32 * sizeof(u32));
131
+ if (ret)
132
+ return ret;
133
+ if (regwindow32_set(target, regs, uregs))
134
+ return -EFAULT;
135
+ if (!count)
136
+ return 0;
137
+
156138 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
157139 &psr,
158140 32 * sizeof(u32), 33 * sizeof(u32));
....@@ -183,46 +165,18 @@
183165
184166 static int fpregs32_get(struct task_struct *target,
185167 const struct user_regset *regset,
186
- unsigned int pos, unsigned int count,
187
- void *kbuf, void __user *ubuf)
168
+ struct membuf to)
188169 {
189
- const unsigned long *fpregs = target->thread.float_regs;
190
- int ret = 0;
191
-
192170 #if 0
193171 if (target == current)
194172 save_and_clear_fpu();
195173 #endif
196174
197
- ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
198
- fpregs,
199
- 0, 32 * sizeof(u32));
200
-
201
- if (!ret)
202
- ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
203
- 32 * sizeof(u32),
204
- 33 * sizeof(u32));
205
- if (!ret)
206
- ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
207
- &target->thread.fsr,
208
- 33 * sizeof(u32),
209
- 34 * sizeof(u32));
210
-
211
- if (!ret) {
212
- unsigned long val;
213
-
214
- val = (1 << 8) | (8 << 16);
215
- ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
216
- &val,
217
- 34 * sizeof(u32),
218
- 35 * sizeof(u32));
219
- }
220
-
221
- if (!ret)
222
- ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
223
- 35 * sizeof(u32), -1);
224
-
225
- return ret;
175
+ membuf_write(&to, target->thread.float_regs, 32 * sizeof(u32));
176
+ membuf_zero(&to, sizeof(u32));
177
+ membuf_write(&to, &target->thread.fsr, sizeof(u32));
178
+ membuf_store(&to, (u32)((1 << 8) | (8 << 16)));
179
+ return membuf_zero(&to, 64 * sizeof(u32));
226180 }
227181
228182 static int fpregs32_set(struct task_struct *target,
....@@ -244,13 +198,11 @@
244198 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
245199 32 * sizeof(u32),
246200 33 * sizeof(u32));
247
- if (!ret && count > 0) {
201
+ if (!ret)
248202 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
249203 &target->thread.fsr,
250204 33 * sizeof(u32),
251205 34 * sizeof(u32));
252
- }
253
-
254206 if (!ret)
255207 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
256208 34 * sizeof(u32), -1);
....@@ -269,7 +221,7 @@
269221 .core_note_type = NT_PRSTATUS,
270222 .n = 38,
271223 .size = sizeof(u32), .align = sizeof(u32),
272
- .get = genregs32_get, .set = genregs32_set
224
+ .regset_get = genregs32_get, .set = genregs32_set
273225 },
274226 /* Format is:
275227 * F0 --> F31
....@@ -285,8 +237,102 @@
285237 .core_note_type = NT_PRFPREG,
286238 .n = 99,
287239 .size = sizeof(u32), .align = sizeof(u32),
288
- .get = fpregs32_get, .set = fpregs32_set
240
+ .regset_get = fpregs32_get, .set = fpregs32_set
289241 },
242
+};
243
+
244
+static int getregs_get(struct task_struct *target,
245
+ const struct user_regset *regset,
246
+ struct membuf to)
247
+{
248
+ const struct pt_regs *regs = target->thread.kregs;
249
+
250
+ if (target == current)
251
+ flush_user_windows();
252
+
253
+ membuf_store(&to, regs->psr);
254
+ membuf_store(&to, regs->pc);
255
+ membuf_store(&to, regs->npc);
256
+ membuf_store(&to, regs->y);
257
+ return membuf_write(&to, regs->u_regs + 1, 15 * sizeof(u32));
258
+}
259
+
260
+static int setregs_set(struct task_struct *target,
261
+ const struct user_regset *regset,
262
+ unsigned int pos, unsigned int count,
263
+ const void *kbuf, const void __user *ubuf)
264
+{
265
+ struct pt_regs *regs = target->thread.kregs;
266
+ u32 v[4];
267
+ int ret;
268
+
269
+ if (target == current)
270
+ flush_user_windows();
271
+
272
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
273
+ v,
274
+ 0, 4 * sizeof(u32));
275
+ if (ret)
276
+ return ret;
277
+ regs->psr = (regs->psr & ~(PSR_ICC | PSR_SYSCALL)) |
278
+ (v[0] & (PSR_ICC | PSR_SYSCALL));
279
+ regs->pc = v[1];
280
+ regs->npc = v[2];
281
+ regs->y = v[3];
282
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
283
+ regs->u_regs + 1,
284
+ 4 * sizeof(u32) , 19 * sizeof(u32));
285
+}
286
+
287
+static int getfpregs_get(struct task_struct *target,
288
+ const struct user_regset *regset,
289
+ struct membuf to)
290
+{
291
+#if 0
292
+ if (target == current)
293
+ save_and_clear_fpu();
294
+#endif
295
+ membuf_write(&to, &target->thread.float_regs, 32 * sizeof(u32));
296
+ membuf_write(&to, &target->thread.fsr, sizeof(u32));
297
+ return membuf_zero(&to, 35 * sizeof(u32));
298
+}
299
+
300
+static int setfpregs_set(struct task_struct *target,
301
+ const struct user_regset *regset,
302
+ unsigned int pos, unsigned int count,
303
+ const void *kbuf, const void __user *ubuf)
304
+{
305
+ unsigned long *fpregs = target->thread.float_regs;
306
+ int ret;
307
+
308
+#if 0
309
+ if (target == current)
310
+ save_and_clear_fpu();
311
+#endif
312
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
313
+ fpregs,
314
+ 0, 32 * sizeof(u32));
315
+ if (ret)
316
+ return ret;
317
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
318
+ &target->thread.fsr,
319
+ 32 * sizeof(u32),
320
+ 33 * sizeof(u32));
321
+}
322
+
323
+static const struct user_regset ptrace32_regsets[] = {
324
+ [REGSET_GENERAL] = {
325
+ .n = 19, .size = sizeof(u32),
326
+ .regset_get = getregs_get, .set = setregs_set,
327
+ },
328
+ [REGSET_FP] = {
329
+ .n = 68, .size = sizeof(u32),
330
+ .regset_get = getfpregs_get, .set = setfpregs_set,
331
+ },
332
+};
333
+
334
+static const struct user_regset_view ptrace32_view = {
335
+ .regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
290336 };
291337
292338 static const struct user_regset_view user_sparc32_view = {
....@@ -316,74 +362,44 @@
316362 {
317363 unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
318364 void __user *addr2p;
319
- const struct user_regset_view *view;
320365 struct pt_regs __user *pregs;
321366 struct fps __user *fps;
322367 int ret;
323368
324
- view = task_user_regset_view(current);
325369 addr2p = (void __user *) addr2;
326370 pregs = (struct pt_regs __user *) addr;
327371 fps = (struct fps __user *) addr;
328372
329373 switch(request) {
330374 case PTRACE_GETREGS: {
331
- ret = copy_regset_to_user(child, view, REGSET_GENERAL,
332
- 32 * sizeof(u32),
333
- 4 * sizeof(u32),
334
- &pregs->psr);
335
- if (!ret)
336
- copy_regset_to_user(child, view, REGSET_GENERAL,
337
- 1 * sizeof(u32),
338
- 15 * sizeof(u32),
339
- &pregs->u_regs[0]);
375
+ ret = copy_regset_to_user(child, &ptrace32_view,
376
+ REGSET_GENERAL, 0,
377
+ 19 * sizeof(u32),
378
+ pregs);
340379 break;
341380 }
342381
343382 case PTRACE_SETREGS: {
344
- ret = copy_regset_from_user(child, view, REGSET_GENERAL,
345
- 32 * sizeof(u32),
346
- 4 * sizeof(u32),
347
- &pregs->psr);
348
- if (!ret)
349
- copy_regset_from_user(child, view, REGSET_GENERAL,
350
- 1 * sizeof(u32),
351
- 15 * sizeof(u32),
352
- &pregs->u_regs[0]);
383
+ ret = copy_regset_from_user(child, &ptrace32_view,
384
+ REGSET_GENERAL, 0,
385
+ 19 * sizeof(u32),
386
+ pregs);
353387 break;
354388 }
355389
356390 case PTRACE_GETFPREGS: {
357
- ret = copy_regset_to_user(child, view, REGSET_FP,
358
- 0 * sizeof(u32),
359
- 32 * sizeof(u32),
360
- &fps->regs[0]);
361
- if (!ret)
362
- ret = copy_regset_to_user(child, view, REGSET_FP,
363
- 33 * sizeof(u32),
364
- 1 * sizeof(u32),
365
- &fps->fsr);
366
-
367
- if (!ret) {
368
- if (__put_user(0, &fps->fpqd) ||
369
- __put_user(0, &fps->flags) ||
370
- __put_user(0, &fps->extra) ||
371
- clear_user(fps->fpq, sizeof(fps->fpq)))
372
- ret = -EFAULT;
373
- }
391
+ ret = copy_regset_to_user(child, &ptrace32_view,
392
+ REGSET_FP, 0,
393
+ 68 * sizeof(u32),
394
+ fps);
374395 break;
375396 }
376397
377398 case PTRACE_SETFPREGS: {
378
- ret = copy_regset_from_user(child, view, REGSET_FP,
379
- 0 * sizeof(u32),
380
- 32 * sizeof(u32),
381
- &fps->regs[0]);
382
- if (!ret)
383
- ret = copy_regset_from_user(child, view, REGSET_FP,
384
- 33 * sizeof(u32),
385
- 1 * sizeof(u32),
386
- &fps->fsr);
399
+ ret = copy_regset_from_user(child, &ptrace32_view,
400
+ REGSET_FP, 0,
401
+ 33 * sizeof(u32),
402
+ fps);
387403 break;
388404 }
389405