0001
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
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
0074
0075
0076
0077
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
0090
0091
0092
0093
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
0106
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
0149
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
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
0177
0178
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
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, ®,
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, ®,
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
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
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
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
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
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
0495
0496
0497
0498
0499
0500
0501
0502
0503 target->thread.regs->amr = (new_amr & default_uamor) |
0504 (target->thread.regs->amr & ~default_uamor);
0505
0506 return 0;
0507 }
0508 #endif
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
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 }