Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 #include <linux/regset.h>
0004 #include <linux/elf.h>
0005 #include <linux/nospec.h>
0006 #include <linux/pkeys.h>
0007 
0008 #include "ptrace-decl.h"
0009 
0010 struct pt_regs_offset {
0011     const char *name;
0012     int offset;
0013 };
0014 
0015 #define STR(s)  #s          /* convert to string */
0016 #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
0017 #define GPR_OFFSET_NAME(num)    \
0018     {.name = STR(r##num), .offset = offsetof(struct pt_regs, gpr[num])}, \
0019     {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])}
0020 #define REG_OFFSET_END {.name = NULL, .offset = 0}
0021 
0022 static const struct pt_regs_offset regoffset_table[] = {
0023     GPR_OFFSET_NAME(0),
0024     GPR_OFFSET_NAME(1),
0025     GPR_OFFSET_NAME(2),
0026     GPR_OFFSET_NAME(3),
0027     GPR_OFFSET_NAME(4),
0028     GPR_OFFSET_NAME(5),
0029     GPR_OFFSET_NAME(6),
0030     GPR_OFFSET_NAME(7),
0031     GPR_OFFSET_NAME(8),
0032     GPR_OFFSET_NAME(9),
0033     GPR_OFFSET_NAME(10),
0034     GPR_OFFSET_NAME(11),
0035     GPR_OFFSET_NAME(12),
0036     GPR_OFFSET_NAME(13),
0037     GPR_OFFSET_NAME(14),
0038     GPR_OFFSET_NAME(15),
0039     GPR_OFFSET_NAME(16),
0040     GPR_OFFSET_NAME(17),
0041     GPR_OFFSET_NAME(18),
0042     GPR_OFFSET_NAME(19),
0043     GPR_OFFSET_NAME(20),
0044     GPR_OFFSET_NAME(21),
0045     GPR_OFFSET_NAME(22),
0046     GPR_OFFSET_NAME(23),
0047     GPR_OFFSET_NAME(24),
0048     GPR_OFFSET_NAME(25),
0049     GPR_OFFSET_NAME(26),
0050     GPR_OFFSET_NAME(27),
0051     GPR_OFFSET_NAME(28),
0052     GPR_OFFSET_NAME(29),
0053     GPR_OFFSET_NAME(30),
0054     GPR_OFFSET_NAME(31),
0055     REG_OFFSET_NAME(nip),
0056     REG_OFFSET_NAME(msr),
0057     REG_OFFSET_NAME(ctr),
0058     REG_OFFSET_NAME(link),
0059     REG_OFFSET_NAME(xer),
0060     REG_OFFSET_NAME(ccr),
0061 #ifdef CONFIG_PPC64
0062     REG_OFFSET_NAME(softe),
0063 #else
0064     REG_OFFSET_NAME(mq),
0065 #endif
0066     REG_OFFSET_NAME(trap),
0067     REG_OFFSET_NAME(dar),
0068     REG_OFFSET_NAME(dsisr),
0069     REG_OFFSET_END,
0070 };
0071 
0072 /**
0073  * regs_query_register_offset() - query register offset from its name
0074  * @name:   the name of a register
0075  *
0076  * regs_query_register_offset() returns the offset of a register in struct
0077  * pt_regs from its name. If the name is invalid, this returns -EINVAL;
0078  */
0079 int regs_query_register_offset(const char *name)
0080 {
0081     const struct pt_regs_offset *roff;
0082     for (roff = regoffset_table; roff->name != NULL; roff++)
0083         if (!strcmp(roff->name, name))
0084             return roff->offset;
0085     return -EINVAL;
0086 }
0087 
0088 /**
0089  * regs_query_register_name() - query register name from its offset
0090  * @offset: the offset of a register in struct pt_regs.
0091  *
0092  * regs_query_register_name() returns the name of a register from its
0093  * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
0094  */
0095 const char *regs_query_register_name(unsigned int offset)
0096 {
0097     const struct pt_regs_offset *roff;
0098     for (roff = regoffset_table; roff->name != NULL; roff++)
0099         if (roff->offset == offset)
0100             return roff->name;
0101     return NULL;
0102 }
0103 
0104 /*
0105  * does not yet catch signals sent when the child dies.
0106  * in exit.c or in signal.c.
0107  */
0108 
0109 static unsigned long get_user_msr(struct task_struct *task)
0110 {
0111     return task->thread.regs->msr | task->thread.fpexc_mode;
0112 }
0113 
0114 static __always_inline int set_user_msr(struct task_struct *task, unsigned long msr)
0115 {
0116     unsigned long newmsr = (task->thread.regs->msr & ~MSR_DEBUGCHANGE) |
0117                 (msr & MSR_DEBUGCHANGE);
0118     regs_set_return_msr(task->thread.regs, newmsr);
0119     return 0;
0120 }
0121 
0122 #ifdef CONFIG_PPC64
0123 static int get_user_dscr(struct task_struct *task, unsigned long *data)
0124 {
0125     *data = task->thread.dscr;
0126     return 0;
0127 }
0128 
0129 static int set_user_dscr(struct task_struct *task, unsigned long dscr)
0130 {
0131     task->thread.dscr = dscr;
0132     task->thread.dscr_inherit = 1;
0133     return 0;
0134 }
0135 #else
0136 static int get_user_dscr(struct task_struct *task, unsigned long *data)
0137 {
0138     return -EIO;
0139 }
0140 
0141 static int set_user_dscr(struct task_struct *task, unsigned long dscr)
0142 {
0143     return -EIO;
0144 }
0145 #endif
0146 
0147 /*
0148  * We prevent mucking around with the reserved area of trap
0149  * which are used internally by the kernel.
0150  */
0151 static __always_inline int set_user_trap(struct task_struct *task, unsigned long trap)
0152 {
0153     set_trap(task->thread.regs, trap);
0154     return 0;
0155 }
0156 
0157 /*
0158  * Get contents of register REGNO in task TASK.
0159  */
0160 int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
0161 {
0162     unsigned int regs_max;
0163 
0164     if (task->thread.regs == NULL || !data)
0165         return -EIO;
0166 
0167     if (regno == PT_MSR) {
0168         *data = get_user_msr(task);
0169         return 0;
0170     }
0171 
0172     if (regno == PT_DSCR)
0173         return get_user_dscr(task, data);
0174 
0175     /*
0176      * softe copies paca->irq_soft_mask variable state. Since irq_soft_mask is
0177      * no more used as a flag, lets force usr to always see the softe value as 1
0178      * which means interrupts are not soft disabled.
0179      */
0180     if (IS_ENABLED(CONFIG_PPC64) && regno == PT_SOFTE) {
0181         *data = 1;
0182         return  0;
0183     }
0184 
0185     regs_max = sizeof(struct user_pt_regs) / sizeof(unsigned long);
0186     if (regno < regs_max) {
0187         regno = array_index_nospec(regno, regs_max);
0188         *data = ((unsigned long *)task->thread.regs)[regno];
0189         return 0;
0190     }
0191 
0192     return -EIO;
0193 }
0194 
0195 /*
0196  * Write contents of register REGNO in task TASK.
0197  */
0198 int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
0199 {
0200     if (task->thread.regs == NULL)
0201         return -EIO;
0202 
0203     if (regno == PT_MSR)
0204         return set_user_msr(task, data);
0205     if (regno == PT_TRAP)
0206         return set_user_trap(task, data);
0207     if (regno == PT_DSCR)
0208         return set_user_dscr(task, data);
0209 
0210     if (regno <= PT_MAX_PUT_REG) {
0211         regno = array_index_nospec(regno, PT_MAX_PUT_REG + 1);
0212         ((unsigned long *)task->thread.regs)[regno] = data;
0213         return 0;
0214     }
0215     return -EIO;
0216 }
0217 
0218 static int gpr_get(struct task_struct *target, const struct user_regset *regset,
0219            struct membuf to)
0220 {
0221     struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr));
0222 #ifdef CONFIG_PPC64
0223     struct membuf to_softe = membuf_at(&to, offsetof(struct pt_regs, softe));
0224 #endif
0225     if (target->thread.regs == NULL)
0226         return -EIO;
0227 
0228     membuf_write(&to, target->thread.regs, sizeof(struct user_pt_regs));
0229 
0230     membuf_store(&to_msr, get_user_msr(target));
0231 #ifdef CONFIG_PPC64
0232     membuf_store(&to_softe, 0x1ul);
0233 #endif
0234     return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) -
0235                  sizeof(struct user_pt_regs));
0236 }
0237 
0238 static int gpr_set(struct task_struct *target, const struct user_regset *regset,
0239            unsigned int pos, unsigned int count, const void *kbuf,
0240            const void __user *ubuf)
0241 {
0242     unsigned long reg;
0243     int ret;
0244 
0245     if (target->thread.regs == NULL)
0246         return -EIO;
0247 
0248     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0249                  target->thread.regs,
0250                  0, PT_MSR * sizeof(reg));
0251 
0252     if (!ret && count > 0) {
0253         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
0254                      PT_MSR * sizeof(reg),
0255                      (PT_MSR + 1) * sizeof(reg));
0256         if (!ret)
0257             ret = set_user_msr(target, reg);
0258     }
0259 
0260     BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
0261              offsetof(struct pt_regs, msr) + sizeof(long));
0262 
0263     if (!ret)
0264         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0265                      &target->thread.regs->orig_gpr3,
0266                      PT_ORIG_R3 * sizeof(reg),
0267                      (PT_MAX_PUT_REG + 1) * sizeof(reg));
0268 
0269     if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
0270         ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0271                         (PT_MAX_PUT_REG + 1) * sizeof(reg),
0272                         PT_TRAP * sizeof(reg));
0273 
0274     if (!ret && count > 0) {
0275         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
0276                      PT_TRAP * sizeof(reg),
0277                      (PT_TRAP + 1) * sizeof(reg));
0278         if (!ret)
0279             ret = set_user_trap(target, reg);
0280     }
0281 
0282     if (!ret)
0283         ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0284                         (PT_TRAP + 1) * sizeof(reg), -1);
0285 
0286     return ret;
0287 }
0288 
0289 #ifdef CONFIG_PPC64
0290 static int ppr_get(struct task_struct *target, const struct user_regset *regset,
0291            struct membuf to)
0292 {
0293     return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64));
0294 }
0295 
0296 static int ppr_set(struct task_struct *target, const struct user_regset *regset,
0297            unsigned int pos, unsigned int count, const void *kbuf,
0298            const void __user *ubuf)
0299 {
0300     return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0301                   &target->thread.regs->ppr, 0, sizeof(u64));
0302 }
0303 
0304 static int dscr_get(struct task_struct *target, const struct user_regset *regset,
0305             struct membuf to)
0306 {
0307     return membuf_write(&to, &target->thread.dscr, sizeof(u64));
0308 }
0309 static int dscr_set(struct task_struct *target, const struct user_regset *regset,
0310             unsigned int pos, unsigned int count, const void *kbuf,
0311             const void __user *ubuf)
0312 {
0313     return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0314                   &target->thread.dscr, 0, sizeof(u64));
0315 }
0316 #endif
0317 #ifdef CONFIG_PPC_BOOK3S_64
0318 static int tar_get(struct task_struct *target, const struct user_regset *regset,
0319            struct membuf to)
0320 {
0321     return membuf_write(&to, &target->thread.tar, sizeof(u64));
0322 }
0323 static int tar_set(struct task_struct *target, const struct user_regset *regset,
0324            unsigned int pos, unsigned int count, const void *kbuf,
0325            const void __user *ubuf)
0326 {
0327     return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0328                   &target->thread.tar, 0, sizeof(u64));
0329 }
0330 
0331 static int ebb_active(struct task_struct *target, const struct user_regset *regset)
0332 {
0333     if (!cpu_has_feature(CPU_FTR_ARCH_207S))
0334         return -ENODEV;
0335 
0336     if (target->thread.used_ebb)
0337         return regset->n;
0338 
0339     return 0;
0340 }
0341 
0342 static int ebb_get(struct task_struct *target, const struct user_regset *regset,
0343            struct membuf to)
0344 {
0345     /* Build tests */
0346     BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
0347     BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
0348 
0349     if (!cpu_has_feature(CPU_FTR_ARCH_207S))
0350         return -ENODEV;
0351 
0352     if (!target->thread.used_ebb)
0353         return -ENODATA;
0354 
0355     return membuf_write(&to, &target->thread.ebbrr, 3 * sizeof(unsigned long));
0356 }
0357 
0358 static int ebb_set(struct task_struct *target, const struct user_regset *regset,
0359            unsigned int pos, unsigned int count, const void *kbuf,
0360            const void __user *ubuf)
0361 {
0362     int ret = 0;
0363 
0364     /* Build tests */
0365     BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
0366     BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
0367 
0368     if (!cpu_has_feature(CPU_FTR_ARCH_207S))
0369         return -ENODEV;
0370 
0371     if (target->thread.used_ebb)
0372         return -ENODATA;
0373 
0374     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr,
0375                  0, sizeof(unsigned long));
0376 
0377     if (!ret)
0378         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0379                      &target->thread.ebbhr, sizeof(unsigned long),
0380                      2 * sizeof(unsigned long));
0381 
0382     if (!ret)
0383         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0384                      &target->thread.bescr, 2 * sizeof(unsigned long),
0385                      3 * sizeof(unsigned long));
0386 
0387     return ret;
0388 }
0389 static int pmu_active(struct task_struct *target, const struct user_regset *regset)
0390 {
0391     if (!cpu_has_feature(CPU_FTR_ARCH_207S))
0392         return -ENODEV;
0393 
0394     return regset->n;
0395 }
0396 
0397 static int pmu_get(struct task_struct *target, const struct user_regset *regset,
0398            struct membuf to)
0399 {
0400     /* Build tests */
0401     BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
0402     BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
0403     BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
0404     BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
0405 
0406     if (!cpu_has_feature(CPU_FTR_ARCH_207S))
0407         return -ENODEV;
0408 
0409     return membuf_write(&to, &target->thread.siar, 5 * sizeof(unsigned long));
0410 }
0411 
0412 static int pmu_set(struct task_struct *target, const struct user_regset *regset,
0413            unsigned int pos, unsigned int count, const void *kbuf,
0414            const void __user *ubuf)
0415 {
0416     int ret = 0;
0417 
0418     /* Build tests */
0419     BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
0420     BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
0421     BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
0422     BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
0423 
0424     if (!cpu_has_feature(CPU_FTR_ARCH_207S))
0425         return -ENODEV;
0426 
0427     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.siar,
0428                  0, sizeof(unsigned long));
0429 
0430     if (!ret)
0431         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0432                      &target->thread.sdar, sizeof(unsigned long),
0433                      2 * sizeof(unsigned long));
0434 
0435     if (!ret)
0436         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0437                      &target->thread.sier, 2 * sizeof(unsigned long),
0438                      3 * sizeof(unsigned long));
0439 
0440     if (!ret)
0441         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0442                      &target->thread.mmcr2, 3 * sizeof(unsigned long),
0443                      4 * sizeof(unsigned long));
0444 
0445     if (!ret)
0446         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0447                      &target->thread.mmcr0, 4 * sizeof(unsigned long),
0448                      5 * sizeof(unsigned long));
0449     return ret;
0450 }
0451 #endif
0452 
0453 #ifdef CONFIG_PPC_MEM_KEYS
0454 static int pkey_active(struct task_struct *target, const struct user_regset *regset)
0455 {
0456     if (!arch_pkeys_enabled())
0457         return -ENODEV;
0458 
0459     return regset->n;
0460 }
0461 
0462 static int pkey_get(struct task_struct *target, const struct user_regset *regset,
0463             struct membuf to)
0464 {
0465 
0466     if (!arch_pkeys_enabled())
0467         return -ENODEV;
0468 
0469     membuf_store(&to, target->thread.regs->amr);
0470     membuf_store(&to, target->thread.regs->iamr);
0471     return membuf_store(&to, default_uamor);
0472 }
0473 
0474 static int pkey_set(struct task_struct *target, const struct user_regset *regset,
0475             unsigned int pos, unsigned int count, const void *kbuf,
0476             const void __user *ubuf)
0477 {
0478     u64 new_amr;
0479     int ret;
0480 
0481     if (!arch_pkeys_enabled())
0482         return -ENODEV;
0483 
0484     /* Only the AMR can be set from userspace */
0485     if (pos != 0 || count != sizeof(new_amr))
0486         return -EINVAL;
0487 
0488     ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0489                  &new_amr, 0, sizeof(new_amr));
0490     if (ret)
0491         return ret;
0492 
0493     /*
0494      * UAMOR determines which bits of the AMR can be set from userspace.
0495      * UAMOR value 0b11 indicates that the AMR value can be modified
0496      * from userspace. If the kernel is using a specific key, we avoid
0497      * userspace modifying the AMR value for that key by masking them
0498      * via UAMOR 0b00.
0499      *
0500      * Pick the AMR values for the keys that kernel is using. This
0501      * will be indicated by the ~default_uamor bits.
0502      */
0503     target->thread.regs->amr = (new_amr & default_uamor) |
0504         (target->thread.regs->amr & ~default_uamor);
0505 
0506     return 0;
0507 }
0508 #endif /* CONFIG_PPC_MEM_KEYS */
0509 
0510 static const struct user_regset native_regsets[] = {
0511     [REGSET_GPR] = {
0512         .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
0513         .size = sizeof(long), .align = sizeof(long),
0514         .regset_get = gpr_get, .set = gpr_set
0515     },
0516     [REGSET_FPR] = {
0517         .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
0518         .size = sizeof(double), .align = sizeof(double),
0519         .regset_get = fpr_get, .set = fpr_set
0520     },
0521 #ifdef CONFIG_ALTIVEC
0522     [REGSET_VMX] = {
0523         .core_note_type = NT_PPC_VMX, .n = 34,
0524         .size = sizeof(vector128), .align = sizeof(vector128),
0525         .active = vr_active, .regset_get = vr_get, .set = vr_set
0526     },
0527 #endif
0528 #ifdef CONFIG_VSX
0529     [REGSET_VSX] = {
0530         .core_note_type = NT_PPC_VSX, .n = 32,
0531         .size = sizeof(double), .align = sizeof(double),
0532         .active = vsr_active, .regset_get = vsr_get, .set = vsr_set
0533     },
0534 #endif
0535 #ifdef CONFIG_SPE
0536     [REGSET_SPE] = {
0537         .core_note_type = NT_PPC_SPE, .n = 35,
0538         .size = sizeof(u32), .align = sizeof(u32),
0539         .active = evr_active, .regset_get = evr_get, .set = evr_set
0540     },
0541 #endif
0542 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
0543     [REGSET_TM_CGPR] = {
0544         .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
0545         .size = sizeof(long), .align = sizeof(long),
0546         .active = tm_cgpr_active, .regset_get = tm_cgpr_get, .set = tm_cgpr_set
0547     },
0548     [REGSET_TM_CFPR] = {
0549         .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
0550         .size = sizeof(double), .align = sizeof(double),
0551         .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set
0552     },
0553     [REGSET_TM_CVMX] = {
0554         .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
0555         .size = sizeof(vector128), .align = sizeof(vector128),
0556         .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set
0557     },
0558     [REGSET_TM_CVSX] = {
0559         .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
0560         .size = sizeof(double), .align = sizeof(double),
0561         .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set
0562     },
0563     [REGSET_TM_SPR] = {
0564         .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
0565         .size = sizeof(u64), .align = sizeof(u64),
0566         .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set
0567     },
0568     [REGSET_TM_CTAR] = {
0569         .core_note_type = NT_PPC_TM_CTAR, .n = 1,
0570         .size = sizeof(u64), .align = sizeof(u64),
0571         .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set
0572     },
0573     [REGSET_TM_CPPR] = {
0574         .core_note_type = NT_PPC_TM_CPPR, .n = 1,
0575         .size = sizeof(u64), .align = sizeof(u64),
0576         .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set
0577     },
0578     [REGSET_TM_CDSCR] = {
0579         .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
0580         .size = sizeof(u64), .align = sizeof(u64),
0581         .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set
0582     },
0583 #endif
0584 #ifdef CONFIG_PPC64
0585     [REGSET_PPR] = {
0586         .core_note_type = NT_PPC_PPR, .n = 1,
0587         .size = sizeof(u64), .align = sizeof(u64),
0588         .regset_get = ppr_get, .set = ppr_set
0589     },
0590     [REGSET_DSCR] = {
0591         .core_note_type = NT_PPC_DSCR, .n = 1,
0592         .size = sizeof(u64), .align = sizeof(u64),
0593         .regset_get = dscr_get, .set = dscr_set
0594     },
0595 #endif
0596 #ifdef CONFIG_PPC_BOOK3S_64
0597     [REGSET_TAR] = {
0598         .core_note_type = NT_PPC_TAR, .n = 1,
0599         .size = sizeof(u64), .align = sizeof(u64),
0600         .regset_get = tar_get, .set = tar_set
0601     },
0602     [REGSET_EBB] = {
0603         .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
0604         .size = sizeof(u64), .align = sizeof(u64),
0605         .active = ebb_active, .regset_get = ebb_get, .set = ebb_set
0606     },
0607     [REGSET_PMR] = {
0608         .core_note_type = NT_PPC_PMU, .n = ELF_NPMU,
0609         .size = sizeof(u64), .align = sizeof(u64),
0610         .active = pmu_active, .regset_get = pmu_get, .set = pmu_set
0611     },
0612 #endif
0613 #ifdef CONFIG_PPC_MEM_KEYS
0614     [REGSET_PKEY] = {
0615         .core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY,
0616         .size = sizeof(u64), .align = sizeof(u64),
0617         .active = pkey_active, .regset_get = pkey_get, .set = pkey_set
0618     },
0619 #endif
0620 };
0621 
0622 const struct user_regset_view user_ppc_native_view = {
0623     .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
0624     .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
0625 };
0626 
0627 #include <linux/compat.h>
0628 
0629 int gpr32_get_common(struct task_struct *target,
0630              const struct user_regset *regset,
0631              struct membuf to, unsigned long *regs)
0632 {
0633     int i;
0634 
0635     for (i = 0; i < PT_MSR; i++)
0636         membuf_store(&to, (u32)regs[i]);
0637     membuf_store(&to, (u32)get_user_msr(target));
0638     for (i++ ; i < PT_REGS_COUNT; i++)
0639         membuf_store(&to, (u32)regs[i]);
0640     return membuf_zero(&to, (ELF_NGREG - PT_REGS_COUNT) * sizeof(u32));
0641 }
0642 
0643 int gpr32_set_common(struct task_struct *target,
0644              const struct user_regset *regset,
0645              unsigned int pos, unsigned int count,
0646              const void *kbuf, const void __user *ubuf,
0647              unsigned long *regs)
0648 {
0649     const compat_ulong_t *k = kbuf;
0650     const compat_ulong_t __user *u = ubuf;
0651     compat_ulong_t reg;
0652 
0653     if (!kbuf && !user_read_access_begin(u, count))
0654         return -EFAULT;
0655 
0656     pos /= sizeof(reg);
0657     count /= sizeof(reg);
0658 
0659     if (kbuf)
0660         for (; count > 0 && pos < PT_MSR; --count)
0661             regs[pos++] = *k++;
0662     else
0663         for (; count > 0 && pos < PT_MSR; --count) {
0664             unsafe_get_user(reg, u++, Efault);
0665             regs[pos++] = reg;
0666         }
0667 
0668 
0669     if (count > 0 && pos == PT_MSR) {
0670         if (kbuf)
0671             reg = *k++;
0672         else
0673             unsafe_get_user(reg, u++, Efault);
0674         set_user_msr(target, reg);
0675         ++pos;
0676         --count;
0677     }
0678 
0679     if (kbuf) {
0680         for (; count > 0 && pos <= PT_MAX_PUT_REG; --count)
0681             regs[pos++] = *k++;
0682         for (; count > 0 && pos < PT_TRAP; --count, ++pos)
0683             ++k;
0684     } else {
0685         for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
0686             unsafe_get_user(reg, u++, Efault);
0687             regs[pos++] = reg;
0688         }
0689         for (; count > 0 && pos < PT_TRAP; --count, ++pos)
0690             unsafe_get_user(reg, u++, Efault);
0691     }
0692 
0693     if (count > 0 && pos == PT_TRAP) {
0694         if (kbuf)
0695             reg = *k++;
0696         else
0697             unsafe_get_user(reg, u++, Efault);
0698         set_user_trap(target, reg);
0699         ++pos;
0700         --count;
0701     }
0702     if (!kbuf)
0703         user_read_access_end();
0704 
0705     kbuf = k;
0706     ubuf = u;
0707     pos *= sizeof(reg);
0708     count *= sizeof(reg);
0709     return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0710                      (PT_TRAP + 1) * sizeof(reg), -1);
0711 
0712 Efault:
0713     user_read_access_end();
0714     return -EFAULT;
0715 }
0716 
0717 static int gpr32_get(struct task_struct *target,
0718              const struct user_regset *regset,
0719              struct membuf to)
0720 {
0721     if (target->thread.regs == NULL)
0722         return -EIO;
0723 
0724     return gpr32_get_common(target, regset, to,
0725             &target->thread.regs->gpr[0]);
0726 }
0727 
0728 static int gpr32_set(struct task_struct *target,
0729              const struct user_regset *regset,
0730              unsigned int pos, unsigned int count,
0731              const void *kbuf, const void __user *ubuf)
0732 {
0733     if (target->thread.regs == NULL)
0734         return -EIO;
0735 
0736     return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
0737             &target->thread.regs->gpr[0]);
0738 }
0739 
0740 /*
0741  * These are the regset flavors matching the CONFIG_PPC32 native set.
0742  */
0743 static const struct user_regset compat_regsets[] = {
0744     [REGSET_GPR] = {
0745         .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
0746         .size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
0747         .regset_get = gpr32_get, .set = gpr32_set
0748     },
0749     [REGSET_FPR] = {
0750         .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
0751         .size = sizeof(double), .align = sizeof(double),
0752         .regset_get = fpr_get, .set = fpr_set
0753     },
0754 #ifdef CONFIG_ALTIVEC
0755     [REGSET_VMX] = {
0756         .core_note_type = NT_PPC_VMX, .n = 34,
0757         .size = sizeof(vector128), .align = sizeof(vector128),
0758         .active = vr_active, .regset_get = vr_get, .set = vr_set
0759     },
0760 #endif
0761 #ifdef CONFIG_SPE
0762     [REGSET_SPE] = {
0763         .core_note_type = NT_PPC_SPE, .n = 35,
0764         .size = sizeof(u32), .align = sizeof(u32),
0765         .active = evr_active, .regset_get = evr_get, .set = evr_set
0766     },
0767 #endif
0768 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
0769     [REGSET_TM_CGPR] = {
0770         .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
0771         .size = sizeof(long), .align = sizeof(long),
0772         .active = tm_cgpr_active,
0773         .regset_get = tm_cgpr32_get, .set = tm_cgpr32_set
0774     },
0775     [REGSET_TM_CFPR] = {
0776         .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
0777         .size = sizeof(double), .align = sizeof(double),
0778         .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set
0779     },
0780     [REGSET_TM_CVMX] = {
0781         .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
0782         .size = sizeof(vector128), .align = sizeof(vector128),
0783         .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set
0784     },
0785     [REGSET_TM_CVSX] = {
0786         .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
0787         .size = sizeof(double), .align = sizeof(double),
0788         .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set
0789     },
0790     [REGSET_TM_SPR] = {
0791         .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
0792         .size = sizeof(u64), .align = sizeof(u64),
0793         .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set
0794     },
0795     [REGSET_TM_CTAR] = {
0796         .core_note_type = NT_PPC_TM_CTAR, .n = 1,
0797         .size = sizeof(u64), .align = sizeof(u64),
0798         .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set
0799     },
0800     [REGSET_TM_CPPR] = {
0801         .core_note_type = NT_PPC_TM_CPPR, .n = 1,
0802         .size = sizeof(u64), .align = sizeof(u64),
0803         .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set
0804     },
0805     [REGSET_TM_CDSCR] = {
0806         .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
0807         .size = sizeof(u64), .align = sizeof(u64),
0808         .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set
0809     },
0810 #endif
0811 #ifdef CONFIG_PPC64
0812     [REGSET_PPR] = {
0813         .core_note_type = NT_PPC_PPR, .n = 1,
0814         .size = sizeof(u64), .align = sizeof(u64),
0815         .regset_get = ppr_get, .set = ppr_set
0816     },
0817     [REGSET_DSCR] = {
0818         .core_note_type = NT_PPC_DSCR, .n = 1,
0819         .size = sizeof(u64), .align = sizeof(u64),
0820         .regset_get = dscr_get, .set = dscr_set
0821     },
0822 #endif
0823 #ifdef CONFIG_PPC_BOOK3S_64
0824     [REGSET_TAR] = {
0825         .core_note_type = NT_PPC_TAR, .n = 1,
0826         .size = sizeof(u64), .align = sizeof(u64),
0827         .regset_get = tar_get, .set = tar_set
0828     },
0829     [REGSET_EBB] = {
0830         .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
0831         .size = sizeof(u64), .align = sizeof(u64),
0832         .active = ebb_active, .regset_get = ebb_get, .set = ebb_set
0833     },
0834 #endif
0835 };
0836 
0837 static const struct user_regset_view user_ppc_compat_view = {
0838     .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI,
0839     .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets)
0840 };
0841 
0842 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
0843 {
0844     if (IS_ENABLED(CONFIG_COMPAT) && is_tsk_32bit_task(task))
0845         return &user_ppc_compat_view;
0846     return &user_ppc_native_view;
0847 }