0001
0002
0003 #include <linux/regset.h>
0004
0005 #include <asm/switch_to.h>
0006 #include <asm/tm.h>
0007 #include <asm/asm-prototypes.h>
0008
0009 #include "ptrace-decl.h"
0010
0011 void flush_tmregs_to_thread(struct task_struct *tsk)
0012 {
0013
0014
0015
0016
0017
0018
0019
0020
0021 if (!cpu_has_feature(CPU_FTR_TM) || tsk != current)
0022 return;
0023
0024 if (MSR_TM_SUSPENDED(mfmsr())) {
0025 tm_reclaim_current(TM_CAUSE_SIGNAL);
0026 } else {
0027 tm_enable();
0028 tm_save_sprs(&tsk->thread);
0029 }
0030 }
0031
0032 static unsigned long get_user_ckpt_msr(struct task_struct *task)
0033 {
0034 return task->thread.ckpt_regs.msr | task->thread.fpexc_mode;
0035 }
0036
0037 static int set_user_ckpt_msr(struct task_struct *task, unsigned long msr)
0038 {
0039 task->thread.ckpt_regs.msr &= ~MSR_DEBUGCHANGE;
0040 task->thread.ckpt_regs.msr |= msr & MSR_DEBUGCHANGE;
0041 return 0;
0042 }
0043
0044 static int set_user_ckpt_trap(struct task_struct *task, unsigned long trap)
0045 {
0046 set_trap(&task->thread.ckpt_regs, trap);
0047 return 0;
0048 }
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset)
0059 {
0060 if (!cpu_has_feature(CPU_FTR_TM))
0061 return -ENODEV;
0062
0063 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0064 return 0;
0065
0066 return regset->n;
0067 }
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086 int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
0087 struct membuf to)
0088 {
0089 struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr));
0090 #ifdef CONFIG_PPC64
0091 struct membuf to_softe = membuf_at(&to, offsetof(struct pt_regs, softe));
0092 #endif
0093
0094 if (!cpu_has_feature(CPU_FTR_TM))
0095 return -ENODEV;
0096
0097 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0098 return -ENODATA;
0099
0100 flush_tmregs_to_thread(target);
0101 flush_fp_to_thread(target);
0102 flush_altivec_to_thread(target);
0103
0104 membuf_write(&to, &target->thread.ckpt_regs, sizeof(struct user_pt_regs));
0105
0106 membuf_store(&to_msr, get_user_ckpt_msr(target));
0107 #ifdef CONFIG_PPC64
0108 membuf_store(&to_softe, 0x1ul);
0109 #endif
0110 return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) -
0111 sizeof(struct user_pt_regs));
0112 }
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134 int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
0135 unsigned int pos, unsigned int count,
0136 const void *kbuf, const void __user *ubuf)
0137 {
0138 unsigned long reg;
0139 int ret;
0140
0141 if (!cpu_has_feature(CPU_FTR_TM))
0142 return -ENODEV;
0143
0144 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0145 return -ENODATA;
0146
0147 flush_tmregs_to_thread(target);
0148 flush_fp_to_thread(target);
0149 flush_altivec_to_thread(target);
0150
0151 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0152 &target->thread.ckpt_regs,
0153 0, PT_MSR * sizeof(reg));
0154
0155 if (!ret && count > 0) {
0156 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
0157 PT_MSR * sizeof(reg),
0158 (PT_MSR + 1) * sizeof(reg));
0159 if (!ret)
0160 ret = set_user_ckpt_msr(target, reg);
0161 }
0162
0163 BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
0164 offsetof(struct pt_regs, msr) + sizeof(long));
0165
0166 if (!ret)
0167 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0168 &target->thread.ckpt_regs.orig_gpr3,
0169 PT_ORIG_R3 * sizeof(reg),
0170 (PT_MAX_PUT_REG + 1) * sizeof(reg));
0171
0172 if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
0173 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0174 (PT_MAX_PUT_REG + 1) * sizeof(reg),
0175 PT_TRAP * sizeof(reg));
0176
0177 if (!ret && count > 0) {
0178 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
0179 PT_TRAP * sizeof(reg),
0180 (PT_TRAP + 1) * sizeof(reg));
0181 if (!ret)
0182 ret = set_user_ckpt_trap(target, reg);
0183 }
0184
0185 if (!ret)
0186 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0187 (PT_TRAP + 1) * sizeof(reg), -1);
0188
0189 return ret;
0190 }
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset)
0201 {
0202 if (!cpu_has_feature(CPU_FTR_TM))
0203 return -ENODEV;
0204
0205 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0206 return 0;
0207
0208 return regset->n;
0209 }
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229 int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset,
0230 struct membuf to)
0231 {
0232 u64 buf[33];
0233 int i;
0234
0235 if (!cpu_has_feature(CPU_FTR_TM))
0236 return -ENODEV;
0237
0238 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0239 return -ENODATA;
0240
0241 flush_tmregs_to_thread(target);
0242 flush_fp_to_thread(target);
0243 flush_altivec_to_thread(target);
0244
0245
0246 for (i = 0; i < 32 ; i++)
0247 buf[i] = target->thread.TS_CKFPR(i);
0248 buf[32] = target->thread.ckfp_state.fpscr;
0249 return membuf_write(&to, buf, sizeof(buf));
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273 int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset,
0274 unsigned int pos, unsigned int count,
0275 const void *kbuf, const void __user *ubuf)
0276 {
0277 u64 buf[33];
0278 int i;
0279
0280 if (!cpu_has_feature(CPU_FTR_TM))
0281 return -ENODEV;
0282
0283 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0284 return -ENODATA;
0285
0286 flush_tmregs_to_thread(target);
0287 flush_fp_to_thread(target);
0288 flush_altivec_to_thread(target);
0289
0290 for (i = 0; i < 32; i++)
0291 buf[i] = target->thread.TS_CKFPR(i);
0292 buf[32] = target->thread.ckfp_state.fpscr;
0293
0294
0295 i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
0296 if (i)
0297 return i;
0298 for (i = 0; i < 32 ; i++)
0299 target->thread.TS_CKFPR(i) = buf[i];
0300 target->thread.ckfp_state.fpscr = buf[32];
0301 return 0;
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312 int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset)
0313 {
0314 if (!cpu_has_feature(CPU_FTR_TM))
0315 return -ENODEV;
0316
0317 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0318 return 0;
0319
0320 return regset->n;
0321 }
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342 int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset,
0343 struct membuf to)
0344 {
0345 union {
0346 elf_vrreg_t reg;
0347 u32 word;
0348 } vrsave;
0349 BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
0350
0351 if (!cpu_has_feature(CPU_FTR_TM))
0352 return -ENODEV;
0353
0354 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0355 return -ENODATA;
0356
0357
0358 flush_tmregs_to_thread(target);
0359 flush_fp_to_thread(target);
0360 flush_altivec_to_thread(target);
0361
0362 membuf_write(&to, &target->thread.ckvr_state, 33 * sizeof(vector128));
0363
0364
0365
0366 memset(&vrsave, 0, sizeof(vrsave));
0367 vrsave.word = target->thread.ckvrsave;
0368 return membuf_write(&to, &vrsave, sizeof(vrsave));
0369 }
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393 int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset,
0394 unsigned int pos, unsigned int count,
0395 const void *kbuf, const void __user *ubuf)
0396 {
0397 int ret;
0398
0399 BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
0400
0401 if (!cpu_has_feature(CPU_FTR_TM))
0402 return -ENODEV;
0403
0404 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0405 return -ENODATA;
0406
0407 flush_tmregs_to_thread(target);
0408 flush_fp_to_thread(target);
0409 flush_altivec_to_thread(target);
0410
0411 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ckvr_state,
0412 0, 33 * sizeof(vector128));
0413 if (!ret && count > 0) {
0414
0415
0416
0417 union {
0418 elf_vrreg_t reg;
0419 u32 word;
0420 } vrsave;
0421 memset(&vrsave, 0, sizeof(vrsave));
0422 vrsave.word = target->thread.ckvrsave;
0423 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
0424 33 * sizeof(vector128), -1);
0425 if (!ret)
0426 target->thread.ckvrsave = vrsave.word;
0427 }
0428
0429 return ret;
0430 }
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440 int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset)
0441 {
0442 if (!cpu_has_feature(CPU_FTR_TM))
0443 return -ENODEV;
0444
0445 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0446 return 0;
0447
0448 flush_vsx_to_thread(target);
0449 return target->thread.used_vsr ? regset->n : 0;
0450 }
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469 int tm_cvsx_get(struct task_struct *target, const struct user_regset *regset,
0470 struct membuf to)
0471 {
0472 u64 buf[32];
0473 int i;
0474
0475 if (!cpu_has_feature(CPU_FTR_TM))
0476 return -ENODEV;
0477
0478 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0479 return -ENODATA;
0480
0481
0482 flush_tmregs_to_thread(target);
0483 flush_fp_to_thread(target);
0484 flush_altivec_to_thread(target);
0485 flush_vsx_to_thread(target);
0486
0487 for (i = 0; i < 32 ; i++)
0488 buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
0489 return membuf_write(&to, buf, 32 * sizeof(double));
0490 }
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512 int tm_cvsx_set(struct task_struct *target, const struct user_regset *regset,
0513 unsigned int pos, unsigned int count,
0514 const void *kbuf, const void __user *ubuf)
0515 {
0516 u64 buf[32];
0517 int ret, i;
0518
0519 if (!cpu_has_feature(CPU_FTR_TM))
0520 return -ENODEV;
0521
0522 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0523 return -ENODATA;
0524
0525
0526 flush_tmregs_to_thread(target);
0527 flush_fp_to_thread(target);
0528 flush_altivec_to_thread(target);
0529 flush_vsx_to_thread(target);
0530
0531 for (i = 0; i < 32 ; i++)
0532 buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
0533
0534 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0535 buf, 0, 32 * sizeof(double));
0536 if (!ret)
0537 for (i = 0; i < 32 ; i++)
0538 target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
0539
0540 return ret;
0541 }
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 int tm_spr_active(struct task_struct *target, const struct user_regset *regset)
0552 {
0553 if (!cpu_has_feature(CPU_FTR_TM))
0554 return -ENODEV;
0555
0556 return regset->n;
0557 }
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574 int tm_spr_get(struct task_struct *target, const struct user_regset *regset,
0575 struct membuf to)
0576 {
0577
0578 BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
0579 BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
0580 BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
0581
0582 if (!cpu_has_feature(CPU_FTR_TM))
0583 return -ENODEV;
0584
0585
0586 flush_tmregs_to_thread(target);
0587 flush_fp_to_thread(target);
0588 flush_altivec_to_thread(target);
0589
0590
0591 membuf_write(&to, &target->thread.tm_tfhar, sizeof(u64));
0592
0593 membuf_write(&to, &target->thread.tm_texasr, sizeof(u64));
0594
0595 return membuf_write(&to, &target->thread.tm_tfiar, sizeof(u64));
0596 }
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616 int tm_spr_set(struct task_struct *target, const struct user_regset *regset,
0617 unsigned int pos, unsigned int count,
0618 const void *kbuf, const void __user *ubuf)
0619 {
0620 int ret;
0621
0622
0623 BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
0624 BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
0625 BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
0626
0627 if (!cpu_has_feature(CPU_FTR_TM))
0628 return -ENODEV;
0629
0630
0631 flush_tmregs_to_thread(target);
0632 flush_fp_to_thread(target);
0633 flush_altivec_to_thread(target);
0634
0635
0636 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0637 &target->thread.tm_tfhar, 0, sizeof(u64));
0638
0639
0640 if (!ret)
0641 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0642 &target->thread.tm_texasr, sizeof(u64),
0643 2 * sizeof(u64));
0644
0645
0646 if (!ret)
0647 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0648 &target->thread.tm_tfiar,
0649 2 * sizeof(u64), 3 * sizeof(u64));
0650 return ret;
0651 }
0652
0653 int tm_tar_active(struct task_struct *target, const struct user_regset *regset)
0654 {
0655 if (!cpu_has_feature(CPU_FTR_TM))
0656 return -ENODEV;
0657
0658 if (MSR_TM_ACTIVE(target->thread.regs->msr))
0659 return regset->n;
0660
0661 return 0;
0662 }
0663
0664 int tm_tar_get(struct task_struct *target, const struct user_regset *regset,
0665 struct membuf to)
0666 {
0667 if (!cpu_has_feature(CPU_FTR_TM))
0668 return -ENODEV;
0669
0670 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0671 return -ENODATA;
0672
0673 return membuf_write(&to, &target->thread.tm_tar, sizeof(u64));
0674 }
0675
0676 int tm_tar_set(struct task_struct *target, const struct user_regset *regset,
0677 unsigned int pos, unsigned int count,
0678 const void *kbuf, const void __user *ubuf)
0679 {
0680 int ret;
0681
0682 if (!cpu_has_feature(CPU_FTR_TM))
0683 return -ENODEV;
0684
0685 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0686 return -ENODATA;
0687
0688 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0689 &target->thread.tm_tar, 0, sizeof(u64));
0690 return ret;
0691 }
0692
0693 int tm_ppr_active(struct task_struct *target, const struct user_regset *regset)
0694 {
0695 if (!cpu_has_feature(CPU_FTR_TM))
0696 return -ENODEV;
0697
0698 if (MSR_TM_ACTIVE(target->thread.regs->msr))
0699 return regset->n;
0700
0701 return 0;
0702 }
0703
0704
0705 int tm_ppr_get(struct task_struct *target, const struct user_regset *regset,
0706 struct membuf to)
0707 {
0708 if (!cpu_has_feature(CPU_FTR_TM))
0709 return -ENODEV;
0710
0711 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0712 return -ENODATA;
0713
0714 return membuf_write(&to, &target->thread.tm_ppr, sizeof(u64));
0715 }
0716
0717 int tm_ppr_set(struct task_struct *target, const struct user_regset *regset,
0718 unsigned int pos, unsigned int count,
0719 const void *kbuf, const void __user *ubuf)
0720 {
0721 int ret;
0722
0723 if (!cpu_has_feature(CPU_FTR_TM))
0724 return -ENODEV;
0725
0726 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0727 return -ENODATA;
0728
0729 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0730 &target->thread.tm_ppr, 0, sizeof(u64));
0731 return ret;
0732 }
0733
0734 int tm_dscr_active(struct task_struct *target, const struct user_regset *regset)
0735 {
0736 if (!cpu_has_feature(CPU_FTR_TM))
0737 return -ENODEV;
0738
0739 if (MSR_TM_ACTIVE(target->thread.regs->msr))
0740 return regset->n;
0741
0742 return 0;
0743 }
0744
0745 int tm_dscr_get(struct task_struct *target, const struct user_regset *regset,
0746 struct membuf to)
0747 {
0748 if (!cpu_has_feature(CPU_FTR_TM))
0749 return -ENODEV;
0750
0751 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0752 return -ENODATA;
0753
0754 return membuf_write(&to, &target->thread.tm_dscr, sizeof(u64));
0755 }
0756
0757 int tm_dscr_set(struct task_struct *target, const struct user_regset *regset,
0758 unsigned int pos, unsigned int count,
0759 const void *kbuf, const void __user *ubuf)
0760 {
0761 int ret;
0762
0763 if (!cpu_has_feature(CPU_FTR_TM))
0764 return -ENODEV;
0765
0766 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
0767 return -ENODATA;
0768
0769 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0770 &target->thread.tm_dscr, 0, sizeof(u64));
0771 return ret;
0772 }
0773
0774 int tm_cgpr32_get(struct task_struct *target, const struct user_regset *regset,
0775 struct membuf to)
0776 {
0777 gpr32_get_common(target, regset, to,
0778 &target->thread.ckpt_regs.gpr[0]);
0779 return membuf_zero(&to, ELF_NGREG * sizeof(u32));
0780 }
0781
0782 int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset,
0783 unsigned int pos, unsigned int count,
0784 const void *kbuf, const void __user *ubuf)
0785 {
0786 return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
0787 &target->thread.ckpt_regs.gpr[0]);
0788 }