1
2
3#include <linux/regset.h>
4
5#include <asm/switch_to.h>
6#include <asm/tm.h>
7#include <asm/asm-prototypes.h>
8
9#include "ptrace-decl.h"
10
11void flush_tmregs_to_thread(struct task_struct *tsk)
12{
13
14
15
16
17
18
19
20
21 if (!cpu_has_feature(CPU_FTR_TM) || tsk != current)
22 return;
23
24 if (MSR_TM_SUSPENDED(mfmsr())) {
25 tm_reclaim_current(TM_CAUSE_SIGNAL);
26 } else {
27 tm_enable();
28 tm_save_sprs(&tsk->thread);
29 }
30}
31
32static unsigned long get_user_ckpt_msr(struct task_struct *task)
33{
34 return task->thread.ckpt_regs.msr | task->thread.fpexc_mode;
35}
36
37static int set_user_ckpt_msr(struct task_struct *task, unsigned long msr)
38{
39 task->thread.ckpt_regs.msr &= ~MSR_DEBUGCHANGE;
40 task->thread.ckpt_regs.msr |= msr & MSR_DEBUGCHANGE;
41 return 0;
42}
43
44static int set_user_ckpt_trap(struct task_struct *task, unsigned long trap)
45{
46 task->thread.ckpt_regs.trap = trap & 0xfff0;
47 return 0;
48}
49
50
51
52
53
54
55
56
57
58int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset)
59{
60 if (!cpu_has_feature(CPU_FTR_TM))
61 return -ENODEV;
62
63 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
64 return 0;
65
66 return regset->n;
67}
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
90 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
91{
92 int ret;
93
94 if (!cpu_has_feature(CPU_FTR_TM))
95 return -ENODEV;
96
97 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
98 return -ENODATA;
99
100 flush_tmregs_to_thread(target);
101 flush_fp_to_thread(target);
102 flush_altivec_to_thread(target);
103
104 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
105 &target->thread.ckpt_regs,
106 0, offsetof(struct pt_regs, msr));
107 if (!ret) {
108 unsigned long msr = get_user_ckpt_msr(target);
109
110 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &msr,
111 offsetof(struct pt_regs, msr),
112 offsetof(struct pt_regs, msr) +
113 sizeof(msr));
114 }
115
116 BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
117 offsetof(struct pt_regs, msr) + sizeof(long));
118
119 if (!ret)
120 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
121 &target->thread.ckpt_regs.orig_gpr3,
122 offsetof(struct pt_regs, orig_gpr3),
123 sizeof(struct user_pt_regs));
124 if (!ret)
125 ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
126 sizeof(struct user_pt_regs), -1);
127
128 return ret;
129}
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
152 unsigned int pos, unsigned int count,
153 const void *kbuf, const void __user *ubuf)
154{
155 unsigned long reg;
156 int ret;
157
158 if (!cpu_has_feature(CPU_FTR_TM))
159 return -ENODEV;
160
161 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
162 return -ENODATA;
163
164 flush_tmregs_to_thread(target);
165 flush_fp_to_thread(target);
166 flush_altivec_to_thread(target);
167
168 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
169 &target->thread.ckpt_regs,
170 0, PT_MSR * sizeof(reg));
171
172 if (!ret && count > 0) {
173 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
174 PT_MSR * sizeof(reg),
175 (PT_MSR + 1) * sizeof(reg));
176 if (!ret)
177 ret = set_user_ckpt_msr(target, reg);
178 }
179
180 BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
181 offsetof(struct pt_regs, msr) + sizeof(long));
182
183 if (!ret)
184 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
185 &target->thread.ckpt_regs.orig_gpr3,
186 PT_ORIG_R3 * sizeof(reg),
187 (PT_MAX_PUT_REG + 1) * sizeof(reg));
188
189 if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
190 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
191 (PT_MAX_PUT_REG + 1) * sizeof(reg),
192 PT_TRAP * sizeof(reg));
193
194 if (!ret && count > 0) {
195 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
196 PT_TRAP * sizeof(reg),
197 (PT_TRAP + 1) * sizeof(reg));
198 if (!ret)
199 ret = set_user_ckpt_trap(target, reg);
200 }
201
202 if (!ret)
203 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
204 (PT_TRAP + 1) * sizeof(reg), -1);
205
206 return ret;
207}
208
209
210
211
212
213
214
215
216
217int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset)
218{
219 if (!cpu_has_feature(CPU_FTR_TM))
220 return -ENODEV;
221
222 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
223 return 0;
224
225 return regset->n;
226}
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset,
250 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
251{
252 u64 buf[33];
253 int i;
254
255 if (!cpu_has_feature(CPU_FTR_TM))
256 return -ENODEV;
257
258 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
259 return -ENODATA;
260
261 flush_tmregs_to_thread(target);
262 flush_fp_to_thread(target);
263 flush_altivec_to_thread(target);
264
265
266 for (i = 0; i < 32 ; i++)
267 buf[i] = target->thread.TS_CKFPR(i);
268 buf[32] = target->thread.ckfp_state.fpscr;
269 return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
270}
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset,
294 unsigned int pos, unsigned int count,
295 const void *kbuf, const void __user *ubuf)
296{
297 u64 buf[33];
298 int i;
299
300 if (!cpu_has_feature(CPU_FTR_TM))
301 return -ENODEV;
302
303 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
304 return -ENODATA;
305
306 flush_tmregs_to_thread(target);
307 flush_fp_to_thread(target);
308 flush_altivec_to_thread(target);
309
310 for (i = 0; i < 32; i++)
311 buf[i] = target->thread.TS_CKFPR(i);
312 buf[32] = target->thread.ckfp_state.fpscr;
313
314
315 i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
316 if (i)
317 return i;
318 for (i = 0; i < 32 ; i++)
319 target->thread.TS_CKFPR(i) = buf[i];
320 target->thread.ckfp_state.fpscr = buf[32];
321 return 0;
322}
323
324
325
326
327
328
329
330
331
332int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset)
333{
334 if (!cpu_has_feature(CPU_FTR_TM))
335 return -ENODEV;
336
337 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
338 return 0;
339
340 return regset->n;
341}
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset,
366 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
367{
368 int ret;
369
370 BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
371
372 if (!cpu_has_feature(CPU_FTR_TM))
373 return -ENODEV;
374
375 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
376 return -ENODATA;
377
378
379 flush_tmregs_to_thread(target);
380 flush_fp_to_thread(target);
381 flush_altivec_to_thread(target);
382
383 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &target->thread.ckvr_state,
384 0, 33 * sizeof(vector128));
385 if (!ret) {
386
387
388
389 union {
390 elf_vrreg_t reg;
391 u32 word;
392 } vrsave;
393 memset(&vrsave, 0, sizeof(vrsave));
394 vrsave.word = target->thread.ckvrsave;
395 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &vrsave,
396 33 * sizeof(vector128), -1);
397 }
398
399 return ret;
400}
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset,
425 unsigned int pos, unsigned int count,
426 const void *kbuf, const void __user *ubuf)
427{
428 int ret;
429
430 BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
431
432 if (!cpu_has_feature(CPU_FTR_TM))
433 return -ENODEV;
434
435 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
436 return -ENODATA;
437
438 flush_tmregs_to_thread(target);
439 flush_fp_to_thread(target);
440 flush_altivec_to_thread(target);
441
442 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ckvr_state,
443 0, 33 * sizeof(vector128));
444 if (!ret && count > 0) {
445
446
447
448 union {
449 elf_vrreg_t reg;
450 u32 word;
451 } vrsave;
452 memset(&vrsave, 0, sizeof(vrsave));
453 vrsave.word = target->thread.ckvrsave;
454 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
455 33 * sizeof(vector128), -1);
456 if (!ret)
457 target->thread.ckvrsave = vrsave.word;
458 }
459
460 return ret;
461}
462
463
464
465
466
467
468
469
470
471int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset)
472{
473 if (!cpu_has_feature(CPU_FTR_TM))
474 return -ENODEV;
475
476 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
477 return 0;
478
479 flush_vsx_to_thread(target);
480 return target->thread.used_vsr ? regset->n : 0;
481}
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503int tm_cvsx_get(struct task_struct *target, const struct user_regset *regset,
504 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
505{
506 u64 buf[32];
507 int ret, i;
508
509 if (!cpu_has_feature(CPU_FTR_TM))
510 return -ENODEV;
511
512 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
513 return -ENODATA;
514
515
516 flush_tmregs_to_thread(target);
517 flush_fp_to_thread(target);
518 flush_altivec_to_thread(target);
519 flush_vsx_to_thread(target);
520
521 for (i = 0; i < 32 ; i++)
522 buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
523 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
524 buf, 0, 32 * sizeof(double));
525
526 return ret;
527}
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549int tm_cvsx_set(struct task_struct *target, const struct user_regset *regset,
550 unsigned int pos, unsigned int count,
551 const void *kbuf, const void __user *ubuf)
552{
553 u64 buf[32];
554 int ret, i;
555
556 if (!cpu_has_feature(CPU_FTR_TM))
557 return -ENODEV;
558
559 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
560 return -ENODATA;
561
562
563 flush_tmregs_to_thread(target);
564 flush_fp_to_thread(target);
565 flush_altivec_to_thread(target);
566 flush_vsx_to_thread(target);
567
568 for (i = 0; i < 32 ; i++)
569 buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
570
571 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
572 buf, 0, 32 * sizeof(double));
573 if (!ret)
574 for (i = 0; i < 32 ; i++)
575 target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
576
577 return ret;
578}
579
580
581
582
583
584
585
586
587
588int tm_spr_active(struct task_struct *target, const struct user_regset *regset)
589{
590 if (!cpu_has_feature(CPU_FTR_TM))
591 return -ENODEV;
592
593 return regset->n;
594}
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614int tm_spr_get(struct task_struct *target, const struct user_regset *regset,
615 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
616{
617 int ret;
618
619
620 BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
621 BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
622 BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
623
624 if (!cpu_has_feature(CPU_FTR_TM))
625 return -ENODEV;
626
627
628 flush_tmregs_to_thread(target);
629 flush_fp_to_thread(target);
630 flush_altivec_to_thread(target);
631
632
633 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
634 &target->thread.tm_tfhar, 0, sizeof(u64));
635
636
637 if (!ret)
638 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
639 &target->thread.tm_texasr, sizeof(u64),
640 2 * sizeof(u64));
641
642
643 if (!ret)
644 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
645 &target->thread.tm_tfiar,
646 2 * sizeof(u64), 3 * sizeof(u64));
647 return ret;
648}
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668int tm_spr_set(struct task_struct *target, const struct user_regset *regset,
669 unsigned int pos, unsigned int count,
670 const void *kbuf, const void __user *ubuf)
671{
672 int ret;
673
674
675 BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
676 BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
677 BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
678
679 if (!cpu_has_feature(CPU_FTR_TM))
680 return -ENODEV;
681
682
683 flush_tmregs_to_thread(target);
684 flush_fp_to_thread(target);
685 flush_altivec_to_thread(target);
686
687
688 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
689 &target->thread.tm_tfhar, 0, sizeof(u64));
690
691
692 if (!ret)
693 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
694 &target->thread.tm_texasr, sizeof(u64),
695 2 * sizeof(u64));
696
697
698 if (!ret)
699 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
700 &target->thread.tm_tfiar,
701 2 * sizeof(u64), 3 * sizeof(u64));
702 return ret;
703}
704
705int tm_tar_active(struct task_struct *target, const struct user_regset *regset)
706{
707 if (!cpu_has_feature(CPU_FTR_TM))
708 return -ENODEV;
709
710 if (MSR_TM_ACTIVE(target->thread.regs->msr))
711 return regset->n;
712
713 return 0;
714}
715
716int tm_tar_get(struct task_struct *target, const struct user_regset *regset,
717 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
718{
719 int ret;
720
721 if (!cpu_has_feature(CPU_FTR_TM))
722 return -ENODEV;
723
724 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
725 return -ENODATA;
726
727 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
728 &target->thread.tm_tar, 0, sizeof(u64));
729 return ret;
730}
731
732int tm_tar_set(struct task_struct *target, const struct user_regset *regset,
733 unsigned int pos, unsigned int count,
734 const void *kbuf, const void __user *ubuf)
735{
736 int ret;
737
738 if (!cpu_has_feature(CPU_FTR_TM))
739 return -ENODEV;
740
741 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
742 return -ENODATA;
743
744 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
745 &target->thread.tm_tar, 0, sizeof(u64));
746 return ret;
747}
748
749int tm_ppr_active(struct task_struct *target, const struct user_regset *regset)
750{
751 if (!cpu_has_feature(CPU_FTR_TM))
752 return -ENODEV;
753
754 if (MSR_TM_ACTIVE(target->thread.regs->msr))
755 return regset->n;
756
757 return 0;
758}
759
760
761int tm_ppr_get(struct task_struct *target, const struct user_regset *regset,
762 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
763{
764 int ret;
765
766 if (!cpu_has_feature(CPU_FTR_TM))
767 return -ENODEV;
768
769 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
770 return -ENODATA;
771
772 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
773 &target->thread.tm_ppr, 0, sizeof(u64));
774 return ret;
775}
776
777int tm_ppr_set(struct task_struct *target, const struct user_regset *regset,
778 unsigned int pos, unsigned int count,
779 const void *kbuf, const void __user *ubuf)
780{
781 int ret;
782
783 if (!cpu_has_feature(CPU_FTR_TM))
784 return -ENODEV;
785
786 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
787 return -ENODATA;
788
789 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
790 &target->thread.tm_ppr, 0, sizeof(u64));
791 return ret;
792}
793
794int tm_dscr_active(struct task_struct *target, const struct user_regset *regset)
795{
796 if (!cpu_has_feature(CPU_FTR_TM))
797 return -ENODEV;
798
799 if (MSR_TM_ACTIVE(target->thread.regs->msr))
800 return regset->n;
801
802 return 0;
803}
804
805int tm_dscr_get(struct task_struct *target, const struct user_regset *regset,
806 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
807{
808 int ret;
809
810 if (!cpu_has_feature(CPU_FTR_TM))
811 return -ENODEV;
812
813 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
814 return -ENODATA;
815
816 ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
817 &target->thread.tm_dscr, 0, sizeof(u64));
818 return ret;
819}
820
821int tm_dscr_set(struct task_struct *target, const struct user_regset *regset,
822 unsigned int pos, unsigned int count,
823 const void *kbuf, const void __user *ubuf)
824{
825 int ret;
826
827 if (!cpu_has_feature(CPU_FTR_TM))
828 return -ENODEV;
829
830 if (!MSR_TM_ACTIVE(target->thread.regs->msr))
831 return -ENODATA;
832
833 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
834 &target->thread.tm_dscr, 0, sizeof(u64));
835 return ret;
836}
837
838int tm_cgpr32_get(struct task_struct *target, const struct user_regset *regset,
839 unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf)
840{
841 return gpr32_get_common(target, regset, pos, count, kbuf, ubuf,
842 &target->thread.ckpt_regs.gpr[0]);
843}
844
845int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset,
846 unsigned int pos, unsigned int count,
847 const void *kbuf, const void __user *ubuf)
848{
849 return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
850 &target->thread.ckpt_regs.gpr[0]);
851}
852