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