Commit 609355df authored by Christopher M. Riedl's avatar Christopher M. Riedl Committed by Michael Ellerman
Browse files

powerpc/signal: Add unsafe_copy_{vsx, fpr}_from_user()



Reuse the "safe" implementation from signal.c but call unsafe_get_user()
directly in a loop to avoid the intermediate copy into a local buffer.

Signed-off-by: default avatarChristopher M. Riedl <cmr@codefail.de>
Reviewed-by: default avatarDaniel Axtens <dja@axtens.net>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20210227011259.11992-3-cmr@codefail.de
parent 9466c179
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -53,6 +53,26 @@ unsigned long copy_ckfpr_from_user(struct task_struct *task, void __user *from);
				&buf[i], label);\
} while (0)

#define unsafe_copy_fpr_from_user(task, from, label)	do {		\
	struct task_struct *__t = task;					\
	u64 __user *buf = (u64 __user *)from;				\
	int i;								\
									\
	for (i = 0; i < ELF_NFPREG - 1; i++)				\
		unsafe_get_user(__t->thread.TS_FPR(i), &buf[i], label); \
	unsafe_get_user(__t->thread.fp_state.fpscr, &buf[i], label);	\
} while (0)

#define unsafe_copy_vsx_from_user(task, from, label)	do {		\
	struct task_struct *__t = task;					\
	u64 __user *buf = (u64 __user *)from;				\
	int i;								\
									\
	for (i = 0; i < ELF_NVSRHALFREG ; i++)				\
		unsafe_get_user(__t->thread.fp_state.fpr[i][TS_VSRLOWOFFSET], \
				&buf[i], label);			\
} while (0)

#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
#define unsafe_copy_ckfpr_to_user(to, task, label)	do {		\
	struct task_struct *__t = task;					\
@@ -80,6 +100,10 @@ unsigned long copy_ckfpr_from_user(struct task_struct *task, void __user *from);
	unsafe_copy_to_user(to, (task)->thread.fp_state.fpr,	\
			    ELF_NFPREG * sizeof(double), label)

#define unsafe_copy_fpr_from_user(task, from, label)			\
	unsafe_copy_from_user((task)->thread.fp_state.fpr, from,	\
			    ELF_NFPREG * sizeof(double), label)

static inline unsigned long
copy_fpr_to_user(void __user *to, struct task_struct *task)
{
@@ -115,6 +139,8 @@ copy_ckfpr_from_user(struct task_struct *task, void __user *from)
#else
#define unsafe_copy_fpr_to_user(to, task, label) do { } while (0)

#define unsafe_copy_fpr_from_user(task, from, label) do { } while (0)

static inline unsigned long
copy_fpr_to_user(void __user *to, struct task_struct *task)
{