~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/kernel/ptrace/ptrace-tm.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-or-later
  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 
 11 void flush_tmregs_to_thread(struct task_struct *tsk)
 12 {
 13         /*
 14          * If task is not current, it will have been flushed already to
 15          * its thread_struct during __switch_to().
 16          *
 17          * A reclaim flushes ALL the state or if not in TM save TM SPRs
 18          * in the appropriate thread structures from live.
 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 
 32 static unsigned long get_user_ckpt_msr(struct task_struct *task)
 33 {
 34         return task->thread.ckpt_regs.msr | task->thread.fpexc_mode;
 35 }
 36 
 37 static 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 
 44 static 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  * tm_cgpr_active - get active number of registers in CGPR
 52  * @target:     The target task.
 53  * @regset:     The user regset structure.
 54  *
 55  * This function checks for the active number of available
 56  * regisers in transaction checkpointed GPR category.
 57  */
 58 int 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  * tm_cgpr_get - get CGPR registers
 71  * @target:     The target task.
 72  * @regset:     The user regset structure.
 73  * @to:         Destination of copy.
 74  *
 75  * This function gets transaction checkpointed GPR registers.
 76  *
 77  * When the transaction is active, 'ckpt_regs' holds all the checkpointed
 78  * GPR register values for the current transaction to fall back on if it
 79  * aborts in between. This function gets those checkpointed GPR registers.
 80  * The userspace interface buffer layout is as follows.
 81  *
 82  * struct data {
 83  *      struct pt_regs ckpt_regs;
 84  * };
 85  */
 86 int 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  * tm_cgpr_set - set the CGPR registers
116  * @target:     The target task.
117  * @regset:     The user regset structure.
118  * @pos:        The buffer position.
119  * @count:      Number of bytes to copy.
120  * @kbuf:       Kernel buffer to copy into.
121  * @ubuf:       User buffer to copy from.
122  *
123  * This function sets in transaction checkpointed GPR registers.
124  *
125  * When the transaction is active, 'ckpt_regs' holds the checkpointed
126  * GPR register values for the current transaction to fall back on if it
127  * aborts in between. This function sets those checkpointed GPR registers.
128  * The userspace interface buffer layout is as follows.
129  *
130  * struct data {
131  *      struct pt_regs ckpt_regs;
132  * };
133  */
134 int 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, &reg,
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                 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, &reg,
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                 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
187                                           (PT_TRAP + 1) * sizeof(reg), -1);
188 
189         return ret;
190 }
191 
192 /**
193  * tm_cfpr_active - get active number of registers in CFPR
194  * @target:     The target task.
195  * @regset:     The user regset structure.
196  *
197  * This function checks for the active number of available
198  * regisers in transaction checkpointed FPR category.
199  */
200 int 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  * tm_cfpr_get - get CFPR registers
213  * @target:     The target task.
214  * @regset:     The user regset structure.
215  * @to:         Destination of copy.
216  *
217  * This function gets in transaction checkpointed FPR registers.
218  *
219  * When the transaction is active 'ckfp_state' holds the checkpointed
220  * values for the current transaction to fall back on if it aborts
221  * in between. This function gets those checkpointed FPR registers.
222  * The userspace interface buffer layout is as follows.
223  *
224  * struct data {
225  *      u64     fpr[32];
226  *      u64     fpscr;
227  *};
228  */
229 int 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         /* copy to local buffer then write that out */
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  * tm_cfpr_set - set CFPR registers
254  * @target:     The target task.
255  * @regset:     The user regset structure.
256  * @pos:        The buffer position.
257  * @count:      Number of bytes to copy.
258  * @kbuf:       Kernel buffer to copy into.
259  * @ubuf:       User buffer to copy from.
260  *
261  * This function sets in transaction checkpointed FPR registers.
262  *
263  * When the transaction is active 'ckfp_state' holds the checkpointed
264  * FPR register values for the current transaction to fall back on
265  * if it aborts in between. This function sets these checkpointed
266  * FPR registers. The userspace interface buffer layout is as follows.
267  *
268  * struct data {
269  *      u64     fpr[32];
270  *      u64     fpscr;
271  *};
272  */
273 int 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         /* copy to local buffer then write that out */
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  * tm_cvmx_active - get active number of registers in CVMX
306  * @target:     The target task.
307  * @regset:     The user regset structure.
308  *
309  * This function checks for the active number of available
310  * regisers in checkpointed VMX category.
311  */
312 int 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  * tm_cvmx_get - get CMVX registers
325  * @target:     The target task.
326  * @regset:     The user regset structure.
327  * @to:         Destination of copy.
328  *
329  * This function gets in transaction checkpointed VMX registers.
330  *
331  * When the transaction is active 'ckvr_state' and 'ckvrsave' hold
332  * the checkpointed values for the current transaction to fall
333  * back on if it aborts in between. The userspace interface buffer
334  * layout is as follows.
335  *
336  * struct data {
337  *      vector128       vr[32];
338  *      vector128       vscr;
339  *      vector128       vrsave;
340  *};
341  */
342 int 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         /* Flush the state */
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          * Copy out only the low-order word of vrsave.
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  * tm_cvmx_set - set CMVX registers
373  * @target:     The target task.
374  * @regset:     The user regset structure.
375  * @pos:        The buffer position.
376  * @count:      Number of bytes to copy.
377  * @kbuf:       Kernel buffer to copy into.
378  * @ubuf:       User buffer to copy from.
379  *
380  * This function sets in transaction checkpointed VMX registers.
381  *
382  * When the transaction is active 'ckvr_state' and 'ckvrsave' hold
383  * the checkpointed values for the current transaction to fall
384  * back on if it aborts in between. The userspace interface buffer
385  * layout is as follows.
386  *
387  * struct data {
388  *      vector128       vr[32];
389  *      vector128       vscr;
390  *      vector128       vrsave;
391  *};
392  */
393 int 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                  * We use only the low-order word of vrsave.
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  * tm_cvsx_active - get active number of registers in CVSX
434  * @target:     The target task.
435  * @regset:     The user regset structure.
436  *
437  * This function checks for the active number of available
438  * regisers in transaction checkpointed VSX category.
439  */
440 int 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  * tm_cvsx_get - get CVSX registers
454  * @target:     The target task.
455  * @regset:     The user regset structure.
456  * @to:         Destination of copy.
457  *
458  * This function gets in transaction checkpointed VSX registers.
459  *
460  * When the transaction is active 'ckfp_state' holds the checkpointed
461  * values for the current transaction to fall back on if it aborts
462  * in between. This function gets those checkpointed VSX registers.
463  * The userspace interface buffer layout is as follows.
464  *
465  * struct data {
466  *      u64     vsx[32];
467  *};
468  */
469 int 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         /* Flush the state */
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  * tm_cvsx_set - set CFPR registers
494  * @target:     The target task.
495  * @regset:     The user regset structure.
496  * @pos:        The buffer position.
497  * @count:      Number of bytes to copy.
498  * @kbuf:       Kernel buffer to copy into.
499  * @ubuf:       User buffer to copy from.
500  *
501  * This function sets in transaction checkpointed VSX registers.
502  *
503  * When the transaction is active 'ckfp_state' holds the checkpointed
504  * VSX register values for the current transaction to fall back on
505  * if it aborts in between. This function sets these checkpointed
506  * FPR registers. The userspace interface buffer layout is as follows.
507  *
508  * struct data {
509  *      u64     vsx[32];
510  *};
511  */
512 int 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         /* Flush the state */
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  * tm_spr_active - get active number of registers in TM SPR
545  * @target:     The target task.
546  * @regset:     The user regset structure.
547  *
548  * This function checks the active number of available
549  * regisers in the transactional memory SPR category.
550  */
551 int 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  * tm_spr_get - get the TM related SPR registers
561  * @target:     The target task.
562  * @regset:     The user regset structure.
563  * @to:         Destination of copy.
564  *
565  * This function gets transactional memory related SPR registers.
566  * The userspace interface buffer layout is as follows.
567  *
568  * struct {
569  *      u64             tm_tfhar;
570  *      u64             tm_texasr;
571  *      u64             tm_tfiar;
572  * };
573  */
574 int tm_spr_get(struct task_struct *target, const struct user_regset *regset,
575                struct membuf to)
576 {
577         /* Build tests */
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         /* Flush the states */
586         flush_tmregs_to_thread(target);
587         flush_fp_to_thread(target);
588         flush_altivec_to_thread(target);
589 
590         /* TFHAR register */
591         membuf_write(&to, &target->thread.tm_tfhar, sizeof(u64));
592         /* TEXASR register */
593         membuf_write(&to, &target->thread.tm_texasr, sizeof(u64));
594         /* TFIAR register */
595         return membuf_write(&to, &target->thread.tm_tfiar, sizeof(u64));
596 }
597 
598 /**
599  * tm_spr_set - set the TM related SPR registers
600  * @target:     The target task.
601  * @regset:     The user regset structure.
602  * @pos:        The buffer position.
603  * @count:      Number of bytes to copy.
604  * @kbuf:       Kernel buffer to copy into.
605  * @ubuf:       User buffer to copy from.
606  *
607  * This function sets transactional memory related SPR registers.
608  * The userspace interface buffer layout is as follows.
609  *
610  * struct {
611  *      u64             tm_tfhar;
612  *      u64             tm_texasr;
613  *      u64             tm_tfiar;
614  * };
615  */
616 int 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         /* Build tests */
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         /* Flush the states */
631         flush_tmregs_to_thread(target);
632         flush_fp_to_thread(target);
633         flush_altivec_to_thread(target);
634 
635         /* TFHAR register */
636         ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
637                                  &target->thread.tm_tfhar, 0, sizeof(u64));
638 
639         /* TEXASR register */
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         /* TFIAR register */
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 
653 int 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 
664 int 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 
676 int 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 
693 int 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 
705 int 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 
717 int 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 
734 int 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 
745 int 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 
757 int 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 
774 int 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 
782 int 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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php