Commit f9026e19 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull s390 fixes from Vasily Gorbik:

 - Fix HAVE_DYNAMIC_FTRACE_WITH_ARGS implementation by providing correct
   switching between ftrace_caller/ftrace_regs_caller and supplying
   pt_regs only when ftrace_regs_caller is activated.

 - Fix exception table sorting.

 - Fix breakage of kdump tooling by preserving metadata it cannot
   function without.

* tag 's390-5.17-5' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/extable: fix exception table sorting
  s390/ftrace: fix arch_ftrace_get_regs implementation
  s390/ftrace: fix ftrace_caller/ftrace_regs_caller generation
  s390/setup: preserve memory at OLDMEM_BASE and OLDMEM_SIZE
parents ac84e82f c194dad2
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -69,8 +69,13 @@ static inline void swap_ex_entry_fixup(struct exception_table_entry *a,
{
	a->fixup = b->fixup + delta;
	b->fixup = tmp.fixup - delta;
	a->handler = b->handler + delta;
	b->handler = tmp.handler - delta;
	a->handler = b->handler;
	if (a->handler)
		a->handler += delta;
	b->handler = tmp.handler;
	if (b->handler)
		b->handler -= delta;
}
#define swap_ex_entry_fixup swap_ex_entry_fixup

#endif
+6 −4
Original line number Diff line number Diff line
@@ -47,15 +47,17 @@ struct ftrace_regs {

static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
{
	return &fregs->regs;
	struct pt_regs *regs = &fregs->regs;

	if (test_pt_regs_flag(regs, PIF_FTRACE_FULL_REGS))
		return regs;
	return NULL;
}

static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *fregs,
							   unsigned long ip)
{
	struct pt_regs *regs = arch_ftrace_get_regs(fregs);

	regs->psw.addr = ip;
	fregs->regs.psw.addr = ip;
}

/*
+2 −0
Original line number Diff line number Diff line
@@ -15,11 +15,13 @@
#define PIF_EXECVE_PGSTE_RESTART	1	/* restart execve for PGSTE binaries */
#define PIF_SYSCALL_RET_SET		2	/* return value was set via ptrace */
#define PIF_GUEST_FAULT			3	/* indicates program check in sie64a */
#define PIF_FTRACE_FULL_REGS		4	/* all register contents valid (ftrace) */

#define _PIF_SYSCALL			BIT(PIF_SYSCALL)
#define _PIF_EXECVE_PGSTE_RESTART	BIT(PIF_EXECVE_PGSTE_RESTART)
#define _PIF_SYSCALL_RET_SET		BIT(PIF_SYSCALL_RET_SET)
#define _PIF_GUEST_FAULT		BIT(PIF_GUEST_FAULT)
#define _PIF_FTRACE_FULL_REGS		BIT(PIF_FTRACE_FULL_REGS)

#ifndef __ASSEMBLY__

+36 −1
Original line number Diff line number Diff line
@@ -159,9 +159,38 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
	return 0;
}

static struct ftrace_hotpatch_trampoline *ftrace_get_trampoline(struct dyn_ftrace *rec)
{
	struct ftrace_hotpatch_trampoline *trampoline;
	struct ftrace_insn insn;
	s64 disp;
	u16 opc;

	if (copy_from_kernel_nofault(&insn, (void *)rec->ip, sizeof(insn)))
		return ERR_PTR(-EFAULT);
	disp = (s64)insn.disp * 2;
	trampoline = (void *)(rec->ip + disp);
	if (get_kernel_nofault(opc, &trampoline->brasl_opc))
		return ERR_PTR(-EFAULT);
	if (opc != 0xc015)
		return ERR_PTR(-EINVAL);
	return trampoline;
}

int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
		       unsigned long addr)
{
	struct ftrace_hotpatch_trampoline *trampoline;
	u64 old;

	trampoline = ftrace_get_trampoline(rec);
	if (IS_ERR(trampoline))
		return PTR_ERR(trampoline);
	if (get_kernel_nofault(old, &trampoline->interceptor))
		return -EFAULT;
	if (old != old_addr)
		return -EINVAL;
	s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
	return 0;
}

@@ -188,6 +217,12 @@ static void brcl_enable(void *brcl)

int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{
	struct ftrace_hotpatch_trampoline *trampoline;

	trampoline = ftrace_get_trampoline(rec);
	if (IS_ERR(trampoline))
		return PTR_ERR(trampoline);
	s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
	brcl_enable((void *)rec->ip);
	return 0;
}
@@ -291,7 +326,7 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,

	regs = ftrace_get_regs(fregs);
	p = get_kprobe((kprobe_opcode_t *)ip);
	if (unlikely(!p) || kprobe_disabled(p))
	if (!regs || unlikely(!p) || kprobe_disabled(p))
		goto out;

	if (kprobe_running()) {
+9 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ ENDPROC(ftrace_stub)
#define STACK_PTREGS_GPRS	(STACK_PTREGS + __PT_GPRS)
#define STACK_PTREGS_PSW	(STACK_PTREGS + __PT_PSW)
#define STACK_PTREGS_ORIG_GPR2	(STACK_PTREGS + __PT_ORIG_GPR2)
#define STACK_PTREGS_FLAGS	(STACK_PTREGS + __PT_FLAGS)
#ifdef __PACK_STACK
/* allocate just enough for r14, r15 and backchain */
#define TRACED_FUNC_FRAME_SIZE	24
@@ -57,6 +58,14 @@ ENDPROC(ftrace_stub)
	.if \allregs == 1
	stg	%r14,(STACK_PTREGS_PSW)(%r15)
	stosm	(STACK_PTREGS_PSW)(%r15),0
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
	mvghi	STACK_PTREGS_FLAGS(%r15),_PIF_FTRACE_FULL_REGS
#else
	lghi	%r14,_PIF_FTRACE_FULL_REGS
	stg	%r14,STACK_PTREGS_FLAGS(%r15)
#endif
	.else
	xc	STACK_PTREGS_FLAGS(8,%r15),STACK_PTREGS_FLAGS(%r15)
	.endif

	lg	%r14,(__SF_GPRS+8*8)(%r1)	# restore original return address
Loading