From 4f9e67f5e03ab92ecbe51399a8cc55968106e8f9 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 27 Jan 2022 15:06:31 +0100 Subject: [PATCH 1/8] MAINTAINERS: add Alexander Gordeev as maintainer for s390 Change Alexander Gordeev's status so he is maintainer instead of reviewer for s390. Acked-by: Alexander Gordeev Acked-by: Christian Borntraeger Acked-by: Sven Schnelle Acked-by: Vasily Gorbik Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 69a2935daf6c..68b2ba510674 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16818,7 +16818,7 @@ S390 M: Heiko Carstens M: Vasily Gorbik M: Christian Borntraeger -R: Alexander Gordeev +M: Alexander Gordeev R: Sven Schnelle L: linux-s390@vger.kernel.org S: Supported From 72fc40931d7a488e1646d04f988f4d5a97b02100 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Thu, 27 Jan 2022 15:24:49 +0100 Subject: [PATCH 2/8] MAINTAINERS: downgrade myself to Reviewer for s390 Now that Alexander Gordeev has volunteered to be a co-maintainer for s390, I can act as a reviewer instead of being a maintainer for s390. With Alexander, Heiko, and Vasily we are in really good shape. I will continue to act as the maintainer for KVM on s390 together with Janosch. Signed-off-by: Christian Borntraeger Acked-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 68b2ba510674..5c56a172ce11 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -16817,8 +16817,8 @@ F: drivers/video/fbdev/savage/ S390 M: Heiko Carstens M: Vasily Gorbik -M: Christian Borntraeger M: Alexander Gordeev +R: Christian Borntraeger R: Sven Schnelle L: linux-s390@vger.kernel.org S: Supported From e286f231eab410793f3e91c924e6dbd23edee05a Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 31 Jan 2022 14:17:11 +0100 Subject: [PATCH 3/8] s390/module: fix building test_modules_helpers.o with clang Move test_modules_return_* prototypes into a header file in order to placate -Wmissing-prototypes. Fixes: 90c5318795ee ("s390/module: test loading modules with a lot of relocations") Reported-by: kernel test robot Reviewed-by: Heiko Carstens Signed-off-by: Ilya Leoshkevich Signed-off-by: Vasily Gorbik --- arch/s390/lib/test_modules.c | 3 --- arch/s390/lib/test_modules.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/s390/lib/test_modules.c b/arch/s390/lib/test_modules.c index d056baa8fbb0..9894009fc1f2 100644 --- a/arch/s390/lib/test_modules.c +++ b/arch/s390/lib/test_modules.c @@ -5,9 +5,6 @@ #include "test_modules.h" -#define DECLARE_RETURN(i) int test_modules_return_ ## i(void) -REPEAT_10000(DECLARE_RETURN); - /* * Test that modules with many relocations are loaded properly. */ diff --git a/arch/s390/lib/test_modules.h b/arch/s390/lib/test_modules.h index 43b5e4b4af3e..6371fcf17684 100644 --- a/arch/s390/lib/test_modules.h +++ b/arch/s390/lib/test_modules.h @@ -47,4 +47,7 @@ __REPEAT_10000_1(f, 8); \ __REPEAT_10000_1(f, 9) +#define DECLARE_RETURN(i) int test_modules_return_ ## i(void) +REPEAT_10000(DECLARE_RETURN); + #endif From dd9cb842fa9d90653a9b48aba52f89c069f3bc50 Mon Sep 17 00:00:00 2001 From: Vineeth Vijayan Date: Wed, 2 Feb 2022 21:45:56 +0100 Subject: [PATCH 4/8] s390/cio: verify the driver availability for path_event call If no driver is attached to a device or the driver does not provide the path_event function, an FCES path-event on this device could end up in a kernel-panic. Verify the driver availability before the path_event function call. Fixes: 32ef938815c1 ("s390/cio: Add support for FCES status notification") Cc: stable@vger.kernel.org Signed-off-by: Vineeth Vijayan Suggested-by: Peter Oberparleiter Reviewed-by: Jan Hoeppner Reviewed-by: Peter Oberparleiter Signed-off-by: Vasily Gorbik --- drivers/s390/cio/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index cd938a26b76c..3b1cd0c96a74 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1180,7 +1180,7 @@ static int io_subchannel_chp_event(struct subchannel *sch, else path_event[chpid] = PE_NONE; } - if (cdev) + if (cdev && cdev->drv && cdev->drv->path_event) cdev->drv->path_event(cdev, path_event); break; } From 6b4b54c7ca347bcb4aa7a3cc01aa16e84ac7fbe4 Mon Sep 17 00:00:00 2001 From: Alexander Egorenkov Date: Wed, 9 Feb 2022 11:25:09 +0100 Subject: [PATCH 5/8] s390/setup: preserve memory at OLDMEM_BASE and OLDMEM_SIZE We need to preserve the values at OLDMEM_BASE and OLDMEM_SIZE which are used by zgetdump in case when kdump crashes. In that case zgetdump will attempt to read OLDMEM_BASE and OLDMEM_SIZE in order to find out where the memory range [0 - OLDMEM_SIZE] belonging to the production kernel is. Fixes: f1a546947431 ("s390/setup: don't reserve memory that occupied decompressor's head") Cc: stable@vger.kernel.org # 5.15+ Signed-off-by: Alexander Egorenkov Acked-by: Vasily Gorbik Signed-off-by: Vasily Gorbik --- arch/s390/kernel/setup.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index f2c25d113e7b..05327be3a982 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -800,6 +800,8 @@ static void __init check_initrd(void) static void __init reserve_kernel(void) { memblock_reserve(0, STARTUP_NORMAL_OFFSET); + memblock_reserve(OLDMEM_BASE, sizeof(unsigned long)); + memblock_reserve(OLDMEM_SIZE, sizeof(unsigned long)); memblock_reserve(__amode31_base, __eamode31 - __samode31); memblock_reserve(__pa(sclp_early_sccb), EXT_SCCB_READ_SCP); memblock_reserve(__pa(_stext), _end - _stext); From 9fa881f7e3c74ce6626d166bca9397e5d925937f Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 23 Feb 2022 13:02:59 +0100 Subject: [PATCH 6/8] s390/ftrace: fix ftrace_caller/ftrace_regs_caller generation ftrace_caller was used for both ftrace_caller and ftrace_regs_caller, which means that the target address of the hotpatch trampoline was never updated. With commit 894979689d3a ("s390/ftrace: provide separate ftrace_caller/ftrace_regs_caller implementations") a separate ftrace_regs_caller entry point was implemeted, however it was forgotten to implement the necessary changes for ftrace_modify_call and ftrace_make_call, where the branch target has to be modified accordingly. Therefore add the missing code now. Fixes: 894979689d3a ("s390/ftrace: provide separate ftrace_caller/ftrace_regs_caller implementations") Reviewed-by: Sven Schnelle Acked-by: Ilya Leoshkevich Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/kernel/ftrace.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 21d62d8b6b9a..5026d218066d 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -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; } From 1389f17937a03fe4ec71b094e1aa6530a901963e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 22 Feb 2022 14:53:47 +0100 Subject: [PATCH 7/8] s390/ftrace: fix arch_ftrace_get_regs implementation arch_ftrace_get_regs is supposed to return a struct pt_regs pointer only if the pt_regs structure contains all register contents, which means it must have been populated when created via ftrace_regs_caller. If it was populated via ftrace_caller the contents are not complete (the psw mask part is missing), and therefore a NULL pointer needs be returned. The current code incorrectly always returns a struct pt_regs pointer. Fix this by adding another pt_regs flag which indicates if the contents are complete, and fix arch_ftrace_get_regs accordingly. Fixes: 894979689d3a ("s390/ftrace: provide separate ftrace_caller/ftrace_regs_caller implementations") Reported-by: Christophe Leroy Reported-by: Naveen N. Rao Reviewed-by: Sven Schnelle Acked-by: Ilya Leoshkevich Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/ftrace.h | 10 ++++++---- arch/s390/include/asm/ptrace.h | 2 ++ arch/s390/kernel/ftrace.c | 2 +- arch/s390/kernel/mcount.S | 9 +++++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index 267f70f4393f..6f80ec9c04be 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h @@ -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; } /* diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 4ffa8e7f0ed3..ddb70fb13fbc 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -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__ diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index 5026d218066d..89c0870d5679 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c @@ -326,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()) { diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S index 39bcc0e39a10..a24177dcd12a 100644 --- a/arch/s390/kernel/mcount.S +++ b/arch/s390/kernel/mcount.S @@ -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 From c194dad21025dfd043210912653baab823bdff67 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 24 Feb 2022 22:03:29 +0100 Subject: [PATCH 8/8] s390/extable: fix exception table sorting s390 has a swap_ex_entry_fixup function, however it is not being used since common code expects a swap_ex_entry_fixup define. If it is not defined the default implementation will be used. So fix this by adding a proper define. However also the implementation of the function must be fixed, since a NULL value for handler has a special meaning and must not be adjusted. Luckily all of this doesn't fix a real bug currently: the main extable is correctly sorted during build time, and for runtime sorting there is currently no case where the handler field is not NULL. Fixes: 05a68e892e89 ("s390/kernel: expand exception table logic to allow new handling options") Acked-by: Ilya Leoshkevich Reviewed-by: Alexander Gordeev Signed-off-by: Heiko Carstens Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/extable.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arch/s390/include/asm/extable.h b/arch/s390/include/asm/extable.h index 16dc57dd90b3..8511f0e59290 100644 --- a/arch/s390/include/asm/extable.h +++ b/arch/s390/include/asm/extable.h @@ -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