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