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

Commit 08e1c01d authored by Anshuman Khandual's avatar Anshuman Khandual Committed by Michael Ellerman
Browse files

powerpc/ptrace: Enable support for TM SPR state



This patch enables support for TM SPR state related ELF core
note NT_PPC_TM_SPR based ptrace requests through PTRACE_GETREGSET,
PTRACE_SETREGSET calls. This is achieved through adding a register
set REGSET_TM_SPR 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 9d3918f7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@
#define ELF_NFPREG	33	/* includes fpscr */
#define ELF_NVMX	34	/* includes all vector registers */
#define ELF_NVSX	32	/* includes all VSX registers */
#define ELF_NTMSPRREG	3	/* include tfhar, tfiar, texasr */

typedef unsigned long elf_greg_t64;
typedef elf_greg_t64 elf_gregset_t64[ELF_NGREG];
+142 −1
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ struct pt_regs_offset {

#define TVSO(f)	(offsetof(struct thread_vr_state, f))
#define TFSO(f)	(offsetof(struct thread_fp_state, f))
#define TSO(f)	(offsetof(struct thread_struct, f))

static const struct pt_regs_offset regoffset_table[] = {
	GPR_OFFSET_NAME(0),
@@ -1412,7 +1413,136 @@ static int tm_cvsx_set(struct task_struct *target,

	return ret;
}
#endif

/**
 * tm_spr_active - get active number of registers in TM SPR
 * @target:	The target task.
 * @regset:	The user regset structure.
 *
 * This function checks the active number of available
 * regisers in the transactional memory SPR category.
 */
static int tm_spr_active(struct task_struct *target,
			 const struct user_regset *regset)
{
	if (!cpu_has_feature(CPU_FTR_TM))
		return -ENODEV;

	return regset->n;
}

/**
 * tm_spr_get - get the TM related SPR 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 transactional memory related SPR registers.
 * The userspace interface buffer layout is as follows.
 *
 * struct {
 *	u64		tm_tfhar;
 *	u64		tm_texasr;
 *	u64		tm_tfiar;
 * };
 */
static int tm_spr_get(struct task_struct *target,
		      const struct user_regset *regset,
		      unsigned int pos, unsigned int count,
		      void *kbuf, void __user *ubuf)
{
	int ret;

	/* Build tests */
	BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
	BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
	BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));

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

	/* Flush the states */
	flush_fp_to_thread(target);
	flush_altivec_to_thread(target);
	flush_tmregs_to_thread(target);

	/* TFHAR register */
	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				&target->thread.tm_tfhar, 0, sizeof(u64));

	/* TEXASR register */
	if (!ret)
		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				&target->thread.tm_texasr, sizeof(u64),
				2 * sizeof(u64));

	/* TFIAR register */
	if (!ret)
		ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				&target->thread.tm_tfiar,
				2 * sizeof(u64), 3 * sizeof(u64));
	return ret;
}

/**
 * tm_spr_set - set the TM related SPR 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 transactional memory related SPR registers.
 * The userspace interface buffer layout is as follows.
 *
 * struct {
 *	u64		tm_tfhar;
 *	u64		tm_texasr;
 *	u64		tm_tfiar;
 * };
 */
static int 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)
{
	int ret;

	/* Build tests */
	BUILD_BUG_ON(TSO(tm_tfhar) + sizeof(u64) != TSO(tm_texasr));
	BUILD_BUG_ON(TSO(tm_texasr) + sizeof(u64) != TSO(tm_tfiar));
	BUILD_BUG_ON(TSO(tm_tfiar) + sizeof(u64) != TSO(ckpt_regs));

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

	/* Flush the states */
	flush_fp_to_thread(target);
	flush_altivec_to_thread(target);
	flush_tmregs_to_thread(target);

	/* TFHAR register */
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				&target->thread.tm_tfhar, 0, sizeof(u64));

	/* TEXASR register */
	if (!ret)
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				&target->thread.tm_texasr, sizeof(u64),
				2 * sizeof(u64));

	/* TFIAR register */
	if (!ret)
		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				&target->thread.tm_tfiar,
				 2 * sizeof(u64), 3 * sizeof(u64));
	return ret;
}
#endif	/* CONFIG_PPC_TRANSACTIONAL_MEM */

/*
 * These are our native regset flavors.
@@ -1434,6 +1564,7 @@ enum powerpc_regset {
	REGSET_TM_CFPR,		/* TM checkpointed FPR registers */
	REGSET_TM_CVMX,		/* TM checkpointed VMX registers */
	REGSET_TM_CVSX,		/* TM checkpointed VSX registers */
	REGSET_TM_SPR,		/* TM specific SPR registers */
#endif
};

@@ -1490,6 +1621,11 @@ static const struct user_regset native_regsets[] = {
		.size = sizeof(double), .align = sizeof(double),
		.active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
	},
	[REGSET_TM_SPR] = {
		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
		.size = sizeof(u64), .align = sizeof(u64),
		.active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
	},
#endif
};

@@ -1737,6 +1873,11 @@ static const struct user_regset compat_regsets[] = {
		.size = sizeof(double), .align = sizeof(double),
		.active = tm_cvsx_active, .get = tm_cvsx_get, .set = tm_cvsx_set
	},
	[REGSET_TM_SPR] = {
		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
		.size = sizeof(u64), .align = sizeof(u64),
		.active = tm_spr_active, .get = tm_spr_get, .set = tm_spr_set
	},
#endif
};