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 __always_inline
int set_user_msr(struct task_struct
*task
, unsigned long msr
)
116 unsigned long newmsr
= (task
->thread
.regs
->msr
& ~MSR_DEBUGCHANGE
) |
117 (msr
& MSR_DEBUGCHANGE
);
118 regs_set_return_msr(task
->thread
.regs
, newmsr
);
123 static int get_user_dscr(struct task_struct
*task
, unsigned long *data
)
125 *data
= task
->thread
.dscr
;
129 static int set_user_dscr(struct task_struct
*task
, unsigned long dscr
)
131 task
->thread
.dscr
= dscr
;
132 task
->thread
.dscr_inherit
= 1;
136 static int get_user_dscr(struct task_struct
*task
, unsigned long *data
)
141 static int set_user_dscr(struct task_struct
*task
, unsigned long dscr
)
148 * We prevent mucking around with the reserved area of trap
149 * which are used internally by the kernel.
151 static __always_inline
int set_user_trap(struct task_struct
*task
, unsigned long trap
)
153 set_trap(task
->thread
.regs
, trap
);
158 * Get contents of register REGNO in task TASK.
160 int ptrace_get_reg(struct task_struct
*task
, int regno
, unsigned long *data
)
162 unsigned int regs_max
;
164 if (task
->thread
.regs
== NULL
|| !data
)
167 if (regno
== PT_MSR
) {
168 *data
= get_user_msr(task
);
172 if (regno
== PT_DSCR
)
173 return get_user_dscr(task
, data
);
176 * softe copies paca->irq_soft_mask variable state. Since irq_soft_mask is
177 * no more used as a flag, lets force usr to always see the softe value as 1
178 * which means interrupts are not soft disabled.
180 if (IS_ENABLED(CONFIG_PPC64
) && regno
== PT_SOFTE
) {
185 regs_max
= sizeof(struct user_pt_regs
) / sizeof(unsigned long);
186 if (regno
< regs_max
) {
187 regno
= array_index_nospec(regno
, regs_max
);
188 *data
= ((unsigned long *)task
->thread
.regs
)[regno
];
196 * Write contents of register REGNO in task TASK.
198 int ptrace_put_reg(struct task_struct
*task
, int regno
, unsigned long data
)
200 if (task
->thread
.regs
== NULL
)
204 return set_user_msr(task
, data
);
205 if (regno
== PT_TRAP
)
206 return set_user_trap(task
, data
);
207 if (regno
== PT_DSCR
)
208 return set_user_dscr(task
, data
);
210 if (regno
<= PT_MAX_PUT_REG
) {
211 regno
= array_index_nospec(regno
, PT_MAX_PUT_REG
+ 1);
212 ((unsigned long *)task
->thread
.regs
)[regno
] = data
;
218 static int gpr_get(struct task_struct
*target
, const struct user_regset
*regset
,
221 struct membuf to_msr
= membuf_at(&to
, offsetof(struct pt_regs
, msr
));
223 struct membuf to_softe
= membuf_at(&to
, offsetof(struct pt_regs
, softe
));
225 if (target
->thread
.regs
== NULL
)
228 membuf_write(&to
, target
->thread
.regs
, sizeof(struct user_pt_regs
));
230 membuf_store(&to_msr
, get_user_msr(target
));
232 membuf_store(&to_softe
, 0x1ul
);
234 return membuf_zero(&to
, ELF_NGREG
* sizeof(unsigned long) -
235 sizeof(struct user_pt_regs
));
238 static int gpr_set(struct task_struct
*target
, const struct user_regset
*regset
,
239 unsigned int pos
, unsigned int count
, const void *kbuf
,
240 const void __user
*ubuf
)
245 if (target
->thread
.regs
== NULL
)
248 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
250 0, PT_MSR
* sizeof(reg
));
252 if (!ret
&& count
> 0) {
253 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, ®
,
254 PT_MSR
* sizeof(reg
),
255 (PT_MSR
+ 1) * sizeof(reg
));
257 ret
= set_user_msr(target
, reg
);
260 BUILD_BUG_ON(offsetof(struct pt_regs
, orig_gpr3
) !=
261 offsetof(struct pt_regs
, msr
) + sizeof(long));
264 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
265 &target
->thread
.regs
->orig_gpr3
,
266 PT_ORIG_R3
* sizeof(reg
),
267 (PT_MAX_PUT_REG
+ 1) * sizeof(reg
));
269 if (PT_MAX_PUT_REG
+ 1 < PT_TRAP
&& !ret
)
270 user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
271 (PT_MAX_PUT_REG
+ 1) * sizeof(reg
),
272 PT_TRAP
* sizeof(reg
));
274 if (!ret
&& count
> 0) {
275 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, ®
,
276 PT_TRAP
* sizeof(reg
),
277 (PT_TRAP
+ 1) * sizeof(reg
));
279 ret
= set_user_trap(target
, reg
);
283 user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
284 (PT_TRAP
+ 1) * sizeof(reg
), -1);
290 static int ppr_get(struct task_struct
*target
, const struct user_regset
*regset
,
293 if (!target
->thread
.regs
)
296 return membuf_write(&to
, &target
->thread
.regs
->ppr
, sizeof(u64
));
299 static int ppr_set(struct task_struct
*target
, const struct user_regset
*regset
,
300 unsigned int pos
, unsigned int count
, const void *kbuf
,
301 const void __user
*ubuf
)
303 if (!target
->thread
.regs
)
306 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
307 &target
->thread
.regs
->ppr
, 0, sizeof(u64
));
310 static int dscr_get(struct task_struct
*target
, const struct user_regset
*regset
,
313 return membuf_write(&to
, &target
->thread
.dscr
, sizeof(u64
));
315 static int dscr_set(struct task_struct
*target
, const struct user_regset
*regset
,
316 unsigned int pos
, unsigned int count
, const void *kbuf
,
317 const void __user
*ubuf
)
319 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
320 &target
->thread
.dscr
, 0, sizeof(u64
));
323 #ifdef CONFIG_PPC_BOOK3S_64
324 static int tar_get(struct task_struct
*target
, const struct user_regset
*regset
,
327 return membuf_write(&to
, &target
->thread
.tar
, sizeof(u64
));
329 static int tar_set(struct task_struct
*target
, const struct user_regset
*regset
,
330 unsigned int pos
, unsigned int count
, const void *kbuf
,
331 const void __user
*ubuf
)
333 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
334 &target
->thread
.tar
, 0, sizeof(u64
));
337 static int ebb_active(struct task_struct
*target
, const struct user_regset
*regset
)
339 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
342 if (target
->thread
.used_ebb
)
348 static int ebb_get(struct task_struct
*target
, const struct user_regset
*regset
,
352 BUILD_BUG_ON(TSO(ebbrr
) + sizeof(unsigned long) != TSO(ebbhr
));
353 BUILD_BUG_ON(TSO(ebbhr
) + sizeof(unsigned long) != TSO(bescr
));
355 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
358 if (!target
->thread
.used_ebb
)
361 return membuf_write(&to
, &target
->thread
.ebbrr
, 3 * sizeof(unsigned long));
364 static int ebb_set(struct task_struct
*target
, const struct user_regset
*regset
,
365 unsigned int pos
, unsigned int count
, const void *kbuf
,
366 const void __user
*ubuf
)
371 BUILD_BUG_ON(TSO(ebbrr
) + sizeof(unsigned long) != TSO(ebbhr
));
372 BUILD_BUG_ON(TSO(ebbhr
) + sizeof(unsigned long) != TSO(bescr
));
374 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
377 if (target
->thread
.used_ebb
)
380 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, &target
->thread
.ebbrr
,
381 0, sizeof(unsigned long));
384 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
385 &target
->thread
.ebbhr
, sizeof(unsigned long),
386 2 * sizeof(unsigned long));
389 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
390 &target
->thread
.bescr
, 2 * sizeof(unsigned long),
391 3 * sizeof(unsigned long));
395 static int pmu_active(struct task_struct
*target
, const struct user_regset
*regset
)
397 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
403 static int pmu_get(struct task_struct
*target
, const struct user_regset
*regset
,
407 BUILD_BUG_ON(TSO(siar
) + sizeof(unsigned long) != TSO(sdar
));
408 BUILD_BUG_ON(TSO(sdar
) + sizeof(unsigned long) != TSO(sier
));
409 BUILD_BUG_ON(TSO(sier
) + sizeof(unsigned long) != TSO(mmcr2
));
410 BUILD_BUG_ON(TSO(mmcr2
) + sizeof(unsigned long) != TSO(mmcr0
));
412 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
415 return membuf_write(&to
, &target
->thread
.siar
, 5 * sizeof(unsigned long));
418 static int pmu_set(struct task_struct
*target
, const struct user_regset
*regset
,
419 unsigned int pos
, unsigned int count
, const void *kbuf
,
420 const void __user
*ubuf
)
425 BUILD_BUG_ON(TSO(siar
) + sizeof(unsigned long) != TSO(sdar
));
426 BUILD_BUG_ON(TSO(sdar
) + sizeof(unsigned long) != TSO(sier
));
427 BUILD_BUG_ON(TSO(sier
) + sizeof(unsigned long) != TSO(mmcr2
));
428 BUILD_BUG_ON(TSO(mmcr2
) + sizeof(unsigned long) != TSO(mmcr0
));
430 if (!cpu_has_feature(CPU_FTR_ARCH_207S
))
433 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, &target
->thread
.siar
,
434 0, sizeof(unsigned long));
437 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
438 &target
->thread
.sdar
, sizeof(unsigned long),
439 2 * sizeof(unsigned long));
442 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
443 &target
->thread
.sier
, 2 * sizeof(unsigned long),
444 3 * sizeof(unsigned long));
447 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
448 &target
->thread
.mmcr2
, 3 * sizeof(unsigned long),
449 4 * sizeof(unsigned long));
452 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
453 &target
->thread
.mmcr0
, 4 * sizeof(unsigned long),
454 5 * sizeof(unsigned long));
458 static int dexcr_active(struct task_struct
*target
, const struct user_regset
*regset
)
460 if (!cpu_has_feature(CPU_FTR_ARCH_31
))
466 static int dexcr_get(struct task_struct
*target
, const struct user_regset
*regset
,
469 if (!cpu_has_feature(CPU_FTR_ARCH_31
))
472 membuf_store(&to
, (u64
)lower_32_bits(target
->thread
.dexcr
));
475 * Technically the HDEXCR is per-cpu, but a hypervisor can't reasonably
476 * change it between CPUs of the same guest.
478 return membuf_store(&to
, (u64
)lower_32_bits(mfspr(SPRN_HDEXCR_RO
)));
481 #ifdef CONFIG_CHECKPOINT_RESTORE
482 static int hashkeyr_active(struct task_struct
*target
, const struct user_regset
*regset
)
484 if (!cpu_has_feature(CPU_FTR_ARCH_31
))
490 static int hashkeyr_get(struct task_struct
*target
, const struct user_regset
*regset
,
493 if (!cpu_has_feature(CPU_FTR_ARCH_31
))
496 return membuf_store(&to
, target
->thread
.hashkeyr
);
499 static int hashkeyr_set(struct task_struct
*target
, const struct user_regset
*regset
,
500 unsigned int pos
, unsigned int count
, const void *kbuf
,
501 const void __user
*ubuf
)
503 if (!cpu_has_feature(CPU_FTR_ARCH_31
))
506 return user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
, &target
->thread
.hashkeyr
,
507 0, sizeof(unsigned long));
509 #endif /* CONFIG_CHECKPOINT_RESTORE */
510 #endif /* CONFIG_PPC_BOOK3S_64 */
512 #ifdef CONFIG_PPC_MEM_KEYS
513 static int pkey_active(struct task_struct
*target
, const struct user_regset
*regset
)
515 if (!arch_pkeys_enabled())
521 static int pkey_get(struct task_struct
*target
, const struct user_regset
*regset
,
525 if (!arch_pkeys_enabled())
528 membuf_store(&to
, target
->thread
.regs
->amr
);
529 membuf_store(&to
, target
->thread
.regs
->iamr
);
530 return membuf_store(&to
, default_uamor
);
533 static int pkey_set(struct task_struct
*target
, const struct user_regset
*regset
,
534 unsigned int pos
, unsigned int count
, const void *kbuf
,
535 const void __user
*ubuf
)
540 if (!arch_pkeys_enabled())
543 /* Only the AMR can be set from userspace */
544 if (pos
!= 0 || count
!= sizeof(new_amr
))
547 ret
= user_regset_copyin(&pos
, &count
, &kbuf
, &ubuf
,
548 &new_amr
, 0, sizeof(new_amr
));
553 * UAMOR determines which bits of the AMR can be set from userspace.
554 * UAMOR value 0b11 indicates that the AMR value can be modified
555 * from userspace. If the kernel is using a specific key, we avoid
556 * userspace modifying the AMR value for that key by masking them
559 * Pick the AMR values for the keys that kernel is using. This
560 * will be indicated by the ~default_uamor bits.
562 target
->thread
.regs
->amr
= (new_amr
& default_uamor
) |
563 (target
->thread
.regs
->amr
& ~default_uamor
);
567 #endif /* CONFIG_PPC_MEM_KEYS */
569 static const struct user_regset native_regsets
[] = {
571 .core_note_type
= NT_PRSTATUS
, .n
= ELF_NGREG
,
572 .size
= sizeof(long), .align
= sizeof(long),
573 .regset_get
= gpr_get
, .set
= gpr_set
576 .core_note_type
= NT_PRFPREG
, .n
= ELF_NFPREG
,
577 .size
= sizeof(double), .align
= sizeof(double),
578 .regset_get
= fpr_get
, .set
= fpr_set
580 #ifdef CONFIG_ALTIVEC
582 .core_note_type
= NT_PPC_VMX
, .n
= 34,
583 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
584 .active
= vr_active
, .regset_get
= vr_get
, .set
= vr_set
589 .core_note_type
= NT_PPC_VSX
, .n
= 32,
590 .size
= sizeof(double), .align
= sizeof(double),
591 .active
= vsr_active
, .regset_get
= vsr_get
, .set
= vsr_set
596 .core_note_type
= NT_PPC_SPE
, .n
= 35,
597 .size
= sizeof(u32
), .align
= sizeof(u32
),
598 .active
= evr_active
, .regset_get
= evr_get
, .set
= evr_set
601 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
603 .core_note_type
= NT_PPC_TM_CGPR
, .n
= ELF_NGREG
,
604 .size
= sizeof(long), .align
= sizeof(long),
605 .active
= tm_cgpr_active
, .regset_get
= tm_cgpr_get
, .set
= tm_cgpr_set
608 .core_note_type
= NT_PPC_TM_CFPR
, .n
= ELF_NFPREG
,
609 .size
= sizeof(double), .align
= sizeof(double),
610 .active
= tm_cfpr_active
, .regset_get
= tm_cfpr_get
, .set
= tm_cfpr_set
613 .core_note_type
= NT_PPC_TM_CVMX
, .n
= ELF_NVMX
,
614 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
615 .active
= tm_cvmx_active
, .regset_get
= tm_cvmx_get
, .set
= tm_cvmx_set
618 .core_note_type
= NT_PPC_TM_CVSX
, .n
= ELF_NVSX
,
619 .size
= sizeof(double), .align
= sizeof(double),
620 .active
= tm_cvsx_active
, .regset_get
= tm_cvsx_get
, .set
= tm_cvsx_set
623 .core_note_type
= NT_PPC_TM_SPR
, .n
= ELF_NTMSPRREG
,
624 .size
= sizeof(u64
), .align
= sizeof(u64
),
625 .active
= tm_spr_active
, .regset_get
= tm_spr_get
, .set
= tm_spr_set
628 .core_note_type
= NT_PPC_TM_CTAR
, .n
= 1,
629 .size
= sizeof(u64
), .align
= sizeof(u64
),
630 .active
= tm_tar_active
, .regset_get
= tm_tar_get
, .set
= tm_tar_set
633 .core_note_type
= NT_PPC_TM_CPPR
, .n
= 1,
634 .size
= sizeof(u64
), .align
= sizeof(u64
),
635 .active
= tm_ppr_active
, .regset_get
= tm_ppr_get
, .set
= tm_ppr_set
637 [REGSET_TM_CDSCR
] = {
638 .core_note_type
= NT_PPC_TM_CDSCR
, .n
= 1,
639 .size
= sizeof(u64
), .align
= sizeof(u64
),
640 .active
= tm_dscr_active
, .regset_get
= tm_dscr_get
, .set
= tm_dscr_set
645 .core_note_type
= NT_PPC_PPR
, .n
= 1,
646 .size
= sizeof(u64
), .align
= sizeof(u64
),
647 .regset_get
= ppr_get
, .set
= ppr_set
650 .core_note_type
= NT_PPC_DSCR
, .n
= 1,
651 .size
= sizeof(u64
), .align
= sizeof(u64
),
652 .regset_get
= dscr_get
, .set
= dscr_set
655 #ifdef CONFIG_PPC_BOOK3S_64
657 .core_note_type
= NT_PPC_TAR
, .n
= 1,
658 .size
= sizeof(u64
), .align
= sizeof(u64
),
659 .regset_get
= tar_get
, .set
= tar_set
662 .core_note_type
= NT_PPC_EBB
, .n
= ELF_NEBB
,
663 .size
= sizeof(u64
), .align
= sizeof(u64
),
664 .active
= ebb_active
, .regset_get
= ebb_get
, .set
= ebb_set
667 .core_note_type
= NT_PPC_PMU
, .n
= ELF_NPMU
,
668 .size
= sizeof(u64
), .align
= sizeof(u64
),
669 .active
= pmu_active
, .regset_get
= pmu_get
, .set
= pmu_set
672 .core_note_type
= NT_PPC_DEXCR
, .n
= ELF_NDEXCR
,
673 .size
= sizeof(u64
), .align
= sizeof(u64
),
674 .active
= dexcr_active
, .regset_get
= dexcr_get
676 #ifdef CONFIG_CHECKPOINT_RESTORE
677 [REGSET_HASHKEYR
] = {
678 .core_note_type
= NT_PPC_HASHKEYR
, .n
= ELF_NHASHKEYR
,
679 .size
= sizeof(u64
), .align
= sizeof(u64
),
680 .active
= hashkeyr_active
, .regset_get
= hashkeyr_get
, .set
= hashkeyr_set
684 #ifdef CONFIG_PPC_MEM_KEYS
686 .core_note_type
= NT_PPC_PKEY
, .n
= ELF_NPKEY
,
687 .size
= sizeof(u64
), .align
= sizeof(u64
),
688 .active
= pkey_active
, .regset_get
= pkey_get
, .set
= pkey_set
693 const struct user_regset_view user_ppc_native_view
= {
694 .name
= UTS_MACHINE
, .e_machine
= ELF_ARCH
, .ei_osabi
= ELF_OSABI
,
695 .regsets
= native_regsets
, .n
= ARRAY_SIZE(native_regsets
)
698 #include <linux/compat.h>
700 int gpr32_get_common(struct task_struct
*target
,
701 const struct user_regset
*regset
,
702 struct membuf to
, unsigned long *regs
)
706 for (i
= 0; i
< PT_MSR
; i
++)
707 membuf_store(&to
, (u32
)regs
[i
]);
708 membuf_store(&to
, (u32
)get_user_msr(target
));
709 for (i
++ ; i
< PT_REGS_COUNT
; i
++)
710 membuf_store(&to
, (u32
)regs
[i
]);
711 return membuf_zero(&to
, (ELF_NGREG
- PT_REGS_COUNT
) * sizeof(u32
));
714 static int gpr32_set_common_kernel(struct task_struct
*target
,
715 const struct user_regset
*regset
,
716 unsigned int pos
, unsigned int count
,
717 const void *kbuf
, unsigned long *regs
)
719 const compat_ulong_t
*k
= kbuf
;
721 pos
/= sizeof(compat_ulong_t
);
722 count
/= sizeof(compat_ulong_t
);
724 for (; count
> 0 && pos
< PT_MSR
; --count
)
727 if (count
> 0 && pos
== PT_MSR
) {
728 set_user_msr(target
, *k
++);
733 for (; count
> 0 && pos
<= PT_MAX_PUT_REG
; --count
)
735 for (; count
> 0 && pos
< PT_TRAP
; --count
, ++pos
)
738 if (count
> 0 && pos
== PT_TRAP
) {
739 set_user_trap(target
, *k
++);
745 pos
*= sizeof(compat_ulong_t
);
746 count
*= sizeof(compat_ulong_t
);
747 user_regset_copyin_ignore(&pos
, &count
, &kbuf
, NULL
,
748 (PT_TRAP
+ 1) * sizeof(compat_ulong_t
), -1);
752 static int gpr32_set_common_user(struct task_struct
*target
,
753 const struct user_regset
*regset
,
754 unsigned int pos
, unsigned int count
,
755 const void __user
*ubuf
, unsigned long *regs
)
757 const compat_ulong_t __user
*u
= ubuf
;
758 const void *kbuf
= NULL
;
761 if (!user_read_access_begin(u
, count
))
765 count
/= sizeof(reg
);
767 for (; count
> 0 && pos
< PT_MSR
; --count
) {
768 unsafe_get_user(reg
, u
++, Efault
);
772 if (count
> 0 && pos
== PT_MSR
) {
773 unsafe_get_user(reg
, u
++, Efault
);
774 set_user_msr(target
, reg
);
779 for (; count
> 0 && pos
<= PT_MAX_PUT_REG
; --count
) {
780 unsafe_get_user(reg
, u
++, Efault
);
783 for (; count
> 0 && pos
< PT_TRAP
; --count
, ++pos
)
784 unsafe_get_user(reg
, u
++, Efault
);
786 if (count
> 0 && pos
== PT_TRAP
) {
787 unsafe_get_user(reg
, u
++, Efault
);
788 set_user_trap(target
, reg
);
792 user_read_access_end();
796 count
*= sizeof(reg
);
797 user_regset_copyin_ignore(&pos
, &count
, &kbuf
, &ubuf
,
798 (PT_TRAP
+ 1) * sizeof(reg
), -1);
802 user_read_access_end();
806 int gpr32_set_common(struct task_struct
*target
,
807 const struct user_regset
*regset
,
808 unsigned int pos
, unsigned int count
,
809 const void *kbuf
, const void __user
*ubuf
,
813 return gpr32_set_common_kernel(target
, regset
, pos
, count
, kbuf
, regs
);
815 return gpr32_set_common_user(target
, regset
, pos
, count
, ubuf
, regs
);
818 static int gpr32_get(struct task_struct
*target
,
819 const struct user_regset
*regset
,
822 if (target
->thread
.regs
== NULL
)
825 return gpr32_get_common(target
, regset
, to
,
826 &target
->thread
.regs
->gpr
[0]);
829 static int gpr32_set(struct task_struct
*target
,
830 const struct user_regset
*regset
,
831 unsigned int pos
, unsigned int count
,
832 const void *kbuf
, const void __user
*ubuf
)
834 if (target
->thread
.regs
== NULL
)
837 return gpr32_set_common(target
, regset
, pos
, count
, kbuf
, ubuf
,
838 &target
->thread
.regs
->gpr
[0]);
842 * These are the regset flavors matching the CONFIG_PPC32 native set.
844 static const struct user_regset compat_regsets
[] = {
846 .core_note_type
= NT_PRSTATUS
, .n
= ELF_NGREG
,
847 .size
= sizeof(compat_long_t
), .align
= sizeof(compat_long_t
),
848 .regset_get
= gpr32_get
, .set
= gpr32_set
851 .core_note_type
= NT_PRFPREG
, .n
= ELF_NFPREG
,
852 .size
= sizeof(double), .align
= sizeof(double),
853 .regset_get
= fpr_get
, .set
= fpr_set
855 #ifdef CONFIG_ALTIVEC
857 .core_note_type
= NT_PPC_VMX
, .n
= 34,
858 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
859 .active
= vr_active
, .regset_get
= vr_get
, .set
= vr_set
864 .core_note_type
= NT_PPC_SPE
, .n
= 35,
865 .size
= sizeof(u32
), .align
= sizeof(u32
),
866 .active
= evr_active
, .regset_get
= evr_get
, .set
= evr_set
869 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
871 .core_note_type
= NT_PPC_TM_CGPR
, .n
= ELF_NGREG
,
872 .size
= sizeof(long), .align
= sizeof(long),
873 .active
= tm_cgpr_active
,
874 .regset_get
= tm_cgpr32_get
, .set
= tm_cgpr32_set
877 .core_note_type
= NT_PPC_TM_CFPR
, .n
= ELF_NFPREG
,
878 .size
= sizeof(double), .align
= sizeof(double),
879 .active
= tm_cfpr_active
, .regset_get
= tm_cfpr_get
, .set
= tm_cfpr_set
882 .core_note_type
= NT_PPC_TM_CVMX
, .n
= ELF_NVMX
,
883 .size
= sizeof(vector128
), .align
= sizeof(vector128
),
884 .active
= tm_cvmx_active
, .regset_get
= tm_cvmx_get
, .set
= tm_cvmx_set
887 .core_note_type
= NT_PPC_TM_CVSX
, .n
= ELF_NVSX
,
888 .size
= sizeof(double), .align
= sizeof(double),
889 .active
= tm_cvsx_active
, .regset_get
= tm_cvsx_get
, .set
= tm_cvsx_set
892 .core_note_type
= NT_PPC_TM_SPR
, .n
= ELF_NTMSPRREG
,
893 .size
= sizeof(u64
), .align
= sizeof(u64
),
894 .active
= tm_spr_active
, .regset_get
= tm_spr_get
, .set
= tm_spr_set
897 .core_note_type
= NT_PPC_TM_CTAR
, .n
= 1,
898 .size
= sizeof(u64
), .align
= sizeof(u64
),
899 .active
= tm_tar_active
, .regset_get
= tm_tar_get
, .set
= tm_tar_set
902 .core_note_type
= NT_PPC_TM_CPPR
, .n
= 1,
903 .size
= sizeof(u64
), .align
= sizeof(u64
),
904 .active
= tm_ppr_active
, .regset_get
= tm_ppr_get
, .set
= tm_ppr_set
906 [REGSET_TM_CDSCR
] = {
907 .core_note_type
= NT_PPC_TM_CDSCR
, .n
= 1,
908 .size
= sizeof(u64
), .align
= sizeof(u64
),
909 .active
= tm_dscr_active
, .regset_get
= tm_dscr_get
, .set
= tm_dscr_set
914 .core_note_type
= NT_PPC_PPR
, .n
= 1,
915 .size
= sizeof(u64
), .align
= sizeof(u64
),
916 .regset_get
= ppr_get
, .set
= ppr_set
919 .core_note_type
= NT_PPC_DSCR
, .n
= 1,
920 .size
= sizeof(u64
), .align
= sizeof(u64
),
921 .regset_get
= dscr_get
, .set
= dscr_set
924 #ifdef CONFIG_PPC_BOOK3S_64
926 .core_note_type
= NT_PPC_TAR
, .n
= 1,
927 .size
= sizeof(u64
), .align
= sizeof(u64
),
928 .regset_get
= tar_get
, .set
= tar_set
931 .core_note_type
= NT_PPC_EBB
, .n
= ELF_NEBB
,
932 .size
= sizeof(u64
), .align
= sizeof(u64
),
933 .active
= ebb_active
, .regset_get
= ebb_get
, .set
= ebb_set
938 static const struct user_regset_view user_ppc_compat_view
= {
939 .name
= "ppc", .e_machine
= EM_PPC
, .ei_osabi
= ELF_OSABI
,
940 .regsets
= compat_regsets
, .n
= ARRAY_SIZE(compat_regsets
)
943 const struct user_regset_view
*task_user_regset_view(struct task_struct
*task
)
945 if (IS_ENABLED(CONFIG_COMPAT
) && is_tsk_32bit_task(task
))
946 return &user_ppc_compat_view
;
947 return &user_ppc_native_view
;