Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Thumshirn <jthumshirn@suse.de>2018-01-12 16:12:14 +0100
committerJohannes Thumshirn <jthumshirn@suse.de>2018-01-12 16:12:16 +0100
commit786f75f89adf3cd1a1b3e0de4c9db1fd3b32aef0 (patch)
treebd359242cea673c403374d45a7cf556bffe61336
parent30f19984d53a8ec58879df89e1e20af169a55e4c (diff)
s390: fix transactional execution control register handling
(bnc#1072915, LTC#162116).
-rw-r--r--patches.arch/s390-sles15-02-02-te-ctl.patch141
-rw-r--r--series.conf1
2 files changed, 142 insertions, 0 deletions
diff --git a/patches.arch/s390-sles15-02-02-te-ctl.patch b/patches.arch/s390-sles15-02-02-te-ctl.patch
new file mode 100644
index 0000000000..0a6fb1bb83
--- /dev/null
+++ b/patches.arch/s390-sles15-02-02-te-ctl.patch
@@ -0,0 +1,141 @@
+From: Heiko Carstens <heiko.carstens@de.ibm.com>
+Subject: s390: fix transactional execution control register handling
+Patch-mainline: v4.15-rc1
+Git-commit: a1c5befc1c24eb9c1ee83f711e0f21ee79cbb556
+References: bnc#1072915, LTC#162116
+
+Description: transactional execution: control register handling
+Symptom: User process crashes on transactional execution related
+ instructions like tbegin.
+Problem: There are several bugs with control register handling with
+ respect to transactional execution:
+ - on task switch update_per_regs() is only called if the
+ next task has an mm (is not a kernel thread). This
+ however is incorrect. This breaks e.g. for user mode
+ helper handling, where the kernel creates a kernel
+ thread and then execve's a user space program. Control
+ register contents related to transactional execution
+ won't be updated on execve. If the previous task ran
+ with transactional execution disabled then the new
+ task will also run with transactional execution
+ disabled, which is incorrect.
+ - on startup the transactional execution facility is not
+ enabled for the idle thread. This is not really a bug,
+ but an inconsistency to other facilities. Therefore
+ - on fork the new thread's per_flags field is not
+ cleared. This means that a child process inherits the
+ PER_FLAG_NO_TE flag. This flag can be set with a
+ ptrace request to disable transactional execution for
+ the current process. It should not be inherited by new
+ child processes in order to be consistent with the
+ handling of all other PER related debugging
+ options.
+Solution: Call update_per_regs() unconditionally within switch_to(),
+ enable the transactional execution facility as early as
+ possible if it is available, and clear the per_flags field
+ in copy_thread_tls().
+Reproduction: -
+
+Upstream-Description:
+
+ s390: fix transactional execution control register handling
+
+ Dan Horák reported the following crash related to transactional execution:
+
+ User process fault: interruption code 0013 ilc:3 in libpthread-2.26.so[3ff93c00000+1b000]
+ CPU: 2 PID: 1 Comm: /init Not tainted 4.13.4-300.fc27.s390x #1
+ Hardware name: IBM 2827 H43 400 (z/VM 6.4.0)
+ task: 00000000fafc8000 task.stack: 00000000fafc4000
+ User PSW : 0705200180000000 000003ff93c14e70
+ 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
+ User GPRS: 0000000000000077 000003ff00000000 000003ff93144d48 000003ff93144d5e
+ 0000000000000000 0000000000000002 0000000000000000 000003ff00000000
+ 0000000000000000 0000000000000418 0000000000000000 000003ffcc9fe770
+ 000003ff93d28f50 000003ff9310acf0 000003ff92b0319a 000003ffcc9fe6d0
+ User Code: 000003ff93c14e62: 60e0b030 std %f14,48(%r11)
+ 000003ff93c14e66: 60f0b038 std %f15,56(%r11)
+ #000003ff93c14e6a: e5600000ff0e tbegin 0,65294
+ >000003ff93c14e70: a7740006 brc 7,3ff93c14e7c
+ 000003ff93c14e74: a7080000 lhi %r0,0
+ 000003ff93c14e78: a7f40023 brc 15,3ff93c14ebe
+ 000003ff93c14e7c: b2220000 ipm %r0
+ 000003ff93c14e80: 8800001c srl %r0,28
+
+ There are several bugs with control register handling with respect to
+ transactional execution:
+
+ - on task switch update_per_regs() is only called if the next task has
+ an mm (is not a kernel thread). This however is incorrect. This
+ breaks e.g. for user mode helper handling, where the kernel creates
+ a kernel thread and then execve's a user space program. Control
+ register contents related to transactional execution won't be
+ updated on execve. If the previous task ran with transactional
+ execution disabled then the new task will also run with
+ transactional execution disabled, which is incorrect. Therefore call
+ update_per_regs() unconditionally within switch_to().
+
+ - on startup the transactional execution facility is not enabled for
+ the idle thread. This is not really a bug, but an inconsistency to
+ other facilities. Therefore enable the facility if it is available.
+
+ - on fork the new thread's per_flags field is not cleared. This means
+ that a child process inherits the PER_FLAG_NO_TE flag. This flag can
+ be set with a ptrace request to disable transactional execution for
+ the current process. It should not be inherited by new child
+ processes in order to be consistent with the handling of all other
+ PER related debugging options. Therefore clear the per_flags field in
+ copy_thread_tls().
+
+ Reported-and-tested-by: Dan Horák <dan@danny.cz>
+ Fixes: d35339a42dd1 ("s390: add support for transactional memory")
+ Cc: <stable@vger.kernel.org> # v3.7+
+ Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
+ Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
+ Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+
+
+Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
+Acked-by: Johannes Thumshirn <jthumshirn@suse.de>
+---
+ arch/s390/include/asm/switch_to.h | 2 +-
+ arch/s390/kernel/early.c | 4 +++-
+ arch/s390/kernel/process.c | 1 +
+ 3 files changed, 5 insertions(+), 2 deletions(-)
+
+--- a/arch/s390/include/asm/switch_to.h
++++ b/arch/s390/include/asm/switch_to.h
+@@ -36,8 +36,8 @@ static inline void restore_access_regs(u
+ save_ri_cb(prev->thread.ri_cb); \
+ save_gs_cb(prev->thread.gs_cb); \
+ } \
++ update_cr_regs(next); \
+ if (next->mm) { \
+- update_cr_regs(next); \
+ set_cpu_flag(CIF_FPU); \
+ restore_access_regs(&next->thread.acrs[0]); \
+ restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
+--- a/arch/s390/kernel/early.c
++++ b/arch/s390/kernel/early.c
+@@ -373,8 +373,10 @@ static __init void detect_machine_facili
+ S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE;
+ if (test_facility(40))
+ S390_lowcore.machine_flags |= MACHINE_FLAG_LPP;
+- if (test_facility(50) && test_facility(73))
++ if (test_facility(50) && test_facility(73)) {
+ S390_lowcore.machine_flags |= MACHINE_FLAG_TE;
++ __ctl_set_bit(0, 55);
++ }
+ if (test_facility(51))
+ S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
+ if (test_facility(129)) {
+--- a/arch/s390/kernel/process.c
++++ b/arch/s390/kernel/process.c
+@@ -99,6 +99,7 @@ int copy_thread_tls(unsigned long clone_
+ memset(&p->thread.per_user, 0, sizeof(p->thread.per_user));
+ memset(&p->thread.per_event, 0, sizeof(p->thread.per_event));
+ clear_tsk_thread_flag(p, TIF_SINGLE_STEP);
++ p->thread.per_flags = 0;
+ /* Initialize per thread user and system timer values */
+ p->thread.user_timer = 0;
+ p->thread.guest_timer = 0;
diff --git a/series.conf b/series.conf
index 8bc0889939..3233b0b16a 100644
--- a/series.conf
+++ b/series.conf
@@ -5720,6 +5720,7 @@
patches.arch/s390-sles15-00-10-03-kernel-sthyi-add-s390_sthyi-system-call.patch
patches.drivers/s390-cpu-alternatives.patch
patches.drivers/s390-spinlock-alternative.patch
+ patches.arch/s390-sles15-02-02-te-ctl.patch
patches.arch/s390-sles15-01-11-s390-noexec-execute-kexec-datamover-without-DAT.patch
patches.suse/btrfs-change-how-we-decide-to-commit-transactions-du.patch
patches.suse/btrfs-Fix-bug-for-misused-dev_t-when-lookup-in-dev-s.patch