Skip to content

Commit f9026e1

Browse files
committed
Merge tag 's390-5.17-5' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
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
2 parents ac84e82 + c194dad commit f9026e1

File tree

6 files changed

+62
-7
lines changed

6 files changed

+62
-7
lines changed

arch/s390/include/asm/extable.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,13 @@ static inline void swap_ex_entry_fixup(struct exception_table_entry *a,
6969
{
7070
a->fixup = b->fixup + delta;
7171
b->fixup = tmp.fixup - delta;
72-
a->handler = b->handler + delta;
73-
b->handler = tmp.handler - delta;
72+
a->handler = b->handler;
73+
if (a->handler)
74+
a->handler += delta;
75+
b->handler = tmp.handler;
76+
if (b->handler)
77+
b->handler -= delta;
7478
}
79+
#define swap_ex_entry_fixup swap_ex_entry_fixup
7580

7681
#endif

arch/s390/include/asm/ftrace.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,17 @@ struct ftrace_regs {
4747

4848
static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
4949
{
50-
return &fregs->regs;
50+
struct pt_regs *regs = &fregs->regs;
51+
52+
if (test_pt_regs_flag(regs, PIF_FTRACE_FULL_REGS))
53+
return regs;
54+
return NULL;
5155
}
5256

5357
static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *fregs,
5458
unsigned long ip)
5559
{
56-
struct pt_regs *regs = arch_ftrace_get_regs(fregs);
57-
58-
regs->psw.addr = ip;
60+
fregs->regs.psw.addr = ip;
5961
}
6062

6163
/*

arch/s390/include/asm/ptrace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
#define PIF_EXECVE_PGSTE_RESTART 1 /* restart execve for PGSTE binaries */
1616
#define PIF_SYSCALL_RET_SET 2 /* return value was set via ptrace */
1717
#define PIF_GUEST_FAULT 3 /* indicates program check in sie64a */
18+
#define PIF_FTRACE_FULL_REGS 4 /* all register contents valid (ftrace) */
1819

1920
#define _PIF_SYSCALL BIT(PIF_SYSCALL)
2021
#define _PIF_EXECVE_PGSTE_RESTART BIT(PIF_EXECVE_PGSTE_RESTART)
2122
#define _PIF_SYSCALL_RET_SET BIT(PIF_SYSCALL_RET_SET)
2223
#define _PIF_GUEST_FAULT BIT(PIF_GUEST_FAULT)
24+
#define _PIF_FTRACE_FULL_REGS BIT(PIF_FTRACE_FULL_REGS)
2325

2426
#ifndef __ASSEMBLY__
2527

arch/s390/kernel/ftrace.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,38 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
159159
return 0;
160160
}
161161

162+
static struct ftrace_hotpatch_trampoline *ftrace_get_trampoline(struct dyn_ftrace *rec)
163+
{
164+
struct ftrace_hotpatch_trampoline *trampoline;
165+
struct ftrace_insn insn;
166+
s64 disp;
167+
u16 opc;
168+
169+
if (copy_from_kernel_nofault(&insn, (void *)rec->ip, sizeof(insn)))
170+
return ERR_PTR(-EFAULT);
171+
disp = (s64)insn.disp * 2;
172+
trampoline = (void *)(rec->ip + disp);
173+
if (get_kernel_nofault(opc, &trampoline->brasl_opc))
174+
return ERR_PTR(-EFAULT);
175+
if (opc != 0xc015)
176+
return ERR_PTR(-EINVAL);
177+
return trampoline;
178+
}
179+
162180
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
163181
unsigned long addr)
164182
{
183+
struct ftrace_hotpatch_trampoline *trampoline;
184+
u64 old;
185+
186+
trampoline = ftrace_get_trampoline(rec);
187+
if (IS_ERR(trampoline))
188+
return PTR_ERR(trampoline);
189+
if (get_kernel_nofault(old, &trampoline->interceptor))
190+
return -EFAULT;
191+
if (old != old_addr)
192+
return -EINVAL;
193+
s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
165194
return 0;
166195
}
167196

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

189218
int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
190219
{
220+
struct ftrace_hotpatch_trampoline *trampoline;
221+
222+
trampoline = ftrace_get_trampoline(rec);
223+
if (IS_ERR(trampoline))
224+
return PTR_ERR(trampoline);
225+
s390_kernel_write(&trampoline->interceptor, &addr, sizeof(addr));
191226
brcl_enable((void *)rec->ip);
192227
return 0;
193228
}
@@ -291,7 +326,7 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
291326

292327
regs = ftrace_get_regs(fregs);
293328
p = get_kprobe((kprobe_opcode_t *)ip);
294-
if (unlikely(!p) || kprobe_disabled(p))
329+
if (!regs || unlikely(!p) || kprobe_disabled(p))
295330
goto out;
296331

297332
if (kprobe_running()) {

arch/s390/kernel/mcount.S

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ ENDPROC(ftrace_stub)
2727
#define STACK_PTREGS_GPRS (STACK_PTREGS + __PT_GPRS)
2828
#define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW)
2929
#define STACK_PTREGS_ORIG_GPR2 (STACK_PTREGS + __PT_ORIG_GPR2)
30+
#define STACK_PTREGS_FLAGS (STACK_PTREGS + __PT_FLAGS)
3031
#ifdef __PACK_STACK
3132
/* allocate just enough for r14, r15 and backchain */
3233
#define TRACED_FUNC_FRAME_SIZE 24
@@ -57,6 +58,14 @@ ENDPROC(ftrace_stub)
5758
.if \allregs == 1
5859
stg %r14,(STACK_PTREGS_PSW)(%r15)
5960
stosm (STACK_PTREGS_PSW)(%r15),0
61+
#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
62+
mvghi STACK_PTREGS_FLAGS(%r15),_PIF_FTRACE_FULL_REGS
63+
#else
64+
lghi %r14,_PIF_FTRACE_FULL_REGS
65+
stg %r14,STACK_PTREGS_FLAGS(%r15)
66+
#endif
67+
.else
68+
xc STACK_PTREGS_FLAGS(8,%r15),STACK_PTREGS_FLAGS(%r15)
6069
.endif
6170

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

arch/s390/kernel/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,8 @@ static void __init check_initrd(void)
800800
static void __init reserve_kernel(void)
801801
{
802802
memblock_reserve(0, STARTUP_NORMAL_OFFSET);
803+
memblock_reserve(OLDMEM_BASE, sizeof(unsigned long));
804+
memblock_reserve(OLDMEM_SIZE, sizeof(unsigned long));
803805
memblock_reserve(__amode31_base, __eamode31 - __samode31);
804806
memblock_reserve(__pa(sclp_early_sccb), EXT_SCCB_READ_SCP);
805807
memblock_reserve(__pa(_stext), _end - _stext);

0 commit comments

Comments
 (0)