]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.4.103/s390-fix-transactional-execution-control-register-handling.patch
4.14-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.4.103 / s390-fix-transactional-execution-control-register-handling.patch
CommitLineData
4da8666b
GKH
1From a1c5befc1c24eb9c1ee83f711e0f21ee79cbb556 Mon Sep 17 00:00:00 2001
2From: Heiko Carstens <heiko.carstens@de.ibm.com>
3Date: Thu, 9 Nov 2017 12:29:34 +0100
4Subject: s390: fix transactional execution control register handling
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9From: Heiko Carstens <heiko.carstens@de.ibm.com>
10
11commit a1c5befc1c24eb9c1ee83f711e0f21ee79cbb556 upstream.
12
13Dan Horák reported the following crash related to transactional execution:
14
15User process fault: interruption code 0013 ilc:3 in libpthread-2.26.so[3ff93c00000+1b000]
16CPU: 2 PID: 1 Comm: /init Not tainted 4.13.4-300.fc27.s390x #1
17Hardware name: IBM 2827 H43 400 (z/VM 6.4.0)
18task: 00000000fafc8000 task.stack: 00000000fafc4000
19User PSW : 0705200180000000 000003ff93c14e70
20 R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:1 AS:0 CC:2 PM:0 RI:0 EA:3
21User GPRS: 0000000000000077 000003ff00000000 000003ff93144d48 000003ff93144d5e
22 0000000000000000 0000000000000002 0000000000000000 000003ff00000000
23 0000000000000000 0000000000000418 0000000000000000 000003ffcc9fe770
24 000003ff93d28f50 000003ff9310acf0 000003ff92b0319a 000003ffcc9fe6d0
25User Code: 000003ff93c14e62: 60e0b030 std %f14,48(%r11)
26 000003ff93c14e66: 60f0b038 std %f15,56(%r11)
27 #000003ff93c14e6a: e5600000ff0e tbegin 0,65294
28 >000003ff93c14e70: a7740006 brc 7,3ff93c14e7c
29 000003ff93c14e74: a7080000 lhi %r0,0
30 000003ff93c14e78: a7f40023 brc 15,3ff93c14ebe
31 000003ff93c14e7c: b2220000 ipm %r0
32 000003ff93c14e80: 8800001c srl %r0,28
33
34There are several bugs with control register handling with respect to
35transactional execution:
36
37- on task switch update_per_regs() is only called if the next task has
38 an mm (is not a kernel thread). This however is incorrect. This
39 breaks e.g. for user mode helper handling, where the kernel creates
40 a kernel thread and then execve's a user space program. Control
41 register contents related to transactional execution won't be
42 updated on execve. If the previous task ran with transactional
43 execution disabled then the new task will also run with
44 transactional execution disabled, which is incorrect. Therefore call
45 update_per_regs() unconditionally within switch_to().
46
47- on startup the transactional execution facility is not enabled for
48 the idle thread. This is not really a bug, but an inconsistency to
49 other facilities. Therefore enable the facility if it is available.
50
51- on fork the new thread's per_flags field is not cleared. This means
52 that a child process inherits the PER_FLAG_NO_TE flag. This flag can
53 be set with a ptrace request to disable transactional execution for
54 the current process. It should not be inherited by new child
55 processes in order to be consistent with the handling of all other
56 PER related debugging options. Therefore clear the per_flags field in
57 copy_thread_tls().
58
59Reported-and-tested-by: Dan Horák <dan@danny.cz>
60Fixes: d35339a42dd1 ("s390: add support for transactional memory")
61Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
62Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
63Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
64Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
65Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
66
67---
68 arch/s390/include/asm/switch_to.h | 2 +-
69 arch/s390/kernel/early.c | 4 +++-
70 arch/s390/kernel/process.c | 1 +
71 3 files changed, 5 insertions(+), 2 deletions(-)
72
73--- a/arch/s390/include/asm/switch_to.h
74+++ b/arch/s390/include/asm/switch_to.h
75@@ -34,8 +34,8 @@ static inline void restore_access_regs(u
76 save_access_regs(&prev->thread.acrs[0]); \
77 save_ri_cb(prev->thread.ri_cb); \
78 } \
79+ update_cr_regs(next); \
80 if (next->mm) { \
81- update_cr_regs(next); \
82 set_cpu_flag(CIF_FPU); \
83 restore_access_regs(&next->thread.acrs[0]); \
84 restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
85--- a/arch/s390/kernel/early.c
86+++ b/arch/s390/kernel/early.c
87@@ -325,8 +325,10 @@ static __init void detect_machine_facili
88 S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
89 if (test_facility(40))
90 S390_lowcore.machine_flags |= MACHINE_FLAG_LPP;
91- if (test_facility(50) && test_facility(73))
92+ if (test_facility(50) && test_facility(73)) {
93 S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
94+ __ctl_set_bit(0, 55);
95+ }
96 if (test_facility(51))
97 S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
98 if (test_facility(129)) {
99--- a/arch/s390/kernel/process.c
100+++ b/arch/s390/kernel/process.c
101@@ -137,6 +137,7 @@ int copy_thread(unsigned long clone_flag
102 memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
103 memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
104 clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
105+ p->thread.per_flags = 0;
106 /* Initialize per thread user and system timer values */
107 ti = task_thread_info(p);
108 ti->user_timer = 0;