Merge tag 'for-v5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/sre/linux-power...
[linux-2.6-microblaze.git] / arch / powerpc / kernel / ptrace / ptrace-view.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #include <linux/regset.h>
4 #include <linux/elf.h>
5 #include <linux/nospec.h>
6 #include <linux/pkeys.h>
7
8 #include "ptrace-decl.h"
9
10 struct pt_regs_offset {
11         const char *name;
12         int offset;
13 };
14
15 #define STR(s)  #s                      /* convert to string */
16 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
17 #define GPR_OFFSET_NAME(num)    \
18         {.name = STR(r##num), .offset = offsetof(struct pt_regs, gpr[num])}, \
19         {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])}
20 #define REG_OFFSET_END {.name = NULL, .offset = 0}
21
22 static const struct pt_regs_offset regoffset_table[] = {
23         GPR_OFFSET_NAME(0),
24         GPR_OFFSET_NAME(1),
25         GPR_OFFSET_NAME(2),
26         GPR_OFFSET_NAME(3),
27         GPR_OFFSET_NAME(4),
28         GPR_OFFSET_NAME(5),
29         GPR_OFFSET_NAME(6),
30         GPR_OFFSET_NAME(7),
31         GPR_OFFSET_NAME(8),
32         GPR_OFFSET_NAME(9),
33         GPR_OFFSET_NAME(10),
34         GPR_OFFSET_NAME(11),
35         GPR_OFFSET_NAME(12),
36         GPR_OFFSET_NAME(13),
37         GPR_OFFSET_NAME(14),
38         GPR_OFFSET_NAME(15),
39         GPR_OFFSET_NAME(16),
40         GPR_OFFSET_NAME(17),
41         GPR_OFFSET_NAME(18),
42         GPR_OFFSET_NAME(19),
43         GPR_OFFSET_NAME(20),
44         GPR_OFFSET_NAME(21),
45         GPR_OFFSET_NAME(22),
46         GPR_OFFSET_NAME(23),
47         GPR_OFFSET_NAME(24),
48         GPR_OFFSET_NAME(25),
49         GPR_OFFSET_NAME(26),
50         GPR_OFFSET_NAME(27),
51         GPR_OFFSET_NAME(28),
52         GPR_OFFSET_NAME(29),
53         GPR_OFFSET_NAME(30),
54         GPR_OFFSET_NAME(31),
55         REG_OFFSET_NAME(nip),
56         REG_OFFSET_NAME(msr),
57         REG_OFFSET_NAME(ctr),
58         REG_OFFSET_NAME(link),
59         REG_OFFSET_NAME(xer),
60         REG_OFFSET_NAME(ccr),
61 #ifdef CONFIG_PPC64
62         REG_OFFSET_NAME(softe),
63 #else
64         REG_OFFSET_NAME(mq),
65 #endif
66         REG_OFFSET_NAME(trap),
67         REG_OFFSET_NAME(dar),
68         REG_OFFSET_NAME(dsisr),
69         REG_OFFSET_END,
70 };
71
72 /**
73  * regs_query_register_offset() - query register offset from its name
74  * @name:       the name of a register
75  *
76  * regs_query_register_offset() returns the offset of a register in struct
77  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
78  */
79 int regs_query_register_offset(const char *name)
80 {
81         const struct pt_regs_offset *roff;
82         for (roff = regoffset_table; roff->name != NULL; roff++)
83                 if (!strcmp(roff->name, name))
84                         return roff->offset;
85         return -EINVAL;
86 }
87
88 /**
89  * regs_query_register_name() - query register name from its offset
90  * @offset:     the offset of a register in struct pt_regs.
91  *
92  * regs_query_register_name() returns the name of a register from its
93  * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
94  */
95 const char *regs_query_register_name(unsigned int offset)
96 {
97         const struct pt_regs_offset *roff;
98         for (roff = regoffset_table; roff->name != NULL; roff++)
99                 if (roff->offset == offset)
100                         return roff->name;
101         return NULL;
102 }
103
104 /*
105  * does not yet catch signals sent when the child dies.
106  * in exit.c or in signal.c.
107  */
108
109 static unsigned long get_user_msr(struct task_struct *task)
110 {
111         return task->thread.regs->msr | task->thread.fpexc_mode;
112 }
113
114 static int set_user_msr(struct task_struct *task, unsigned long msr)
115 {
116         task->thread.regs->msr &= ~MSR_DEBUGCHANGE;
117         task->thread.regs->msr |= msr & MSR_DEBUGCHANGE;
118         return 0;
119 }
120
121 #ifdef CONFIG_PPC64
122 static int get_user_dscr(struct task_struct *task, unsigned long *data)
123 {
124         *data = task->thread.dscr;
125         return 0;
126 }
127
128 static int set_user_dscr(struct task_struct *task, unsigned long dscr)
129 {
130         task->thread.dscr = dscr;
131         task->thread.dscr_inherit = 1;
132         return 0;
133 }
134 #else
135 static int get_user_dscr(struct task_struct *task, unsigned long *data)
136 {
137         return -EIO;
138 }
139
140 static int set_user_dscr(struct task_struct *task, unsigned long dscr)
141 {
142         return -EIO;
143 }
144 #endif
145
146 /*
147  * We prevent mucking around with the reserved area of trap
148  * which are used internally by the kernel.
149  */
150 static int set_user_trap(struct task_struct *task, unsigned long trap)
151 {
152         set_trap(task->thread.regs, trap);
153         return 0;
154 }
155
156 /*
157  * Get contents of register REGNO in task TASK.
158  */
159 int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
160 {
161         unsigned int regs_max;
162
163         if (task->thread.regs == NULL || !data)
164                 return -EIO;
165
166         if (regno == PT_MSR) {
167                 *data = get_user_msr(task);
168                 return 0;
169         }
170
171         if (regno == PT_DSCR)
172                 return get_user_dscr(task, data);
173
174         /*
175          * softe copies paca->irq_soft_mask variable state. Since irq_soft_mask is
176          * no more used as a flag, lets force usr to alway see the softe value as 1
177          * which means interrupts are not soft disabled.
178          */
179         if (IS_ENABLED(CONFIG_PPC64) && regno == PT_SOFTE) {
180                 *data = 1;
181                 return  0;
182         }
183
184         regs_max = sizeof(struct user_pt_regs) / sizeof(unsigned long);
185         if (regno < regs_max) {
186                 regno = array_index_nospec(regno, regs_max);
187                 *data = ((unsigned long *)task->thread.regs)[regno];
188                 return 0;
189         }
190
191         return -EIO;
192 }
193
194 /*
195  * Write contents of register REGNO in task TASK.
196  */
197 int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
198 {
199         if (task->thread.regs == NULL)
200                 return -EIO;
201
202         if (regno == PT_MSR)
203                 return set_user_msr(task, data);
204         if (regno == PT_TRAP)
205                 return set_user_trap(task, data);
206         if (regno == PT_DSCR)
207                 return set_user_dscr(task, data);
208
209         if (regno <= PT_MAX_PUT_REG) {
210                 regno = array_index_nospec(regno, PT_MAX_PUT_REG + 1);
211                 ((unsigned long *)task->thread.regs)[regno] = data;
212                 return 0;
213         }
214         return -EIO;
215 }
216
217 static int gpr_get(struct task_struct *target, const struct user_regset *regset,
218                    unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
219 {
220         int i, ret;
221
222         if (target->thread.regs == NULL)
223                 return -EIO;
224
225         if (!FULL_REGS(target->thread.regs)) {
226                 /* We have a partial register set.  Fill 14-31 with bogus values */
227                 for (i = 14; i < 32; i++)
228                         target->thread.regs->gpr[i] = NV_REG_POISON;
229         }
230
231         ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
232                                   target->thread.regs,
233                                   0, offsetof(struct pt_regs, msr));
234         if (!ret) {
235                 unsigned long msr = get_user_msr(target);
236                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr,
237                                           offsetof(struct pt_regs, msr),
238                                           offsetof(struct pt_regs, msr) +
239                                           sizeof(msr));
240         }
241
242         BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
243                      offsetof(struct pt_regs, msr) + sizeof(long));
244
245         if (!ret)
246                 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
247                                           &target->thread.regs->orig_gpr3,
248                                           offsetof(struct pt_regs, orig_gpr3),
249                                           sizeof(struct user_pt_regs));
250         if (!ret)
251                 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
252                                                sizeof(struct user_pt_regs), -1);
253
254         return ret;
255 }
256
257 static int gpr_set(struct task_struct *target, const struct user_regset *regset,
258                    unsigned int pos, unsigned int count, const void *kbuf,
259                    const void __user *ubuf)
260 {
261         unsigned long reg;
262         int ret;
263
264         if (target->thread.regs == NULL)
265                 return -EIO;
266
267         CHECK_FULL_REGS(target->thread.regs);
268
269         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
270                                  target->thread.regs,
271                                  0, PT_MSR * sizeof(reg));
272
273         if (!ret && count > 0) {
274                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
275                                          PT_MSR * sizeof(reg),
276                                          (PT_MSR + 1) * sizeof(reg));
277                 if (!ret)
278                         ret = set_user_msr(target, reg);
279         }
280
281         BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
282                      offsetof(struct pt_regs, msr) + sizeof(long));
283
284         if (!ret)
285                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
286                                          &target->thread.regs->orig_gpr3,
287                                          PT_ORIG_R3 * sizeof(reg),
288                                          (PT_MAX_PUT_REG + 1) * sizeof(reg));
289
290         if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
291                 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
292                                                 (PT_MAX_PUT_REG + 1) * sizeof(reg),
293                                                 PT_TRAP * sizeof(reg));
294
295         if (!ret && count > 0) {
296                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
297                                          PT_TRAP * sizeof(reg),
298                                          (PT_TRAP + 1) * sizeof(reg));
299                 if (!ret)
300                         ret = set_user_trap(target, reg);
301         }
302
303         if (!ret)
304                 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
305                                                 (PT_TRAP + 1) * sizeof(reg), -1);
306
307         return ret;
308 }
309
310 #ifdef CONFIG_PPC64
311 static int ppr_get(struct task_struct *target, const struct user_regset *regset,
312                    unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
313 {
314         return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
315                                    &target->thread.regs->ppr, 0, sizeof(u64));
316 }
317
318 static int ppr_set(struct task_struct *target, const struct user_regset *regset,
319                    unsigned int pos, unsigned int count, const void *kbuf,
320                    const void __user *ubuf)
321 {
322         return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
323                                   &target->thread.regs->ppr, 0, sizeof(u64));
324 }
325
326 static int dscr_get(struct task_struct *target, const struct user_regset *regset,
327                     unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
328 {
329         return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
330                                    &target->thread.dscr, 0, sizeof(u64));
331 }
332 static int dscr_set(struct task_struct *target, const struct user_regset *regset,
333                     unsigned int pos, unsigned int count, const void *kbuf,
334                     const void __user *ubuf)
335 {
336         return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
337                                   &target->thread.dscr, 0, sizeof(u64));
338 }
339 #endif
340 #ifdef CONFIG_PPC_BOOK3S_64
341 static int tar_get(struct task_struct *target, const struct user_regset *regset,
342                    unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
343 {
344         return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
345                                    &target->thread.tar, 0, sizeof(u64));
346 }
347 static int tar_set(struct task_struct *target, const struct user_regset *regset,
348                    unsigned int pos, unsigned int count, const void *kbuf,
349                    const void __user *ubuf)
350 {
351         return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
352                                   &target->thread.tar, 0, sizeof(u64));
353 }
354
355 static int ebb_active(struct task_struct *target, const struct user_regset *regset)
356 {
357         if (!cpu_has_feature(CPU_FTR_ARCH_207S))
358                 return -ENODEV;
359
360         if (target->thread.used_ebb)
361                 return regset->n;
362
363         return 0;
364 }
365
366 static int ebb_get(struct task_struct *target, const struct user_regset *regset,
367                    unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
368 {
369         /* Build tests */
370         BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
371         BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
372
373         if (!cpu_has_feature(CPU_FTR_ARCH_207S))
374                 return -ENODEV;
375
376         if (!target->thread.used_ebb)
377                 return -ENODATA;
378
379         return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr,
380                                    0, 3 * sizeof(unsigned long));
381 }
382
383 static int ebb_set(struct task_struct *target, const struct user_regset *regset,
384                    unsigned int pos, unsigned int count, const void *kbuf,
385                    const void __user *ubuf)
386 {
387         int ret = 0;
388
389         /* Build tests */
390         BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
391         BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
392
393         if (!cpu_has_feature(CPU_FTR_ARCH_207S))
394                 return -ENODEV;
395
396         if (target->thread.used_ebb)
397                 return -ENODATA;
398
399         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr,
400                                  0, sizeof(unsigned long));
401
402         if (!ret)
403                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
404                                          &target->thread.ebbhr, sizeof(unsigned long),
405                                          2 * sizeof(unsigned long));
406
407         if (!ret)
408                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
409                                          &target->thread.bescr, 2 * sizeof(unsigned long),
410                                          3 * sizeof(unsigned long));
411
412         return ret;
413 }
414 static int pmu_active(struct task_struct *target, const struct user_regset *regset)
415 {
416         if (!cpu_has_feature(CPU_FTR_ARCH_207S))
417                 return -ENODEV;
418
419         return regset->n;
420 }
421
422 static int pmu_get(struct task_struct *target, const struct user_regset *regset,
423                    unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
424 {
425         /* Build tests */
426         BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
427         BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
428         BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
429         BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
430
431         if (!cpu_has_feature(CPU_FTR_ARCH_207S))
432                 return -ENODEV;
433
434         return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.siar,
435                                    0, 5 * sizeof(unsigned long));
436 }
437
438 static int pmu_set(struct task_struct *target, const struct user_regset *regset,
439                    unsigned int pos, unsigned int count, const void *kbuf,
440                    const void __user *ubuf)
441 {
442         int ret = 0;
443
444         /* Build tests */
445         BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
446         BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
447         BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
448         BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
449
450         if (!cpu_has_feature(CPU_FTR_ARCH_207S))
451                 return -ENODEV;
452
453         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.siar,
454                                  0, sizeof(unsigned long));
455
456         if (!ret)
457                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
458                                          &target->thread.sdar, sizeof(unsigned long),
459                                          2 * sizeof(unsigned long));
460
461         if (!ret)
462                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
463                                          &target->thread.sier, 2 * sizeof(unsigned long),
464                                          3 * sizeof(unsigned long));
465
466         if (!ret)
467                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
468                                          &target->thread.mmcr2, 3 * sizeof(unsigned long),
469                                          4 * sizeof(unsigned long));
470
471         if (!ret)
472                 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
473                                          &target->thread.mmcr0, 4 * sizeof(unsigned long),
474                                          5 * sizeof(unsigned long));
475         return ret;
476 }
477 #endif
478
479 #ifdef CONFIG_PPC_MEM_KEYS
480 static int pkey_active(struct task_struct *target, const struct user_regset *regset)
481 {
482         if (!arch_pkeys_enabled())
483                 return -ENODEV;
484
485         return regset->n;
486 }
487
488 static int pkey_get(struct task_struct *target, const struct user_regset *regset,
489                     unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
490 {
491         BUILD_BUG_ON(TSO(amr) + sizeof(unsigned long) != TSO(iamr));
492         BUILD_BUG_ON(TSO(iamr) + sizeof(unsigned long) != TSO(uamor));
493
494         if (!arch_pkeys_enabled())
495                 return -ENODEV;
496
497         return user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.amr,
498                                    0, ELF_NPKEY * sizeof(unsigned long));
499 }
500
501 static int pkey_set(struct task_struct *target, const struct user_regset *regset,
502                     unsigned int pos, unsigned int count, const void *kbuf,
503                     const void __user *ubuf)
504 {
505         u64 new_amr;
506         int ret;
507
508         if (!arch_pkeys_enabled())
509                 return -ENODEV;
510
511         /* Only the AMR can be set from userspace */
512         if (pos != 0 || count != sizeof(new_amr))
513                 return -EINVAL;
514
515         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
516                                  &new_amr, 0, sizeof(new_amr));
517         if (ret)
518                 return ret;
519
520         /* UAMOR determines which bits of the AMR can be set from userspace. */
521         target->thread.amr = (new_amr & target->thread.uamor) |
522                              (target->thread.amr & ~target->thread.uamor);
523
524         return 0;
525 }
526 #endif /* CONFIG_PPC_MEM_KEYS */
527
528 static const struct user_regset native_regsets[] = {
529         [REGSET_GPR] = {
530                 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
531                 .size = sizeof(long), .align = sizeof(long),
532                 .get = gpr_get, .set = gpr_set
533         },
534         [REGSET_FPR] = {
535                 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
536                 .size = sizeof(double), .align = sizeof(double),
537                 .get = fpr_get, .set = fpr_set
538         },
539 #ifdef CONFIG_ALTIVEC
540         [REGSET_VMX] = {
541                 .core_note_type = NT_PPC_VMX, .n = 34,
542                 .size = sizeof(vector128), .align = sizeof(vector128),
543                 .active = vr_active, .get = vr_get, .set = vr_set
544         },
545 #endif
546 #ifdef CONFIG_VSX
547         [REGSET_VSX] = {
548                 .core_note_type = NT_PPC_VSX, .n = 32,
549                 .size = sizeof(double), .align = sizeof(double),
550                 .active = vsr_active, .get = vsr_get, .set = vsr_set
551         },
552 #endif
553 #ifdef CONFIG_SPE
554         [REGSET_SPE] = {
555                 .core_note_type = NT_PPC_SPE, .n = 35,
556                 .size = sizeof(u32), .align = sizeof(u32),
557                 .active = evr_active, .get = evr_get, .set = evr_set
558         },
559 #endif
560 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
561         [REGSET_TM_CGPR] = {
562                 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
563                 .size = sizeof(long), .align = sizeof(long),
564                 .active = tm_cgpr_active, .get = tm_cgpr_get, .set = tm_cgpr_set
565         },
566         [REGSET_TM_CFPR] = {
567                 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
568                 .size = sizeof(double), .align = sizeof(double),
569                 .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
570         },
571         [REGSET_TM_CVMX] = {
572                 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
573                 .size = sizeof(vector128), .align = sizeof(vector128),
574                 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
575         },
576         [REGSET_TM_CVSX] = {
577                 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
578                 .size = sizeof(double), .align = sizeof(double),
579                 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
580         },
581         [REGSET_TM_SPR] = {
582                 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
583                 .size = sizeof(u64), .align = sizeof(u64),
584                 .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
585         },
586         [REGSET_TM_CTAR] = {
587                 .core_note_type = NT_PPC_TM_CTAR, .n = 1,
588                 .size = sizeof(u64), .align = sizeof(u64),
589                 .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set
590         },
591         [REGSET_TM_CPPR] = {
592                 .core_note_type = NT_PPC_TM_CPPR, .n = 1,
593                 .size = sizeof(u64), .align = sizeof(u64),
594                 .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set
595         },
596         [REGSET_TM_CDSCR] = {
597                 .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
598                 .size = sizeof(u64), .align = sizeof(u64),
599                 .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set
600         },
601 #endif
602 #ifdef CONFIG_PPC64
603         [REGSET_PPR] = {
604                 .core_note_type = NT_PPC_PPR, .n = 1,
605                 .size = sizeof(u64), .align = sizeof(u64),
606                 .get = ppr_get, .set = ppr_set
607         },
608         [REGSET_DSCR] = {
609                 .core_note_type = NT_PPC_DSCR, .n = 1,
610                 .size = sizeof(u64), .align = sizeof(u64),
611                 .get = dscr_get, .set = dscr_set
612         },
613 #endif
614 #ifdef CONFIG_PPC_BOOK3S_64
615         [REGSET_TAR] = {
616                 .core_note_type = NT_PPC_TAR, .n = 1,
617                 .size = sizeof(u64), .align = sizeof(u64),
618                 .get = tar_get, .set = tar_set
619         },
620         [REGSET_EBB] = {
621                 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
622                 .size = sizeof(u64), .align = sizeof(u64),
623                 .active = ebb_active, .get = ebb_get, .set = ebb_set
624         },
625         [REGSET_PMR] = {
626                 .core_note_type = NT_PPC_PMU, .n = ELF_NPMU,
627                 .size = sizeof(u64), .align = sizeof(u64),
628                 .active = pmu_active, .get = pmu_get, .set = pmu_set
629         },
630 #endif
631 #ifdef CONFIG_PPC_MEM_KEYS
632         [REGSET_PKEY] = {
633                 .core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY,
634                 .size = sizeof(u64), .align = sizeof(u64),
635                 .active = pkey_active, .get = pkey_get, .set = pkey_set
636         },
637 #endif
638 };
639
640 const struct user_regset_view user_ppc_native_view = {
641         .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
642         .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
643 };
644
645 #include <linux/compat.h>
646
647 int gpr32_get_common(struct task_struct *target,
648                      const struct user_regset *regset,
649                      unsigned int pos, unsigned int count,
650                             void *kbuf, void __user *ubuf,
651                             unsigned long *regs)
652 {
653         compat_ulong_t *k = kbuf;
654         compat_ulong_t __user *u = ubuf;
655         compat_ulong_t reg;
656
657         pos /= sizeof(reg);
658         count /= sizeof(reg);
659
660         if (kbuf)
661                 for (; count > 0 && pos < PT_MSR; --count)
662                         *k++ = regs[pos++];
663         else
664                 for (; count > 0 && pos < PT_MSR; --count)
665                         if (__put_user((compat_ulong_t)regs[pos++], u++))
666                                 return -EFAULT;
667
668         if (count > 0 && pos == PT_MSR) {
669                 reg = get_user_msr(target);
670                 if (kbuf)
671                         *k++ = reg;
672                 else if (__put_user(reg, u++))
673                         return -EFAULT;
674                 ++pos;
675                 --count;
676         }
677
678         if (kbuf)
679                 for (; count > 0 && pos < PT_REGS_COUNT; --count)
680                         *k++ = regs[pos++];
681         else
682                 for (; count > 0 && pos < PT_REGS_COUNT; --count)
683                         if (__put_user((compat_ulong_t)regs[pos++], u++))
684                                 return -EFAULT;
685
686         kbuf = k;
687         ubuf = u;
688         pos *= sizeof(reg);
689         count *= sizeof(reg);
690         return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
691                                         PT_REGS_COUNT * sizeof(reg), -1);
692 }
693
694 int gpr32_set_common(struct task_struct *target,
695                      const struct user_regset *regset,
696                      unsigned int pos, unsigned int count,
697                      const void *kbuf, const void __user *ubuf,
698                      unsigned long *regs)
699 {
700         const compat_ulong_t *k = kbuf;
701         const compat_ulong_t __user *u = ubuf;
702         compat_ulong_t reg;
703
704         pos /= sizeof(reg);
705         count /= sizeof(reg);
706
707         if (kbuf)
708                 for (; count > 0 && pos < PT_MSR; --count)
709                         regs[pos++] = *k++;
710         else
711                 for (; count > 0 && pos < PT_MSR; --count) {
712                         if (__get_user(reg, u++))
713                                 return -EFAULT;
714                         regs[pos++] = reg;
715                 }
716
717
718         if (count > 0 && pos == PT_MSR) {
719                 if (kbuf)
720                         reg = *k++;
721                 else if (__get_user(reg, u++))
722                         return -EFAULT;
723                 set_user_msr(target, reg);
724                 ++pos;
725                 --count;
726         }
727
728         if (kbuf) {
729                 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count)
730                         regs[pos++] = *k++;
731                 for (; count > 0 && pos < PT_TRAP; --count, ++pos)
732                         ++k;
733         } else {
734                 for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
735                         if (__get_user(reg, u++))
736                                 return -EFAULT;
737                         regs[pos++] = reg;
738                 }
739                 for (; count > 0 && pos < PT_TRAP; --count, ++pos)
740                         if (__get_user(reg, u++))
741                                 return -EFAULT;
742         }
743
744         if (count > 0 && pos == PT_TRAP) {
745                 if (kbuf)
746                         reg = *k++;
747                 else if (__get_user(reg, u++))
748                         return -EFAULT;
749                 set_user_trap(target, reg);
750                 ++pos;
751                 --count;
752         }
753
754         kbuf = k;
755         ubuf = u;
756         pos *= sizeof(reg);
757         count *= sizeof(reg);
758         return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
759                                          (PT_TRAP + 1) * sizeof(reg), -1);
760 }
761
762 static int gpr32_get(struct task_struct *target,
763                      const struct user_regset *regset,
764                      unsigned int pos, unsigned int count,
765                      void *kbuf, void __user *ubuf)
766 {
767         int i;
768
769         if (target->thread.regs == NULL)
770                 return -EIO;
771
772         if (!FULL_REGS(target->thread.regs)) {
773                 /*
774                  * We have a partial register set.
775                  * Fill 14-31 with bogus values.
776                  */
777                 for (i = 14; i < 32; i++)
778                         target->thread.regs->gpr[i] = NV_REG_POISON;
779         }
780         return gpr32_get_common(target, regset, pos, count, kbuf, ubuf,
781                         &target->thread.regs->gpr[0]);
782 }
783
784 static int gpr32_set(struct task_struct *target,
785                      const struct user_regset *regset,
786                      unsigned int pos, unsigned int count,
787                      const void *kbuf, const void __user *ubuf)
788 {
789         if (target->thread.regs == NULL)
790                 return -EIO;
791
792         CHECK_FULL_REGS(target->thread.regs);
793         return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
794                         &target->thread.regs->gpr[0]);
795 }
796
797 /*
798  * These are the regset flavors matching the CONFIG_PPC32 native set.
799  */
800 static const struct user_regset compat_regsets[] = {
801         [REGSET_GPR] = {
802                 .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
803                 .size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
804                 .get = gpr32_get, .set = gpr32_set
805         },
806         [REGSET_FPR] = {
807                 .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
808                 .size = sizeof(double), .align = sizeof(double),
809                 .get = fpr_get, .set = fpr_set
810         },
811 #ifdef CONFIG_ALTIVEC
812         [REGSET_VMX] = {
813                 .core_note_type = NT_PPC_VMX, .n = 34,
814                 .size = sizeof(vector128), .align = sizeof(vector128),
815                 .active = vr_active, .get = vr_get, .set = vr_set
816         },
817 #endif
818 #ifdef CONFIG_SPE
819         [REGSET_SPE] = {
820                 .core_note_type = NT_PPC_SPE, .n = 35,
821                 .size = sizeof(u32), .align = sizeof(u32),
822                 .active = evr_active, .get = evr_get, .set = evr_set
823         },
824 #endif
825 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
826         [REGSET_TM_CGPR] = {
827                 .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
828                 .size = sizeof(long), .align = sizeof(long),
829                 .active = tm_cgpr_active,
830                 .get = tm_cgpr32_get, .set = tm_cgpr32_set
831         },
832         [REGSET_TM_CFPR] = {
833                 .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
834                 .size = sizeof(double), .align = sizeof(double),
835                 .active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
836         },
837         [REGSET_TM_CVMX] = {
838                 .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
839                 .size = sizeof(vector128), .align = sizeof(vector128),
840                 .active = tm_cvmx_active, .get = tm_cvmx_get, .set = tm_cvmx_set
841         },
842         [REGSET_TM_CVSX] = {
843                 .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
844                 .size = sizeof(double), .align = sizeof(double),
845                 .active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
846         },
847         [REGSET_TM_SPR] = {
848                 .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
849                 .size = sizeof(u64), .align = sizeof(u64),
850                 .active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
851         },
852         [REGSET_TM_CTAR] = {
853                 .core_note_type = NT_PPC_TM_CTAR, .n = 1,
854                 .size = sizeof(u64), .align = sizeof(u64),
855                 .active = tm_tar_active, .get = tm_tar_get, .set = tm_tar_set
856         },
857         [REGSET_TM_CPPR] = {
858                 .core_note_type = NT_PPC_TM_CPPR, .n = 1,
859                 .size = sizeof(u64), .align = sizeof(u64),
860                 .active = tm_ppr_active, .get = tm_ppr_get, .set = tm_ppr_set
861         },
862         [REGSET_TM_CDSCR] = {
863                 .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
864                 .size = sizeof(u64), .align = sizeof(u64),
865                 .active = tm_dscr_active, .get = tm_dscr_get, .set = tm_dscr_set
866         },
867 #endif
868 #ifdef CONFIG_PPC64
869         [REGSET_PPR] = {
870                 .core_note_type = NT_PPC_PPR, .n = 1,
871                 .size = sizeof(u64), .align = sizeof(u64),
872                 .get = ppr_get, .set = ppr_set
873         },
874         [REGSET_DSCR] = {
875                 .core_note_type = NT_PPC_DSCR, .n = 1,
876                 .size = sizeof(u64), .align = sizeof(u64),
877                 .get = dscr_get, .set = dscr_set
878         },
879 #endif
880 #ifdef CONFIG_PPC_BOOK3S_64
881         [REGSET_TAR] = {
882                 .core_note_type = NT_PPC_TAR, .n = 1,
883                 .size = sizeof(u64), .align = sizeof(u64),
884                 .get = tar_get, .set = tar_set
885         },
886         [REGSET_EBB] = {
887                 .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
888                 .size = sizeof(u64), .align = sizeof(u64),
889                 .active = ebb_active, .get = ebb_get, .set = ebb_set
890         },
891 #endif
892 };
893
894 static const struct user_regset_view user_ppc_compat_view = {
895         .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI,
896         .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets)
897 };
898
899 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
900 {
901         if (IS_ENABLED(CONFIG_PPC64) && test_tsk_thread_flag(task, TIF_32BIT))
902                 return &user_ppc_compat_view;
903         return &user_ppc_native_view;
904 }