Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 19cbcbf7 authored by Anshuman Khandual's avatar Anshuman Khandual Committed by Michael Ellerman
Browse files

powerpc/ptrace: Enable support for NT_PPC_CFPR



This patch enables support for TM checkpointed FPR register
set ELF core note NT_PPC_CFPR based ptrace requests through
PTRACE_GETREGSET, PTRACE_SETREGSET calls. This is achieved
through adding a register set REGSET_CFPR in powerpc
corresponding to the ELF core note section added. It
implements the get, set and active functions for this new
register set added.

Signed-off-by: default avatarAnshuman Khandual <khandual@linux.vnet.ibm.com>
Signed-off-by: default avatarSimon Guo <wei.guo.simon@gmail.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 25847fb1
Loading
Loading
Loading
Loading
+126 −0
Original line number Diff line number Diff line
@@ -1032,6 +1032,121 @@ static int tm_cgpr_set(struct task_struct *target,

	return ret;
}

/**
 * tm_cfpr_active - get active number of registers in CFPR
 * @target:	The target task.
 * @regset:	The user regset structure.
 *
 * This function checks for the active number of available
 * regisers in transaction checkpointed FPR category.
 */
static int tm_cfpr_active(struct task_struct *target,
				const struct user_regset *regset)
{
	if (!cpu_has_feature(CPU_FTR_TM))
		return -ENODEV;

	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
		return 0;

	return regset->n;
}

/**
 * tm_cfpr_get - get CFPR registers
 * @target:	The target task.
 * @regset:	The user regset structure.
 * @pos:	The buffer position.
 * @count:	Number of bytes to copy.
 * @kbuf:	Kernel buffer to copy from.
 * @ubuf:	User buffer to copy into.
 *
 * This function gets in transaction checkpointed FPR registers.
 *
 * When the transaction is active 'fp_state' holds the checkpointed
 * values for the current transaction to fall back on if it aborts
 * in between. This function gets those checkpointed FPR registers.
 * The userspace interface buffer layout is as follows.
 *
 * struct data {
 *	u64	fpr[32];
 *	u64	fpscr;
 *};
 */
static int tm_cfpr_get(struct task_struct *target,
			const struct user_regset *regset,
			unsigned int pos, unsigned int count,
			void *kbuf, void __user *ubuf)
{
	u64 buf[33];
	int i;

	if (!cpu_has_feature(CPU_FTR_TM))
		return -ENODEV;

	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
		return -ENODATA;

	flush_fp_to_thread(target);
	flush_altivec_to_thread(target);
	flush_tmregs_to_thread(target);

	/* copy to local buffer then write that out */
	for (i = 0; i < 32 ; i++)
		buf[i] = target->thread.TS_FPR(i);
	buf[32] = target->thread.fp_state.fpscr;
	return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
}

/**
 * tm_cfpr_set - set CFPR registers
 * @target:	The target task.
 * @regset:	The user regset structure.
 * @pos:	The buffer position.
 * @count:	Number of bytes to copy.
 * @kbuf:	Kernel buffer to copy into.
 * @ubuf:	User buffer to copy from.
 *
 * This function sets in transaction checkpointed FPR registers.
 *
 * When the transaction is active 'fp_state' holds the checkpointed
 * FPR register values for the current transaction to fall back on
 * if it aborts in between. This function sets these checkpointed
 * FPR registers. The userspace interface buffer layout is as follows.
 *
 * struct data {
 *	u64	fpr[32];
 *	u64	fpscr;
 *};
 */
static int 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)
{
	u64 buf[33];
	int i;

	if (!cpu_has_feature(CPU_FTR_TM))
		return -ENODEV;

	if (!MSR_TM_ACTIVE(target->thread.regs->msr))
		return -ENODATA;

	flush_fp_to_thread(target);
	flush_altivec_to_thread(target);
	flush_tmregs_to_thread(target);

	/* copy to local buffer then write that out */
	i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
	if (i)
		return i;
	for (i = 0; i < 32 ; i++)
		target->thread.TS_FPR(i) = buf[i];
	target->thread.fp_state.fpscr = buf[32];
	return 0;
}
#endif

/*
@@ -1051,6 +1166,7 @@ enum powerpc_regset {
#endif
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
	REGSET_TM_CGPR,		/* TM checkpointed GPR registers */
	REGSET_TM_CFPR,		/* TM checkpointed FPR registers */
#endif
};

@@ -1092,6 +1208,11 @@ static const struct user_regset native_regsets[] = {
		.size = sizeof(long), .align = sizeof(long),
		.active = tm_cgpr_active, .get = tm_cgpr_get, .set = tm_cgpr_set
	},
	[REGSET_TM_CFPR] = {
		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
		.size = sizeof(double), .align = sizeof(double),
		.active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
	},
#endif
};

@@ -1324,6 +1445,11 @@ static const struct user_regset compat_regsets[] = {
		.active = tm_cgpr_active,
		.get = tm_cgpr32_get, .set = tm_cgpr32_set
	},
	[REGSET_TM_CFPR] = {
		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
		.size = sizeof(double), .align = sizeof(double),
		.active = tm_cfpr_active, .get = tm_cfpr_get, .set = tm_cfpr_set
	},
#endif
};