Commit 640586f8 authored by Oleg Nesterov's avatar Oleg Nesterov Committed by Michael Ellerman
Browse files

powerpc/ptrace: Simplify gpr_get()/tm_cgpr_get()



gpr_get() does membuf_write() twice to override pt_regs->msr in
between. We can call membuf_write() once and change ->msr in the
kernel buffer, this simplifies the code and the next fix.

The patch adds a new simple helper, membuf_at(offs), it returns the
new membuf which can be safely used after membuf_write().

Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
[mpe: Fixup some minor whitespace issues noticed by Christophe]
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20201119160221.GA5188@redhat.com
parent 20fa40b1
Loading
Loading
Loading
Loading
+4 −8
Original line number Diff line number Diff line
@@ -86,6 +86,8 @@ int tm_cgpr_active(struct task_struct *target, const struct user_regset *regset)
int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
		struct membuf to)
{
	struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr));

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

@@ -96,16 +98,10 @@ int tm_cgpr_get(struct task_struct *target, const struct user_regset *regset,
	flush_fp_to_thread(target);
	flush_altivec_to_thread(target);

	membuf_write(&to, &target->thread.ckpt_regs,
			offsetof(struct pt_regs, msr));
	membuf_store(&to, get_user_ckpt_msr(target));
	membuf_write(&to, &target->thread.ckpt_regs, sizeof(struct user_pt_regs));

	BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
		     offsetof(struct pt_regs, msr) + sizeof(long));
	membuf_store(&to_msr, get_user_ckpt_msr(target));

	membuf_write(&to, &target->thread.ckpt_regs.orig_gpr3,
			sizeof(struct user_pt_regs) -
			offsetof(struct pt_regs, orig_gpr3));
	return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) -
			sizeof(struct user_pt_regs));
}
+3 −7
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
static int gpr_get(struct task_struct *target, const struct user_regset *regset,
		   struct membuf to)
{
	struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr));
	int i;

	if (target->thread.regs == NULL)
@@ -228,15 +229,10 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset,
			target->thread.regs->gpr[i] = NV_REG_POISON;
	}

	membuf_write(&to, target->thread.regs, offsetof(struct pt_regs, msr));
	membuf_store(&to, get_user_msr(target));
	membuf_write(&to, target->thread.regs, sizeof(struct user_pt_regs));

	BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
		     offsetof(struct pt_regs, msr) + sizeof(long));
	membuf_store(&to_msr, get_user_msr(target));

	membuf_write(&to, &target->thread.regs->orig_gpr3,
			sizeof(struct user_pt_regs) -
			offsetof(struct pt_regs, orig_gpr3));
	return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) -
				 sizeof(struct user_pt_regs));
}
+12 −0
Original line number Diff line number Diff line
@@ -46,6 +46,18 @@ static inline int membuf_write(struct membuf *s, const void *v, size_t size)
	return s->left;
}

static inline struct membuf membuf_at(const struct membuf *s, size_t offs)
{
	struct membuf n = *s;

	if (offs > n.left)
		offs = n.left;
	n.p += offs;
	n.left -= offs;

	return n;
}

/* current s->p must be aligned for v; v must be a scalar */
#define membuf_store(s, v)				\
({							\