1 // SPDX-License-Identifier: GPL-2.0-or-later
3 #include <linux/regset.h>
5 #include <linux/nospec.h>
6 #include <linux/pkeys.h>
8 #include "ptrace-decl.h"
10 struct pt_regs_offset
{
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}
22 static const struct pt_regs_offset regoffset_table
[] = {
58 REG_OFFSET_NAME(link
),
62 REG_OFFSET_NAME(softe
),
66 REG_OFFSET_NAME(trap
),
68 REG_OFFSET_NAME(dsisr
),
73 * regs_query_register_offset() - query register offset from its name
74 * @name: the name of a register
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;
79 int regs_query_register_offset(const char *name
)
81 const struct pt_regs_offset
*roff
;
82 for (roff
= regoffset_table
; roff
->name
!= NULL
; roff
++)
83 if (!strcmp(roff
->name
, name
))
89 * regs_query_register_name() - query register name from its offset
90 * @offset: the offset of a register in struct pt_regs.
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;
95 const char *regs_query_register_name(unsigned int offset
)
97 const struct pt_regs_offset
*roff
;
98 for (roff
= regoffset_table
; roff
->name
!= NULL
; roff
++)
99 if (roff
->offset
== offset
)
105 * does not yet catch signals sent when the child dies.
106 * in exit.c or in signal.c.
109 static unsigned long get_user_msr(struct task_struct
*task
)
111 return task
->thread
.regs
->msr
| task
->thread
.fpexc_mode
;
114 static int set_user_msr(struct task_struct
*task
, unsigned long msr
)
116 task
->thread
.regs
->msr
&= ~MSR_DEBUGCHANGE
;
117 task
->thread
.regs
->msr
|= msr
& MSR_DEBUGCHANGE
;
122 static int get_user_dscr(struct task_struct
*task
, unsigned long *data
)
124 *data
= task
->thread
.dscr
;
128 static int set_user_dscr(struct task_struct
*task
, unsigned long dscr
)
130 task
->thread
.dscr
= dscr
;
131 task
->thread
.dscr_inherit
= 1;
135 static int get_user_dscr(struct task_struct
*task
, unsigned long *data
)
140 static int set_user_dscr(struct task_struct
*task
, unsigned long dscr
)
147 * We prevent mucking around with the reserved area of trap
148 * which are used internally by the kernel.
150 static int set_user_trap(struct task_struct
*task
, unsigned long trap
)
152 set_trap(task
->thread
.regs
, trap
);
157 * Get contents of register REGNO in task TASK.
159 int ptrace_get_reg(struct task_struct
*task
, int regno
, unsigned long *data
)
161 unsigned int regs_max
;
163 if (task
->thread
.regs
== NULL
|| !data
)
166 if (regno
== PT_MSR
) {
167 *data
= get_user_msr(task
);
171 if (regno
== PT_DSCR
)
172 return get_user_dscr(task
, data
);
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.
179 if (IS_ENABLED(CONFIG_PPC64
) && regno
== PT_SOFTE
) {
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
];
195 * Write contents of register REGNO in task TASK.
197 int ptrace_put_reg(struct task_struct
*task
, int regno
, unsigned long data
)
199 if (task
->thread
.regs
== NULL
)
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
);
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
;
217 static int gpr_get(struct task_struct
*target
, const struct user_regset
*regset
,
220 struct membuf to_msr
= membuf_at(&to
, offsetof(struct pt_regs
, msr
));
222 struct membuf to_softe
= membuf_at(&to
, offsetof(struct pt_regs
, softe
));
226 if (target
->thread
.regs
== NULL
)
229 if (!FULL_REGS(target
->thread
.regs
)) {
230 /* We have a partial register set. Fill 14-31 with bogus values */
231 for (i
= 14; i
< 32; i
++)
232 target
->thread
.regs
->gpr
[i
] = NV_REG_POISON
;
235 membuf_write(&to
, target
->thread
.regs
, sizeof(struct user_pt_regs
));
237 membuf_store(&to_msr
, get_user_msr(target
));
239 membuf_store(&to_softe
, 0x1ul
);
241 return membuf_zero(&to
, ELF_NGREG
* sizeof(unsigned long) -
242 sizeof(struct user_pt_regs
));
245 static int gpr_set(struct task_struct
*target
, const struct user_regset
*regset
,
246 unsigned int pos
, unsigned int count
, const void *kbuf
,
247 const void __user
*ubuf
)
252 if (target
->thread
.regs
== NULL
)
255 CHECK_FULL_REGS(target
->thread
.regs
);
257 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
259 0, PT_MSR
* sizeof(reg
));
261 if (!ret
&& count
> 0) {
262 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, ®
,
263 PT_MSR
* sizeof(reg
),
264 (PT_MSR
+ 1) * sizeof(reg
));
266 ret
= set_user_msr(target
, reg
);
269 BUILD_BUG_ON(offsetof(struct pt_regs
, orig_gpr3
) !=
270 offsetof(struct pt_regs
, msr
) + sizeof(long));
273 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
274 &target
->thread
.regs
->orig_gpr3
,
275 PT_ORIG_R3
* sizeof(reg
),
276 (PT_MAX_PUT_REG
+ 1) * sizeof(reg
));
278 if (PT_MAX_PUT_REG
+ 1 < PT_TRAP
&& !ret
)
279 ret
= user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
280 (PT_MAX_PUT_REG
+ 1) * sizeof(reg
),
281 PT_TRAP
* sizeof(reg
));
283 if (!ret
&& count
> 0) {
284 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, ®
,
285 PT_TRAP
* sizeof(reg
),
286 (PT_TRAP
+ 1) * sizeof(reg
));
288 ret
= set_user_trap(target
, reg
);
292 ret
= user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
293 (PT_TRAP
+ 1) * sizeof(reg
), -1);
299 static int ppr_get(struct task_struct
*target
, const struct user_regset
*regset
,
302 return membuf_write(&to
, &target
->thread
.regs
->ppr
, sizeof(u64
));
305 static int ppr_set(struct task_struct
*target
, const struct user_regset
*regset
,
306 unsigned int pos
, unsigned int count
, const void *kbuf
,
307 const void __user
*ubuf
)
309 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
310 &target
->thread
.regs
->ppr
, 0, sizeof(u64
));
313 static int dscr_get(struct task_struct
*target
, const struct user_regset
*regset
,
316 return membuf_write(&to
, &target
->thread
.dscr
, sizeof(u64
));
318 static int dscr_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
)
322 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
323 &target
->thread
.dscr
, 0, sizeof(u64
));
326 #ifdef CONFIG_PPC_BOOK3S_64
327 static int tar_get(struct task_struct
*target
, const struct user_regset
*regset
,
330 return membuf_write(&to
, &target
->thread
.tar
, sizeof(u64
));
332 static int tar_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
)
336 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
337 &target
->thread
.tar
, 0, sizeof(u64
));
340 static int ebb_active(struct task_struct
*target
, const struct user_regset
*regset
)
342 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
345 if (target
->thread
.used_ebb
)
351 static int ebb_get(struct task_struct
*target
, const struct user_regset
*regset
,
355 BUILD_BUG_ON(TSO(ebbrr
) + sizeof(unsigned long) != TSO(ebbhr
));
356 BUILD_BUG_ON(TSO(ebbhr
) + sizeof(unsigned long) != TSO(bescr
));
358 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
361 if (!target
->thread
.used_ebb
)
364 return membuf_write(&to
, &target
->thread
.ebbrr
, 3 * sizeof(unsigned long));
367 static int ebb_set(struct task_struct
*target
, const struct user_regset
*regset
,
368 unsigned int pos
, unsigned int count
, const void *kbuf
,
369 const void __user
*ubuf
)
374 BUILD_BUG_ON(TSO(ebbrr
) + sizeof(unsigned long) != TSO(ebbhr
));
375 BUILD_BUG_ON(TSO(ebbhr
) + sizeof(unsigned long) != TSO(bescr
));
377 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
380 if (target
->thread
.used_ebb
)
383 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, &target
->thread
.ebbrr
,
384 0, sizeof(unsigned long));
387 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
388 &target
->thread
.ebbhr
, sizeof(unsigned long),
389 2 * sizeof(unsigned long));
392 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
393 &target
->thread
.bescr
, 2 * sizeof(unsigned long),
394 3 * sizeof(unsigned long));
398 static int pmu_active(struct task_struct
*target
, const struct user_regset
*regset
)
400 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
406 static int pmu_get(struct task_struct
*target
, const struct user_regset
*regset
,
410 BUILD_BUG_ON(TSO(siar
) + sizeof(unsigned long) != TSO(sdar
));
411 BUILD_BUG_ON(TSO(sdar
) + sizeof(unsigned long) != TSO(sier
));
412 BUILD_BUG_ON(TSO(sier
) + sizeof(unsigned long) != TSO(mmcr2
));
413 BUILD_BUG_ON(TSO(mmcr2
) + sizeof(unsigned long) != TSO(mmcr0
));
415 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
418 return membuf_write(&to
, &target
->thread
.siar
, 5 * sizeof(unsigned long));
421 static int pmu_set(struct task_struct
*target
, const struct user_regset
*regset
,
422 unsigned int pos
, unsigned int count
, const void *kbuf
,
423 const void __user
*ubuf
)
428 BUILD_BUG_ON(TSO(siar
) + sizeof(unsigned long) != TSO(sdar
));
429 BUILD_BUG_ON(TSO(sdar
) + sizeof(unsigned long) != TSO(sier
));
430 BUILD_BUG_ON(TSO(sier
) + sizeof(unsigned long) != TSO(mmcr2
));
431 BUILD_BUG_ON(TSO(mmcr2
) + sizeof(unsigned long) != TSO(mmcr0
));
433 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
436 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, &target
->thread
.siar
,
437 0, sizeof(unsigned long));
440 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
441 &target
->thread
.sdar
, sizeof(unsigned long),
442 2 * sizeof(unsigned long));
445 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
446 &target
->thread
.sier
, 2 * sizeof(unsigned long),
447 3 * sizeof(unsigned long));
450 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
451 &target
->thread
.mmcr2
, 3 * sizeof(unsigned long),
452 4 * sizeof(unsigned long));
455 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
456 &target
->thread
.mmcr0
, 4 * sizeof(unsigned long),
457 5 * sizeof(unsigned long));
462 #ifdef CONFIG_PPC_MEM_KEYS
463 static int pkey_active(struct task_struct
*target
, const struct user_regset
*regset
)
465 if (!arch_pkeys_enabled())
471 static int pkey_get(struct task_struct
*target
, const struct user_regset
*regset
,
475 if (!arch_pkeys_enabled())
478 membuf_store(&to
, target
->thread
.regs
->amr
);
479 membuf_store(&to
, target
->thread
.regs
->iamr
);
480 return membuf_store(&to
, default_uamor
);
483 static int pkey_set(struct task_struct
*target
, const struct user_regset
*regset
,
484 unsigned int pos
, unsigned int count
, const void *kbuf
,
485 const void __user
*ubuf
)
490 if (!arch_pkeys_enabled())
493 /* Only the AMR can be set from userspace */
494 if (pos
!= 0 || count
!= sizeof(new_amr
))
497 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
498 &new_amr
, 0, sizeof(new_amr
));
503 * UAMOR determines which bits of the AMR can be set from userspace.
504 * UAMOR value 0b11 indicates that the AMR value can be modified
505 * from userspace. If the kernel is using a specific key, we avoid
506 * userspace modifying the AMR value for that key by masking them
509 * Pick the AMR values for the keys that kernel is using. This
510 * will be indicated by the ~default_uamor bits.
512 target
->thread
.regs
->amr
= (new_amr
& default_uamor
) |
513 (target
->thread
.regs
->amr
& ~default_uamor
);
517 #endif /* CONFIG_PPC_MEM_KEYS */
519 static const struct user_regset native_regsets
[] = {
521 .core_note_type
= NT_PRSTATUS
, .n
= ELF_NGREG
,
522 .size
= sizeof(long), .align
= sizeof(long),
523 .regset_get
= gpr_get
, .set
= gpr_set
525 #ifdef CONFIG_PPC_FPU_REGS
527 .core_note_type
= NT_PRFPREG
, .n
= ELF_NFPREG
,
528 .size
= sizeof(double), .align
= sizeof(double),
529 .regset_get
= fpr_get
, .set
= fpr_set
532 #ifdef CONFIG_ALTIVEC
534 .core_note_type
= NT_PPC_VMX
, .n
= 34,
535 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
536 .active
= vr_active
, .regset_get
= vr_get
, .set
= vr_set
541 .core_note_type
= NT_PPC_VSX
, .n
= 32,
542 .size
= sizeof(double), .align
= sizeof(double),
543 .active
= vsr_active
, .regset_get
= vsr_get
, .set
= vsr_set
548 .core_note_type
= NT_PPC_SPE
, .n
= 35,
549 .size
= sizeof(u32
), .align
= sizeof(u32
),
550 .active
= evr_active
, .regset_get
= evr_get
, .set
= evr_set
553 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
555 .core_note_type
= NT_PPC_TM_CGPR
, .n
= ELF_NGREG
,
556 .size
= sizeof(long), .align
= sizeof(long),
557 .active
= tm_cgpr_active
, .regset_get
= tm_cgpr_get
, .set
= tm_cgpr_set
560 .core_note_type
= NT_PPC_TM_CFPR
, .n
= ELF_NFPREG
,
561 .size
= sizeof(double), .align
= sizeof(double),
562 .active
= tm_cfpr_active
, .regset_get
= tm_cfpr_get
, .set
= tm_cfpr_set
565 .core_note_type
= NT_PPC_TM_CVMX
, .n
= ELF_NVMX
,
566 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
567 .active
= tm_cvmx_active
, .regset_get
= tm_cvmx_get
, .set
= tm_cvmx_set
570 .core_note_type
= NT_PPC_TM_CVSX
, .n
= ELF_NVSX
,
571 .size
= sizeof(double), .align
= sizeof(double),
572 .active
= tm_cvsx_active
, .regset_get
= tm_cvsx_get
, .set
= tm_cvsx_set
575 .core_note_type
= NT_PPC_TM_SPR
, .n
= ELF_NTMSPRREG
,
576 .size
= sizeof(u64
), .align
= sizeof(u64
),
577 .active
= tm_spr_active
, .regset_get
= tm_spr_get
, .set
= tm_spr_set
580 .core_note_type
= NT_PPC_TM_CTAR
, .n
= 1,
581 .size
= sizeof(u64
), .align
= sizeof(u64
),
582 .active
= tm_tar_active
, .regset_get
= tm_tar_get
, .set
= tm_tar_set
585 .core_note_type
= NT_PPC_TM_CPPR
, .n
= 1,
586 .size
= sizeof(u64
), .align
= sizeof(u64
),
587 .active
= tm_ppr_active
, .regset_get
= tm_ppr_get
, .set
= tm_ppr_set
589 [REGSET_TM_CDSCR
] = {
590 .core_note_type
= NT_PPC_TM_CDSCR
, .n
= 1,
591 .size
= sizeof(u64
), .align
= sizeof(u64
),
592 .active
= tm_dscr_active
, .regset_get
= tm_dscr_get
, .set
= tm_dscr_set
597 .core_note_type
= NT_PPC_PPR
, .n
= 1,
598 .size
= sizeof(u64
), .align
= sizeof(u64
),
599 .regset_get
= ppr_get
, .set
= ppr_set
602 .core_note_type
= NT_PPC_DSCR
, .n
= 1,
603 .size
= sizeof(u64
), .align
= sizeof(u64
),
604 .regset_get
= dscr_get
, .set
= dscr_set
607 #ifdef CONFIG_PPC_BOOK3S_64
609 .core_note_type
= NT_PPC_TAR
, .n
= 1,
610 .size
= sizeof(u64
), .align
= sizeof(u64
),
611 .regset_get
= tar_get
, .set
= tar_set
614 .core_note_type
= NT_PPC_EBB
, .n
= ELF_NEBB
,
615 .size
= sizeof(u64
), .align
= sizeof(u64
),
616 .active
= ebb_active
, .regset_get
= ebb_get
, .set
= ebb_set
619 .core_note_type
= NT_PPC_PMU
, .n
= ELF_NPMU
,
620 .size
= sizeof(u64
), .align
= sizeof(u64
),
621 .active
= pmu_active
, .regset_get
= pmu_get
, .set
= pmu_set
624 #ifdef CONFIG_PPC_MEM_KEYS
626 .core_note_type
= NT_PPC_PKEY
, .n
= ELF_NPKEY
,
627 .size
= sizeof(u64
), .align
= sizeof(u64
),
628 .active
= pkey_active
, .regset_get
= pkey_get
, .set
= pkey_set
633 const struct user_regset_view user_ppc_native_view
= {
634 .name
= UTS_MACHINE
, .e_machine
= ELF_ARCH
, .ei_osabi
= ELF_OSABI
,
635 .regsets
= native_regsets
, .n
= ARRAY_SIZE(native_regsets
)
638 #include <linux/compat.h>
640 int gpr32_get_common(struct task_struct
*target
,
641 const struct user_regset
*regset
,
642 struct membuf to
, unsigned long *regs
)
646 for (i
= 0; i
< PT_MSR
; i
++)
647 membuf_store(&to
, (u32
)regs
[i
]);
648 membuf_store(&to
, (u32
)get_user_msr(target
));
649 for (i
++ ; i
< PT_REGS_COUNT
; i
++)
650 membuf_store(&to
, (u32
)regs
[i
]);
651 return membuf_zero(&to
, (ELF_NGREG
- PT_REGS_COUNT
) * sizeof(u32
));
654 int gpr32_set_common(struct task_struct
*target
,
655 const struct user_regset
*regset
,
656 unsigned int pos
, unsigned int count
,
657 const void *kbuf
, const void __user
*ubuf
,
660 const compat_ulong_t
*k
= kbuf
;
661 const compat_ulong_t __user
*u
= ubuf
;
665 count
/= sizeof(reg
);
668 for (; count
> 0 && pos
< PT_MSR
; --count
)
671 for (; count
> 0 && pos
< PT_MSR
; --count
) {
672 if (__get_user(reg
, u
++))
678 if (count
> 0 && pos
== PT_MSR
) {
681 else if (__get_user(reg
, u
++))
683 set_user_msr(target
, reg
);
689 for (; count
> 0 && pos
<= PT_MAX_PUT_REG
; --count
)
691 for (; count
> 0 && pos
< PT_TRAP
; --count
, ++pos
)
694 for (; count
> 0 && pos
<= PT_MAX_PUT_REG
; --count
) {
695 if (__get_user(reg
, u
++))
699 for (; count
> 0 && pos
< PT_TRAP
; --count
, ++pos
)
700 if (__get_user(reg
, u
++))
704 if (count
> 0 && pos
== PT_TRAP
) {
707 else if (__get_user(reg
, u
++))
709 set_user_trap(target
, reg
);
717 count
*= sizeof(reg
);
718 return user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
719 (PT_TRAP
+ 1) * sizeof(reg
), -1);
722 static int gpr32_get(struct task_struct
*target
,
723 const struct user_regset
*regset
,
728 if (target
->thread
.regs
== NULL
)
731 if (!FULL_REGS(target
->thread
.regs
)) {
733 * We have a partial register set.
734 * Fill 14-31 with bogus values.
736 for (i
= 14; i
< 32; i
++)
737 target
->thread
.regs
->gpr
[i
] = NV_REG_POISON
;
739 return gpr32_get_common(target
, regset
, to
,
740 &target
->thread
.regs
->gpr
[0]);
743 static int gpr32_set(struct task_struct
*target
,
744 const struct user_regset
*regset
,
745 unsigned int pos
, unsigned int count
,
746 const void *kbuf
, const void __user
*ubuf
)
748 if (target
->thread
.regs
== NULL
)
751 CHECK_FULL_REGS(target
->thread
.regs
);
752 return gpr32_set_common(target
, regset
, pos
, count
, kbuf
, ubuf
,
753 &target
->thread
.regs
->gpr
[0]);
757 * These are the regset flavors matching the CONFIG_PPC32 native set.
759 static const struct user_regset compat_regsets
[] = {
761 .core_note_type
= NT_PRSTATUS
, .n
= ELF_NGREG
,
762 .size
= sizeof(compat_long_t
), .align
= sizeof(compat_long_t
),
763 .regset_get
= gpr32_get
, .set
= gpr32_set
766 .core_note_type
= NT_PRFPREG
, .n
= ELF_NFPREG
,
767 .size
= sizeof(double), .align
= sizeof(double),
768 .regset_get
= fpr_get
, .set
= fpr_set
770 #ifdef CONFIG_ALTIVEC
772 .core_note_type
= NT_PPC_VMX
, .n
= 34,
773 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
774 .active
= vr_active
, .regset_get
= vr_get
, .set
= vr_set
779 .core_note_type
= NT_PPC_SPE
, .n
= 35,
780 .size
= sizeof(u32
), .align
= sizeof(u32
),
781 .active
= evr_active
, .regset_get
= evr_get
, .set
= evr_set
784 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
786 .core_note_type
= NT_PPC_TM_CGPR
, .n
= ELF_NGREG
,
787 .size
= sizeof(long), .align
= sizeof(long),
788 .active
= tm_cgpr_active
,
789 .regset_get
= tm_cgpr32_get
, .set
= tm_cgpr32_set
792 .core_note_type
= NT_PPC_TM_CFPR
, .n
= ELF_NFPREG
,
793 .size
= sizeof(double), .align
= sizeof(double),
794 .active
= tm_cfpr_active
, .regset_get
= tm_cfpr_get
, .set
= tm_cfpr_set
797 .core_note_type
= NT_PPC_TM_CVMX
, .n
= ELF_NVMX
,
798 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
799 .active
= tm_cvmx_active
, .regset_get
= tm_cvmx_get
, .set
= tm_cvmx_set
802 .core_note_type
= NT_PPC_TM_CVSX
, .n
= ELF_NVSX
,
803 .size
= sizeof(double), .align
= sizeof(double),
804 .active
= tm_cvsx_active
, .regset_get
= tm_cvsx_get
, .set
= tm_cvsx_set
807 .core_note_type
= NT_PPC_TM_SPR
, .n
= ELF_NTMSPRREG
,
808 .size
= sizeof(u64
), .align
= sizeof(u64
),
809 .active
= tm_spr_active
, .regset_get
= tm_spr_get
, .set
= tm_spr_set
812 .core_note_type
= NT_PPC_TM_CTAR
, .n
= 1,
813 .size
= sizeof(u64
), .align
= sizeof(u64
),
814 .active
= tm_tar_active
, .regset_get
= tm_tar_get
, .set
= tm_tar_set
817 .core_note_type
= NT_PPC_TM_CPPR
, .n
= 1,
818 .size
= sizeof(u64
), .align
= sizeof(u64
),
819 .active
= tm_ppr_active
, .regset_get
= tm_ppr_get
, .set
= tm_ppr_set
821 [REGSET_TM_CDSCR
] = {
822 .core_note_type
= NT_PPC_TM_CDSCR
, .n
= 1,
823 .size
= sizeof(u64
), .align
= sizeof(u64
),
824 .active
= tm_dscr_active
, .regset_get
= tm_dscr_get
, .set
= tm_dscr_set
829 .core_note_type
= NT_PPC_PPR
, .n
= 1,
830 .size
= sizeof(u64
), .align
= sizeof(u64
),
831 .regset_get
= ppr_get
, .set
= ppr_set
834 .core_note_type
= NT_PPC_DSCR
, .n
= 1,
835 .size
= sizeof(u64
), .align
= sizeof(u64
),
836 .regset_get
= dscr_get
, .set
= dscr_set
839 #ifdef CONFIG_PPC_BOOK3S_64
841 .core_note_type
= NT_PPC_TAR
, .n
= 1,
842 .size
= sizeof(u64
), .align
= sizeof(u64
),
843 .regset_get
= tar_get
, .set
= tar_set
846 .core_note_type
= NT_PPC_EBB
, .n
= ELF_NEBB
,
847 .size
= sizeof(u64
), .align
= sizeof(u64
),
848 .active
= ebb_active
, .regset_get
= ebb_get
, .set
= ebb_set
853 static const struct user_regset_view user_ppc_compat_view
= {
854 .name
= "ppc", .e_machine
= EM_PPC
, .ei_osabi
= ELF_OSABI
,
855 .regsets
= compat_regsets
, .n
= ARRAY_SIZE(compat_regsets
)
858 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
860 if (IS_ENABLED(CONFIG_PPC64
) && test_tsk_thread_flag(task
, TIF_32BIT
))
861 return &user_ppc_compat_view
;
862 return &user_ppc_native_view
;