17c1f8db0SChristophe Leroy // SPDX-License-Identifier: GPL-2.0-or-later
27c1f8db0SChristophe Leroy
37c1f8db0SChristophe Leroy #include <linux/regset.h>
47c1f8db0SChristophe Leroy
57c1f8db0SChristophe Leroy #include <asm/switch_to.h>
67c1f8db0SChristophe Leroy #include <asm/tm.h>
77c1f8db0SChristophe Leroy #include <asm/asm-prototypes.h>
87c1f8db0SChristophe Leroy
97c1f8db0SChristophe Leroy #include "ptrace-decl.h"
107c1f8db0SChristophe Leroy
flush_tmregs_to_thread(struct task_struct * tsk)117c1f8db0SChristophe Leroy void flush_tmregs_to_thread(struct task_struct *tsk)
127c1f8db0SChristophe Leroy {
137c1f8db0SChristophe Leroy /*
147c1f8db0SChristophe Leroy * If task is not current, it will have been flushed already to
150ddbbb89SBjorn Helgaas * its thread_struct during __switch_to().
167c1f8db0SChristophe Leroy *
177c1f8db0SChristophe Leroy * A reclaim flushes ALL the state or if not in TM save TM SPRs
187c1f8db0SChristophe Leroy * in the appropriate thread structures from live.
197c1f8db0SChristophe Leroy */
207c1f8db0SChristophe Leroy
217c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM) || tsk != current)
227c1f8db0SChristophe Leroy return;
237c1f8db0SChristophe Leroy
247c1f8db0SChristophe Leroy if (MSR_TM_SUSPENDED(mfmsr())) {
257c1f8db0SChristophe Leroy tm_reclaim_current(TM_CAUSE_SIGNAL);
267c1f8db0SChristophe Leroy } else {
277c1f8db0SChristophe Leroy tm_enable();
287c1f8db0SChristophe Leroy tm_save_sprs(&tsk->thread);
297c1f8db0SChristophe Leroy }
307c1f8db0SChristophe Leroy }
317c1f8db0SChristophe Leroy
get_user_ckpt_msr(struct task_struct * task)327c1f8db0SChristophe Leroy static unsigned long get_user_ckpt_msr(struct task_struct *task)
337c1f8db0SChristophe Leroy {
347c1f8db0SChristophe Leroy return task->thread.ckpt_regs.msr | task->thread.fpexc_mode;
357c1f8db0SChristophe Leroy }
367c1f8db0SChristophe Leroy
set_user_ckpt_msr(struct task_struct * task,unsigned long msr)377c1f8db0SChristophe Leroy static int set_user_ckpt_msr(struct task_struct *task, unsigned long msr)
387c1f8db0SChristophe Leroy {
397c1f8db0SChristophe Leroy task->thread.ckpt_regs.msr &= ~MSR_DEBUGCHANGE;
407c1f8db0SChristophe Leroy task->thread.ckpt_regs.msr |= msr & MSR_DEBUGCHANGE;
417c1f8db0SChristophe Leroy return 0;
427c1f8db0SChristophe Leroy }
437c1f8db0SChristophe Leroy
set_user_ckpt_trap(struct task_struct * task,unsigned long trap)447c1f8db0SChristophe Leroy static int set_user_ckpt_trap(struct task_struct *task, unsigned long trap)
457c1f8db0SChristophe Leroy {
46db30144bSNicholas Piggin set_trap(&task->thread.ckpt_regs, trap);
477c1f8db0SChristophe Leroy return 0;
487c1f8db0SChristophe Leroy }
497c1f8db0SChristophe Leroy
507c1f8db0SChristophe Leroy /**
517c1f8db0SChristophe Leroy * tm_cgpr_active - get active number of registers in CGPR
527c1f8db0SChristophe Leroy * @target: The target task.
537c1f8db0SChristophe Leroy * @regset: The user regset structure.
547c1f8db0SChristophe Leroy *
557c1f8db0SChristophe Leroy * This function checks for the active number of available
567c1f8db0SChristophe Leroy * regisers in transaction checkpointed GPR category.
577c1f8db0SChristophe Leroy */
tm_cgpr_active(struct task_struct * target,const struct user_regset * regset)587c1f8db0SChristophe Leroy int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset)
597c1f8db0SChristophe Leroy {
607c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
617c1f8db0SChristophe Leroy return -ENODEV;
627c1f8db0SChristophe Leroy
637c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
647c1f8db0SChristophe Leroy return 0;
657c1f8db0SChristophe Leroy
667c1f8db0SChristophe Leroy return regset->n;
677c1f8db0SChristophe Leroy }
687c1f8db0SChristophe Leroy
697c1f8db0SChristophe Leroy /**
707c1f8db0SChristophe Leroy * tm_cgpr_get - get CGPR registers
717c1f8db0SChristophe Leroy * @target: The target task.
727c1f8db0SChristophe Leroy * @regset: The user regset structure.
7347e12855SAl Viro * @to: Destination of copy.
747c1f8db0SChristophe Leroy *
757c1f8db0SChristophe Leroy * This function gets transaction checkpointed GPR registers.
767c1f8db0SChristophe Leroy *
777c1f8db0SChristophe Leroy * When the transaction is active, 'ckpt_regs' holds all the checkpointed
787c1f8db0SChristophe Leroy * GPR register values for the current transaction to fall back on if it
797c1f8db0SChristophe Leroy * aborts in between. This function gets those checkpointed GPR registers.
807c1f8db0SChristophe Leroy * The userspace interface buffer layout is as follows.
817c1f8db0SChristophe Leroy *
827c1f8db0SChristophe Leroy * struct data {
837c1f8db0SChristophe Leroy * struct pt_regs ckpt_regs;
847c1f8db0SChristophe Leroy * };
857c1f8db0SChristophe Leroy */
tm_cgpr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)867c1f8db0SChristophe Leroy int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
8747e12855SAl Viro struct membuf to)
887c1f8db0SChristophe Leroy {
89640586f8SOleg Nesterov struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr));
90324a6946SOleg Nesterov #ifdef CONFIG_PPC64
91324a6946SOleg Nesterov struct membuf to_softe = membuf_at(&to, offsetof(struct pt_regs, softe));
92324a6946SOleg Nesterov #endif
93640586f8SOleg Nesterov
947c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
957c1f8db0SChristophe Leroy return -ENODEV;
967c1f8db0SChristophe Leroy
977c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
987c1f8db0SChristophe Leroy return -ENODATA;
997c1f8db0SChristophe Leroy
1007c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
1017c1f8db0SChristophe Leroy flush_fp_to_thread(target);
1027c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
1037c1f8db0SChristophe Leroy
104640586f8SOleg Nesterov membuf_write(&to, &target->thread.ckpt_regs, sizeof(struct user_pt_regs));
1057c1f8db0SChristophe Leroy
106640586f8SOleg Nesterov membuf_store(&to_msr, get_user_ckpt_msr(target));
107324a6946SOleg Nesterov #ifdef CONFIG_PPC64
108324a6946SOleg Nesterov membuf_store(&to_softe, 0x1ul);
109324a6946SOleg Nesterov #endif
11047e12855SAl Viro return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) -
1117c1f8db0SChristophe Leroy sizeof(struct user_pt_regs));
1127c1f8db0SChristophe Leroy }
1137c1f8db0SChristophe Leroy
1147c1f8db0SChristophe Leroy /*
1157c1f8db0SChristophe Leroy * tm_cgpr_set - set the CGPR registers
1167c1f8db0SChristophe Leroy * @target: The target task.
1177c1f8db0SChristophe Leroy * @regset: The user regset structure.
1187c1f8db0SChristophe Leroy * @pos: The buffer position.
1197c1f8db0SChristophe Leroy * @count: Number of bytes to copy.
1207c1f8db0SChristophe Leroy * @kbuf: Kernel buffer to copy into.
1217c1f8db0SChristophe Leroy * @ubuf: User buffer to copy from.
1227c1f8db0SChristophe Leroy *
1237c1f8db0SChristophe Leroy * This function sets in transaction checkpointed GPR registers.
1247c1f8db0SChristophe Leroy *
1257c1f8db0SChristophe Leroy * When the transaction is active, 'ckpt_regs' holds the checkpointed
1267c1f8db0SChristophe Leroy * GPR register values for the current transaction to fall back on if it
1277c1f8db0SChristophe Leroy * aborts in between. This function sets those checkpointed GPR registers.
1287c1f8db0SChristophe Leroy * The userspace interface buffer layout is as follows.
1297c1f8db0SChristophe Leroy *
1307c1f8db0SChristophe Leroy * struct data {
1317c1f8db0SChristophe Leroy * struct pt_regs ckpt_regs;
1327c1f8db0SChristophe Leroy * };
1337c1f8db0SChristophe Leroy */
tm_cgpr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)1347c1f8db0SChristophe Leroy int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
1357c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
1367c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
1377c1f8db0SChristophe Leroy {
1387c1f8db0SChristophe Leroy unsigned long reg;
1397c1f8db0SChristophe Leroy int ret;
1407c1f8db0SChristophe Leroy
1417c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
1427c1f8db0SChristophe Leroy return -ENODEV;
1437c1f8db0SChristophe Leroy
1447c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
1457c1f8db0SChristophe Leroy return -ENODATA;
1467c1f8db0SChristophe Leroy
1477c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
1487c1f8db0SChristophe Leroy flush_fp_to_thread(target);
1497c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
1507c1f8db0SChristophe Leroy
1517c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
1527c1f8db0SChristophe Leroy &target->thread.ckpt_regs,
1537c1f8db0SChristophe Leroy 0, PT_MSR * sizeof(reg));
1547c1f8db0SChristophe Leroy
1557c1f8db0SChristophe Leroy if (!ret && count > 0) {
1567c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
1577c1f8db0SChristophe Leroy PT_MSR * sizeof(reg),
1587c1f8db0SChristophe Leroy (PT_MSR + 1) * sizeof(reg));
1597c1f8db0SChristophe Leroy if (!ret)
1607c1f8db0SChristophe Leroy ret = set_user_ckpt_msr(target, reg);
1617c1f8db0SChristophe Leroy }
1627c1f8db0SChristophe Leroy
1637c1f8db0SChristophe Leroy BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
1647c1f8db0SChristophe Leroy offsetof(struct pt_regs, msr) + sizeof(long));
1657c1f8db0SChristophe Leroy
1667c1f8db0SChristophe Leroy if (!ret)
1677c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
1687c1f8db0SChristophe Leroy &target->thread.ckpt_regs.orig_gpr3,
1697c1f8db0SChristophe Leroy PT_ORIG_R3 * sizeof(reg),
1707c1f8db0SChristophe Leroy (PT_MAX_PUT_REG + 1) * sizeof(reg));
1717c1f8db0SChristophe Leroy
1727c1f8db0SChristophe Leroy if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
17318b9fe54SSergey Shtylyov user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
1747c1f8db0SChristophe Leroy (PT_MAX_PUT_REG + 1) * sizeof(reg),
1757c1f8db0SChristophe Leroy PT_TRAP * sizeof(reg));
1767c1f8db0SChristophe Leroy
1777c1f8db0SChristophe Leroy if (!ret && count > 0) {
1787c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®,
1797c1f8db0SChristophe Leroy PT_TRAP * sizeof(reg),
1807c1f8db0SChristophe Leroy (PT_TRAP + 1) * sizeof(reg));
1817c1f8db0SChristophe Leroy if (!ret)
1827c1f8db0SChristophe Leroy ret = set_user_ckpt_trap(target, reg);
1837c1f8db0SChristophe Leroy }
1847c1f8db0SChristophe Leroy
1857c1f8db0SChristophe Leroy if (!ret)
18618b9fe54SSergey Shtylyov user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
1877c1f8db0SChristophe Leroy (PT_TRAP + 1) * sizeof(reg), -1);
1887c1f8db0SChristophe Leroy
1897c1f8db0SChristophe Leroy return ret;
1907c1f8db0SChristophe Leroy }
1917c1f8db0SChristophe Leroy
1927c1f8db0SChristophe Leroy /**
1937c1f8db0SChristophe Leroy * tm_cfpr_active - get active number of registers in CFPR
1947c1f8db0SChristophe Leroy * @target: The target task.
1957c1f8db0SChristophe Leroy * @regset: The user regset structure.
1967c1f8db0SChristophe Leroy *
1977c1f8db0SChristophe Leroy * This function checks for the active number of available
1987c1f8db0SChristophe Leroy * regisers in transaction checkpointed FPR category.
1997c1f8db0SChristophe Leroy */
tm_cfpr_active(struct task_struct * target,const struct user_regset * regset)2007c1f8db0SChristophe Leroy int tm_cfpr_active(struct task_struct *target, const struct user_regset *regset)
2017c1f8db0SChristophe Leroy {
2027c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
2037c1f8db0SChristophe Leroy return -ENODEV;
2047c1f8db0SChristophe Leroy
2057c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
2067c1f8db0SChristophe Leroy return 0;
2077c1f8db0SChristophe Leroy
2087c1f8db0SChristophe Leroy return regset->n;
2097c1f8db0SChristophe Leroy }
2107c1f8db0SChristophe Leroy
2117c1f8db0SChristophe Leroy /**
2127c1f8db0SChristophe Leroy * tm_cfpr_get - get CFPR registers
2137c1f8db0SChristophe Leroy * @target: The target task.
2147c1f8db0SChristophe Leroy * @regset: The user regset structure.
21547e12855SAl Viro * @to: Destination of copy.
2167c1f8db0SChristophe Leroy *
2177c1f8db0SChristophe Leroy * This function gets in transaction checkpointed FPR registers.
2187c1f8db0SChristophe Leroy *
2197c1f8db0SChristophe Leroy * When the transaction is active 'ckfp_state' holds the checkpointed
2207c1f8db0SChristophe Leroy * values for the current transaction to fall back on if it aborts
2217c1f8db0SChristophe Leroy * in between. This function gets those checkpointed FPR registers.
2227c1f8db0SChristophe Leroy * The userspace interface buffer layout is as follows.
2237c1f8db0SChristophe Leroy *
2247c1f8db0SChristophe Leroy * struct data {
2257c1f8db0SChristophe Leroy * u64 fpr[32];
2267c1f8db0SChristophe Leroy * u64 fpscr;
2277c1f8db0SChristophe Leroy *};
2287c1f8db0SChristophe Leroy */
tm_cfpr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)2297c1f8db0SChristophe Leroy int tm_cfpr_get(struct task_struct *target, const struct user_regset *regset,
23047e12855SAl Viro struct membuf to)
2317c1f8db0SChristophe Leroy {
2327c1f8db0SChristophe Leroy u64 buf[33];
2337c1f8db0SChristophe Leroy int i;
2347c1f8db0SChristophe Leroy
2357c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
2367c1f8db0SChristophe Leroy return -ENODEV;
2377c1f8db0SChristophe Leroy
2387c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
2397c1f8db0SChristophe Leroy return -ENODATA;
2407c1f8db0SChristophe Leroy
2417c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
2427c1f8db0SChristophe Leroy flush_fp_to_thread(target);
2437c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
2447c1f8db0SChristophe Leroy
2457c1f8db0SChristophe Leroy /* copy to local buffer then write that out */
2467c1f8db0SChristophe Leroy for (i = 0; i < 32 ; i++)
2477c1f8db0SChristophe Leroy buf[i] = target->thread.TS_CKFPR(i);
2487c1f8db0SChristophe Leroy buf[32] = target->thread.ckfp_state.fpscr;
24947e12855SAl Viro return membuf_write(&to, buf, sizeof(buf));
2507c1f8db0SChristophe Leroy }
2517c1f8db0SChristophe Leroy
2527c1f8db0SChristophe Leroy /**
2537c1f8db0SChristophe Leroy * tm_cfpr_set - set CFPR registers
2547c1f8db0SChristophe Leroy * @target: The target task.
2557c1f8db0SChristophe Leroy * @regset: The user regset structure.
2567c1f8db0SChristophe Leroy * @pos: The buffer position.
2577c1f8db0SChristophe Leroy * @count: Number of bytes to copy.
2587c1f8db0SChristophe Leroy * @kbuf: Kernel buffer to copy into.
2597c1f8db0SChristophe Leroy * @ubuf: User buffer to copy from.
2607c1f8db0SChristophe Leroy *
2617c1f8db0SChristophe Leroy * This function sets in transaction checkpointed FPR registers.
2627c1f8db0SChristophe Leroy *
2637c1f8db0SChristophe Leroy * When the transaction is active 'ckfp_state' holds the checkpointed
2647c1f8db0SChristophe Leroy * FPR register values for the current transaction to fall back on
2657c1f8db0SChristophe Leroy * if it aborts in between. This function sets these checkpointed
2667c1f8db0SChristophe Leroy * FPR registers. The userspace interface buffer layout is as follows.
2677c1f8db0SChristophe Leroy *
2687c1f8db0SChristophe Leroy * struct data {
2697c1f8db0SChristophe Leroy * u64 fpr[32];
2707c1f8db0SChristophe Leroy * u64 fpscr;
2717c1f8db0SChristophe Leroy *};
2727c1f8db0SChristophe Leroy */
tm_cfpr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)2737c1f8db0SChristophe Leroy int tm_cfpr_set(struct task_struct *target, const struct user_regset *regset,
2747c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
2757c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
2767c1f8db0SChristophe Leroy {
2777c1f8db0SChristophe Leroy u64 buf[33];
2787c1f8db0SChristophe Leroy int i;
2797c1f8db0SChristophe Leroy
2807c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
2817c1f8db0SChristophe Leroy return -ENODEV;
2827c1f8db0SChristophe Leroy
2837c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
2847c1f8db0SChristophe Leroy return -ENODATA;
2857c1f8db0SChristophe Leroy
2867c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
2877c1f8db0SChristophe Leroy flush_fp_to_thread(target);
2887c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
2897c1f8db0SChristophe Leroy
2907c1f8db0SChristophe Leroy for (i = 0; i < 32; i++)
2917c1f8db0SChristophe Leroy buf[i] = target->thread.TS_CKFPR(i);
2927c1f8db0SChristophe Leroy buf[32] = target->thread.ckfp_state.fpscr;
2937c1f8db0SChristophe Leroy
2947c1f8db0SChristophe Leroy /* copy to local buffer then write that out */
2957c1f8db0SChristophe Leroy i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
2967c1f8db0SChristophe Leroy if (i)
2977c1f8db0SChristophe Leroy return i;
2987c1f8db0SChristophe Leroy for (i = 0; i < 32 ; i++)
2997c1f8db0SChristophe Leroy target->thread.TS_CKFPR(i) = buf[i];
3007c1f8db0SChristophe Leroy target->thread.ckfp_state.fpscr = buf[32];
3017c1f8db0SChristophe Leroy return 0;
3027c1f8db0SChristophe Leroy }
3037c1f8db0SChristophe Leroy
3047c1f8db0SChristophe Leroy /**
3057c1f8db0SChristophe Leroy * tm_cvmx_active - get active number of registers in CVMX
3067c1f8db0SChristophe Leroy * @target: The target task.
3077c1f8db0SChristophe Leroy * @regset: The user regset structure.
3087c1f8db0SChristophe Leroy *
3097c1f8db0SChristophe Leroy * This function checks for the active number of available
3107c1f8db0SChristophe Leroy * regisers in checkpointed VMX category.
3117c1f8db0SChristophe Leroy */
tm_cvmx_active(struct task_struct * target,const struct user_regset * regset)3127c1f8db0SChristophe Leroy int tm_cvmx_active(struct task_struct *target, const struct user_regset *regset)
3137c1f8db0SChristophe Leroy {
3147c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
3157c1f8db0SChristophe Leroy return -ENODEV;
3167c1f8db0SChristophe Leroy
3177c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
3187c1f8db0SChristophe Leroy return 0;
3197c1f8db0SChristophe Leroy
3207c1f8db0SChristophe Leroy return regset->n;
3217c1f8db0SChristophe Leroy }
3227c1f8db0SChristophe Leroy
3237c1f8db0SChristophe Leroy /**
3247c1f8db0SChristophe Leroy * tm_cvmx_get - get CMVX registers
3257c1f8db0SChristophe Leroy * @target: The target task.
3267c1f8db0SChristophe Leroy * @regset: The user regset structure.
32747e12855SAl Viro * @to: Destination of copy.
3287c1f8db0SChristophe Leroy *
3297c1f8db0SChristophe Leroy * This function gets in transaction checkpointed VMX registers.
3307c1f8db0SChristophe Leroy *
3317c1f8db0SChristophe Leroy * When the transaction is active 'ckvr_state' and 'ckvrsave' hold
3327c1f8db0SChristophe Leroy * the checkpointed values for the current transaction to fall
3337c1f8db0SChristophe Leroy * back on if it aborts in between. The userspace interface buffer
3347c1f8db0SChristophe Leroy * layout is as follows.
3357c1f8db0SChristophe Leroy *
3367c1f8db0SChristophe Leroy * struct data {
3377c1f8db0SChristophe Leroy * vector128 vr[32];
3387c1f8db0SChristophe Leroy * vector128 vscr;
3397c1f8db0SChristophe Leroy * vector128 vrsave;
3407c1f8db0SChristophe Leroy *};
3417c1f8db0SChristophe Leroy */
tm_cvmx_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)3427c1f8db0SChristophe Leroy int tm_cvmx_get(struct task_struct *target, const struct user_regset *regset,
34347e12855SAl Viro struct membuf to)
3447c1f8db0SChristophe Leroy {
34547e12855SAl Viro union {
34647e12855SAl Viro elf_vrreg_t reg;
34747e12855SAl Viro u32 word;
34847e12855SAl Viro } vrsave;
3497c1f8db0SChristophe Leroy BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
3507c1f8db0SChristophe Leroy
3517c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
3527c1f8db0SChristophe Leroy return -ENODEV;
3537c1f8db0SChristophe Leroy
3547c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
3557c1f8db0SChristophe Leroy return -ENODATA;
3567c1f8db0SChristophe Leroy
3577c1f8db0SChristophe Leroy /* Flush the state */
3587c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
3597c1f8db0SChristophe Leroy flush_fp_to_thread(target);
3607c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
3617c1f8db0SChristophe Leroy
36247e12855SAl Viro membuf_write(&to, &target->thread.ckvr_state, 33 * sizeof(vector128));
3637c1f8db0SChristophe Leroy /*
3647c1f8db0SChristophe Leroy * Copy out only the low-order word of vrsave.
3657c1f8db0SChristophe Leroy */
3667c1f8db0SChristophe Leroy memset(&vrsave, 0, sizeof(vrsave));
3677c1f8db0SChristophe Leroy vrsave.word = target->thread.ckvrsave;
36847e12855SAl Viro return membuf_write(&to, &vrsave, sizeof(vrsave));
3697c1f8db0SChristophe Leroy }
3707c1f8db0SChristophe Leroy
3717c1f8db0SChristophe Leroy /**
3727c1f8db0SChristophe Leroy * tm_cvmx_set - set CMVX registers
3737c1f8db0SChristophe Leroy * @target: The target task.
3747c1f8db0SChristophe Leroy * @regset: The user regset structure.
3757c1f8db0SChristophe Leroy * @pos: The buffer position.
3767c1f8db0SChristophe Leroy * @count: Number of bytes to copy.
3777c1f8db0SChristophe Leroy * @kbuf: Kernel buffer to copy into.
3787c1f8db0SChristophe Leroy * @ubuf: User buffer to copy from.
3797c1f8db0SChristophe Leroy *
3807c1f8db0SChristophe Leroy * This function sets in transaction checkpointed VMX registers.
3817c1f8db0SChristophe Leroy *
3827c1f8db0SChristophe Leroy * When the transaction is active 'ckvr_state' and 'ckvrsave' hold
3837c1f8db0SChristophe Leroy * the checkpointed values for the current transaction to fall
3847c1f8db0SChristophe Leroy * back on if it aborts in between. The userspace interface buffer
3857c1f8db0SChristophe Leroy * layout is as follows.
3867c1f8db0SChristophe Leroy *
3877c1f8db0SChristophe Leroy * struct data {
3887c1f8db0SChristophe Leroy * vector128 vr[32];
3897c1f8db0SChristophe Leroy * vector128 vscr;
3907c1f8db0SChristophe Leroy * vector128 vrsave;
3917c1f8db0SChristophe Leroy *};
3927c1f8db0SChristophe Leroy */
tm_cvmx_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)3937c1f8db0SChristophe Leroy int tm_cvmx_set(struct task_struct *target, const struct user_regset *regset,
3947c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
3957c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
3967c1f8db0SChristophe Leroy {
3977c1f8db0SChristophe Leroy int ret;
3987c1f8db0SChristophe Leroy
3997c1f8db0SChristophe Leroy BUILD_BUG_ON(TVSO(vscr) != TVSO(vr[32]));
4007c1f8db0SChristophe Leroy
4017c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
4027c1f8db0SChristophe Leroy return -ENODEV;
4037c1f8db0SChristophe Leroy
4047c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
4057c1f8db0SChristophe Leroy return -ENODATA;
4067c1f8db0SChristophe Leroy
4077c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
4087c1f8db0SChristophe Leroy flush_fp_to_thread(target);
4097c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
4107c1f8db0SChristophe Leroy
4117c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ckvr_state,
4127c1f8db0SChristophe Leroy 0, 33 * sizeof(vector128));
4137c1f8db0SChristophe Leroy if (!ret && count > 0) {
4147c1f8db0SChristophe Leroy /*
4157c1f8db0SChristophe Leroy * We use only the low-order word of vrsave.
4167c1f8db0SChristophe Leroy */
4177c1f8db0SChristophe Leroy union {
4187c1f8db0SChristophe Leroy elf_vrreg_t reg;
4197c1f8db0SChristophe Leroy u32 word;
4207c1f8db0SChristophe Leroy } vrsave;
4217c1f8db0SChristophe Leroy memset(&vrsave, 0, sizeof(vrsave));
4227c1f8db0SChristophe Leroy vrsave.word = target->thread.ckvrsave;
4237c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &vrsave,
4247c1f8db0SChristophe Leroy 33 * sizeof(vector128), -1);
4257c1f8db0SChristophe Leroy if (!ret)
4267c1f8db0SChristophe Leroy target->thread.ckvrsave = vrsave.word;
4277c1f8db0SChristophe Leroy }
4287c1f8db0SChristophe Leroy
4297c1f8db0SChristophe Leroy return ret;
4307c1f8db0SChristophe Leroy }
4317c1f8db0SChristophe Leroy
4327c1f8db0SChristophe Leroy /**
4337c1f8db0SChristophe Leroy * tm_cvsx_active - get active number of registers in CVSX
4347c1f8db0SChristophe Leroy * @target: The target task.
4357c1f8db0SChristophe Leroy * @regset: The user regset structure.
4367c1f8db0SChristophe Leroy *
4377c1f8db0SChristophe Leroy * This function checks for the active number of available
4387c1f8db0SChristophe Leroy * regisers in transaction checkpointed VSX category.
4397c1f8db0SChristophe Leroy */
tm_cvsx_active(struct task_struct * target,const struct user_regset * regset)4407c1f8db0SChristophe Leroy int tm_cvsx_active(struct task_struct *target, const struct user_regset *regset)
4417c1f8db0SChristophe Leroy {
4427c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
4437c1f8db0SChristophe Leroy return -ENODEV;
4447c1f8db0SChristophe Leroy
4457c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
4467c1f8db0SChristophe Leroy return 0;
4477c1f8db0SChristophe Leroy
4487c1f8db0SChristophe Leroy flush_vsx_to_thread(target);
4497c1f8db0SChristophe Leroy return target->thread.used_vsr ? regset->n : 0;
4507c1f8db0SChristophe Leroy }
4517c1f8db0SChristophe Leroy
4527c1f8db0SChristophe Leroy /**
4537c1f8db0SChristophe Leroy * tm_cvsx_get - get CVSX registers
4547c1f8db0SChristophe Leroy * @target: The target task.
4557c1f8db0SChristophe Leroy * @regset: The user regset structure.
45647e12855SAl Viro * @to: Destination of copy.
4577c1f8db0SChristophe Leroy *
4587c1f8db0SChristophe Leroy * This function gets in transaction checkpointed VSX registers.
4597c1f8db0SChristophe Leroy *
4607c1f8db0SChristophe Leroy * When the transaction is active 'ckfp_state' holds the checkpointed
4617c1f8db0SChristophe Leroy * values for the current transaction to fall back on if it aborts
4627c1f8db0SChristophe Leroy * in between. This function gets those checkpointed VSX registers.
4637c1f8db0SChristophe Leroy * The userspace interface buffer layout is as follows.
4647c1f8db0SChristophe Leroy *
4657c1f8db0SChristophe Leroy * struct data {
4667c1f8db0SChristophe Leroy * u64 vsx[32];
4677c1f8db0SChristophe Leroy *};
4687c1f8db0SChristophe Leroy */
tm_cvsx_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)4697c1f8db0SChristophe Leroy int tm_cvsx_get(struct task_struct *target, const struct user_regset *regset,
47047e12855SAl Viro struct membuf to)
4717c1f8db0SChristophe Leroy {
4727c1f8db0SChristophe Leroy u64 buf[32];
47347e12855SAl Viro int i;
4747c1f8db0SChristophe Leroy
4757c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
4767c1f8db0SChristophe Leroy return -ENODEV;
4777c1f8db0SChristophe Leroy
4787c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
4797c1f8db0SChristophe Leroy return -ENODATA;
4807c1f8db0SChristophe Leroy
4817c1f8db0SChristophe Leroy /* Flush the state */
4827c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
4837c1f8db0SChristophe Leroy flush_fp_to_thread(target);
4847c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
4857c1f8db0SChristophe Leroy flush_vsx_to_thread(target);
4867c1f8db0SChristophe Leroy
4877c1f8db0SChristophe Leroy for (i = 0; i < 32 ; i++)
4887c1f8db0SChristophe Leroy buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
48947e12855SAl Viro return membuf_write(&to, buf, 32 * sizeof(double));
4907c1f8db0SChristophe Leroy }
4917c1f8db0SChristophe Leroy
4927c1f8db0SChristophe Leroy /**
4937c1f8db0SChristophe Leroy * tm_cvsx_set - set CFPR registers
4947c1f8db0SChristophe Leroy * @target: The target task.
4957c1f8db0SChristophe Leroy * @regset: The user regset structure.
4967c1f8db0SChristophe Leroy * @pos: The buffer position.
4977c1f8db0SChristophe Leroy * @count: Number of bytes to copy.
4987c1f8db0SChristophe Leroy * @kbuf: Kernel buffer to copy into.
4997c1f8db0SChristophe Leroy * @ubuf: User buffer to copy from.
5007c1f8db0SChristophe Leroy *
5017c1f8db0SChristophe Leroy * This function sets in transaction checkpointed VSX registers.
5027c1f8db0SChristophe Leroy *
5037c1f8db0SChristophe Leroy * When the transaction is active 'ckfp_state' holds the checkpointed
5047c1f8db0SChristophe Leroy * VSX register values for the current transaction to fall back on
5057c1f8db0SChristophe Leroy * if it aborts in between. This function sets these checkpointed
5067c1f8db0SChristophe Leroy * FPR registers. The userspace interface buffer layout is as follows.
5077c1f8db0SChristophe Leroy *
5087c1f8db0SChristophe Leroy * struct data {
5097c1f8db0SChristophe Leroy * u64 vsx[32];
5107c1f8db0SChristophe Leroy *};
5117c1f8db0SChristophe Leroy */
tm_cvsx_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)5127c1f8db0SChristophe Leroy int tm_cvsx_set(struct task_struct *target, const struct user_regset *regset,
5137c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
5147c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
5157c1f8db0SChristophe Leroy {
5167c1f8db0SChristophe Leroy u64 buf[32];
5177c1f8db0SChristophe Leroy int ret, i;
5187c1f8db0SChristophe Leroy
5197c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
5207c1f8db0SChristophe Leroy return -ENODEV;
5217c1f8db0SChristophe Leroy
5227c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
5237c1f8db0SChristophe Leroy return -ENODATA;
5247c1f8db0SChristophe Leroy
5257c1f8db0SChristophe Leroy /* Flush the state */
5267c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
5277c1f8db0SChristophe Leroy flush_fp_to_thread(target);
5287c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
5297c1f8db0SChristophe Leroy flush_vsx_to_thread(target);
5307c1f8db0SChristophe Leroy
5317c1f8db0SChristophe Leroy for (i = 0; i < 32 ; i++)
5327c1f8db0SChristophe Leroy buf[i] = target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET];
5337c1f8db0SChristophe Leroy
5347c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
5357c1f8db0SChristophe Leroy buf, 0, 32 * sizeof(double));
5367c1f8db0SChristophe Leroy if (!ret)
5377c1f8db0SChristophe Leroy for (i = 0; i < 32 ; i++)
5387c1f8db0SChristophe Leroy target->thread.ckfp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
5397c1f8db0SChristophe Leroy
5407c1f8db0SChristophe Leroy return ret;
5417c1f8db0SChristophe Leroy }
5427c1f8db0SChristophe Leroy
5437c1f8db0SChristophe Leroy /**
5447c1f8db0SChristophe Leroy * tm_spr_active - get active number of registers in TM SPR
5457c1f8db0SChristophe Leroy * @target: The target task.
5467c1f8db0SChristophe Leroy * @regset: The user regset structure.
5477c1f8db0SChristophe Leroy *
5487c1f8db0SChristophe Leroy * This function checks the active number of available
5497c1f8db0SChristophe Leroy * regisers in the transactional memory SPR category.
5507c1f8db0SChristophe Leroy */
tm_spr_active(struct task_struct * target,const struct user_regset * regset)5517c1f8db0SChristophe Leroy int tm_spr_active(struct task_struct *target, const struct user_regset *regset)
5527c1f8db0SChristophe Leroy {
5537c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
5547c1f8db0SChristophe Leroy return -ENODEV;
5557c1f8db0SChristophe Leroy
5567c1f8db0SChristophe Leroy return regset->n;
5577c1f8db0SChristophe Leroy }
5587c1f8db0SChristophe Leroy
5597c1f8db0SChristophe Leroy /**
5607c1f8db0SChristophe Leroy * tm_spr_get - get the TM related SPR registers
5617c1f8db0SChristophe Leroy * @target: The target task.
5627c1f8db0SChristophe Leroy * @regset: The user regset structure.
56347e12855SAl Viro * @to: Destination of copy.
5647c1f8db0SChristophe Leroy *
5657c1f8db0SChristophe Leroy * This function gets transactional memory related SPR registers.
5667c1f8db0SChristophe Leroy * The userspace interface buffer layout is as follows.
5677c1f8db0SChristophe Leroy *
5687c1f8db0SChristophe Leroy * struct {
5697c1f8db0SChristophe Leroy * u64 tm_tfhar;
5707c1f8db0SChristophe Leroy * u64 tm_texasr;
5717c1f8db0SChristophe Leroy * u64 tm_tfiar;
5727c1f8db0SChristophe Leroy * };
5737c1f8db0SChristophe Leroy */
tm_spr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)5747c1f8db0SChristophe Leroy int tm_spr_get(struct task_struct *target, const struct user_regset *regset,
57547e12855SAl Viro struct membuf to)
5767c1f8db0SChristophe Leroy {
5777c1f8db0SChristophe Leroy /* Build tests */
5787c1f8db0SChristophe Leroy BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
5797c1f8db0SChristophe Leroy BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
5807c1f8db0SChristophe Leroy BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
5817c1f8db0SChristophe Leroy
5827c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
5837c1f8db0SChristophe Leroy return -ENODEV;
5847c1f8db0SChristophe Leroy
5857c1f8db0SChristophe Leroy /* Flush the states */
5867c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
5877c1f8db0SChristophe Leroy flush_fp_to_thread(target);
5887c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
5897c1f8db0SChristophe Leroy
5907c1f8db0SChristophe Leroy /* TFHAR register */
59147e12855SAl Viro membuf_write(&to, &target->thread.tm_tfhar, sizeof(u64));
5927c1f8db0SChristophe Leroy /* TEXASR register */
59347e12855SAl Viro membuf_write(&to, &target->thread.tm_texasr, sizeof(u64));
5947c1f8db0SChristophe Leroy /* TFIAR register */
59547e12855SAl Viro return membuf_write(&to, &target->thread.tm_tfiar, sizeof(u64));
5967c1f8db0SChristophe Leroy }
5977c1f8db0SChristophe Leroy
5987c1f8db0SChristophe Leroy /**
5997c1f8db0SChristophe Leroy * tm_spr_set - set the TM related SPR registers
6007c1f8db0SChristophe Leroy * @target: The target task.
6017c1f8db0SChristophe Leroy * @regset: The user regset structure.
6027c1f8db0SChristophe Leroy * @pos: The buffer position.
6037c1f8db0SChristophe Leroy * @count: Number of bytes to copy.
6047c1f8db0SChristophe Leroy * @kbuf: Kernel buffer to copy into.
6057c1f8db0SChristophe Leroy * @ubuf: User buffer to copy from.
6067c1f8db0SChristophe Leroy *
6077c1f8db0SChristophe Leroy * This function sets transactional memory related SPR registers.
6087c1f8db0SChristophe Leroy * The userspace interface buffer layout is as follows.
6097c1f8db0SChristophe Leroy *
6107c1f8db0SChristophe Leroy * struct {
6117c1f8db0SChristophe Leroy * u64 tm_tfhar;
6127c1f8db0SChristophe Leroy * u64 tm_texasr;
6137c1f8db0SChristophe Leroy * u64 tm_tfiar;
6147c1f8db0SChristophe Leroy * };
6157c1f8db0SChristophe Leroy */
tm_spr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)6167c1f8db0SChristophe Leroy int tm_spr_set(struct task_struct *target, const struct user_regset *regset,
6177c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
6187c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
6197c1f8db0SChristophe Leroy {
6207c1f8db0SChristophe Leroy int ret;
6217c1f8db0SChristophe Leroy
6227c1f8db0SChristophe Leroy /* Build tests */
6237c1f8db0SChristophe Leroy BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
6247c1f8db0SChristophe Leroy BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
6257c1f8db0SChristophe Leroy BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));
6267c1f8db0SChristophe Leroy
6277c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
6287c1f8db0SChristophe Leroy return -ENODEV;
6297c1f8db0SChristophe Leroy
6307c1f8db0SChristophe Leroy /* Flush the states */
6317c1f8db0SChristophe Leroy flush_tmregs_to_thread(target);
6327c1f8db0SChristophe Leroy flush_fp_to_thread(target);
6337c1f8db0SChristophe Leroy flush_altivec_to_thread(target);
6347c1f8db0SChristophe Leroy
6357c1f8db0SChristophe Leroy /* TFHAR register */
6367c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
6377c1f8db0SChristophe Leroy &target->thread.tm_tfhar, 0, sizeof(u64));
6387c1f8db0SChristophe Leroy
6397c1f8db0SChristophe Leroy /* TEXASR register */
6407c1f8db0SChristophe Leroy if (!ret)
6417c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
6427c1f8db0SChristophe Leroy &target->thread.tm_texasr, sizeof(u64),
6437c1f8db0SChristophe Leroy 2 * sizeof(u64));
6447c1f8db0SChristophe Leroy
6457c1f8db0SChristophe Leroy /* TFIAR register */
6467c1f8db0SChristophe Leroy if (!ret)
6477c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
6487c1f8db0SChristophe Leroy &target->thread.tm_tfiar,
6497c1f8db0SChristophe Leroy 2 * sizeof(u64), 3 * sizeof(u64));
6507c1f8db0SChristophe Leroy return ret;
6517c1f8db0SChristophe Leroy }
6527c1f8db0SChristophe Leroy
tm_tar_active(struct task_struct * target,const struct user_regset * regset)6537c1f8db0SChristophe Leroy int tm_tar_active(struct task_struct *target, const struct user_regset *regset)
6547c1f8db0SChristophe Leroy {
6557c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
6567c1f8db0SChristophe Leroy return -ENODEV;
6577c1f8db0SChristophe Leroy
6587c1f8db0SChristophe Leroy if (MSR_TM_ACTIVE(target->thread.regs->msr))
6597c1f8db0SChristophe Leroy return regset->n;
6607c1f8db0SChristophe Leroy
6617c1f8db0SChristophe Leroy return 0;
6627c1f8db0SChristophe Leroy }
6637c1f8db0SChristophe Leroy
tm_tar_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)6647c1f8db0SChristophe Leroy int tm_tar_get(struct task_struct *target, const struct user_regset *regset,
66547e12855SAl Viro struct membuf to)
6667c1f8db0SChristophe Leroy {
6677c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
6687c1f8db0SChristophe Leroy return -ENODEV;
6697c1f8db0SChristophe Leroy
6707c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
6717c1f8db0SChristophe Leroy return -ENODATA;
6727c1f8db0SChristophe Leroy
67347e12855SAl Viro return membuf_write(&to, &target->thread.tm_tar, sizeof(u64));
6747c1f8db0SChristophe Leroy }
6757c1f8db0SChristophe Leroy
tm_tar_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)6767c1f8db0SChristophe Leroy int tm_tar_set(struct task_struct *target, const struct user_regset *regset,
6777c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
6787c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
6797c1f8db0SChristophe Leroy {
6807c1f8db0SChristophe Leroy int ret;
6817c1f8db0SChristophe Leroy
6827c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
6837c1f8db0SChristophe Leroy return -ENODEV;
6847c1f8db0SChristophe Leroy
6857c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
6867c1f8db0SChristophe Leroy return -ENODATA;
6877c1f8db0SChristophe Leroy
6887c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
6897c1f8db0SChristophe Leroy &target->thread.tm_tar, 0, sizeof(u64));
6907c1f8db0SChristophe Leroy return ret;
6917c1f8db0SChristophe Leroy }
6927c1f8db0SChristophe Leroy
tm_ppr_active(struct task_struct * target,const struct user_regset * regset)6937c1f8db0SChristophe Leroy int tm_ppr_active(struct task_struct *target, const struct user_regset *regset)
6947c1f8db0SChristophe Leroy {
6957c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
6967c1f8db0SChristophe Leroy return -ENODEV;
6977c1f8db0SChristophe Leroy
6987c1f8db0SChristophe Leroy if (MSR_TM_ACTIVE(target->thread.regs->msr))
6997c1f8db0SChristophe Leroy return regset->n;
7007c1f8db0SChristophe Leroy
7017c1f8db0SChristophe Leroy return 0;
7027c1f8db0SChristophe Leroy }
7037c1f8db0SChristophe Leroy
7047c1f8db0SChristophe Leroy
tm_ppr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)7057c1f8db0SChristophe Leroy int tm_ppr_get(struct task_struct *target, const struct user_regset *regset,
70647e12855SAl Viro struct membuf to)
7077c1f8db0SChristophe Leroy {
7087c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
7097c1f8db0SChristophe Leroy return -ENODEV;
7107c1f8db0SChristophe Leroy
7117c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
7127c1f8db0SChristophe Leroy return -ENODATA;
7137c1f8db0SChristophe Leroy
71447e12855SAl Viro return membuf_write(&to, &target->thread.tm_ppr, sizeof(u64));
7157c1f8db0SChristophe Leroy }
7167c1f8db0SChristophe Leroy
tm_ppr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)7177c1f8db0SChristophe Leroy int tm_ppr_set(struct task_struct *target, const struct user_regset *regset,
7187c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
7197c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
7207c1f8db0SChristophe Leroy {
7217c1f8db0SChristophe Leroy int ret;
7227c1f8db0SChristophe Leroy
7237c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
7247c1f8db0SChristophe Leroy return -ENODEV;
7257c1f8db0SChristophe Leroy
7267c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
7277c1f8db0SChristophe Leroy return -ENODATA;
7287c1f8db0SChristophe Leroy
7297c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
7307c1f8db0SChristophe Leroy &target->thread.tm_ppr, 0, sizeof(u64));
7317c1f8db0SChristophe Leroy return ret;
7327c1f8db0SChristophe Leroy }
7337c1f8db0SChristophe Leroy
tm_dscr_active(struct task_struct * target,const struct user_regset * regset)7347c1f8db0SChristophe Leroy int tm_dscr_active(struct task_struct *target, const struct user_regset *regset)
7357c1f8db0SChristophe Leroy {
7367c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
7377c1f8db0SChristophe Leroy return -ENODEV;
7387c1f8db0SChristophe Leroy
7397c1f8db0SChristophe Leroy if (MSR_TM_ACTIVE(target->thread.regs->msr))
7407c1f8db0SChristophe Leroy return regset->n;
7417c1f8db0SChristophe Leroy
7427c1f8db0SChristophe Leroy return 0;
7437c1f8db0SChristophe Leroy }
7447c1f8db0SChristophe Leroy
tm_dscr_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)7457c1f8db0SChristophe Leroy int tm_dscr_get(struct task_struct *target, const struct user_regset *regset,
74647e12855SAl Viro struct membuf to)
7477c1f8db0SChristophe Leroy {
7487c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
7497c1f8db0SChristophe Leroy return -ENODEV;
7507c1f8db0SChristophe Leroy
7517c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
7527c1f8db0SChristophe Leroy return -ENODATA;
7537c1f8db0SChristophe Leroy
75447e12855SAl Viro return membuf_write(&to, &target->thread.tm_dscr, sizeof(u64));
7557c1f8db0SChristophe Leroy }
7567c1f8db0SChristophe Leroy
tm_dscr_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)7577c1f8db0SChristophe Leroy int tm_dscr_set(struct task_struct *target, const struct user_regset *regset,
7587c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
7597c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
7607c1f8db0SChristophe Leroy {
7617c1f8db0SChristophe Leroy int ret;
7627c1f8db0SChristophe Leroy
7637c1f8db0SChristophe Leroy if (!cpu_has_feature(CPU_FTR_TM))
7647c1f8db0SChristophe Leroy return -ENODEV;
7657c1f8db0SChristophe Leroy
7667c1f8db0SChristophe Leroy if (!MSR_TM_ACTIVE(target->thread.regs->msr))
7677c1f8db0SChristophe Leroy return -ENODATA;
7687c1f8db0SChristophe Leroy
7697c1f8db0SChristophe Leroy ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
7707c1f8db0SChristophe Leroy &target->thread.tm_dscr, 0, sizeof(u64));
7717c1f8db0SChristophe Leroy return ret;
7727c1f8db0SChristophe Leroy }
7737c1f8db0SChristophe Leroy
tm_cgpr32_get(struct task_struct * target,const struct user_regset * regset,struct membuf to)7747c1f8db0SChristophe Leroy int tm_cgpr32_get(struct task_struct *target, const struct user_regset *regset,
77547e12855SAl Viro struct membuf to)
7767c1f8db0SChristophe Leroy {
77747e12855SAl Viro gpr32_get_common(target, regset, to,
7787c1f8db0SChristophe Leroy &target->thread.ckpt_regs.gpr[0]);
77947e12855SAl Viro return membuf_zero(&to, ELF_NGREG * sizeof(u32));
7807c1f8db0SChristophe Leroy }
7817c1f8db0SChristophe Leroy
tm_cgpr32_set(struct task_struct * target,const struct user_regset * regset,unsigned int pos,unsigned int count,const void * kbuf,const void __user * ubuf)7827c1f8db0SChristophe Leroy int tm_cgpr32_set(struct task_struct *target, const struct user_regset *regset,
7837c1f8db0SChristophe Leroy unsigned int pos, unsigned int count,
7847c1f8db0SChristophe Leroy const void *kbuf, const void __user *ubuf)
7857c1f8db0SChristophe Leroy {
7867c1f8db0SChristophe Leroy return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
7877c1f8db0SChristophe Leroy &target->thread.ckpt_regs.gpr[0]);
7887c1f8db0SChristophe Leroy }
789