]>
Commit | Line | Data |
---|---|---|
4da8666b GKH |
1 | From a1c5befc1c24eb9c1ee83f711e0f21ee79cbb556 Mon Sep 17 00:00:00 2001 |
2 | From: Heiko Carstens <heiko.carstens@de.ibm.com> | |
3 | Date: Thu, 9 Nov 2017 12:29:34 +0100 | |
4 | Subject: s390: fix transactional execution control register handling | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | From: Heiko Carstens <heiko.carstens@de.ibm.com> | |
10 | ||
11 | commit a1c5befc1c24eb9c1ee83f711e0f21ee79cbb556 upstream. | |
12 | ||
13 | Dan Horák reported the following crash related to transactional execution: | |
14 | ||
15 | User process fault: interruption code 0013 ilc:3 in libpthread-2.26.so[3ff93c00000+1b000] | |
16 | CPU: 2 PID: 1 Comm: /init Not tainted 4.13.4-300.fc27.s390x #1 | |
17 | Hardware name: IBM 2827 H43 400 (z/VM 6.4.0) | |
18 | task: 00000000fafc8000 task.stack: 00000000fafc4000 | |
19 | User 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 | |
21 | User GPRS: 0000000000000077 000003ff00000000 000003ff93144d48 000003ff93144d5e | |
22 | 0000000000000000 0000000000000002 0000000000000000 000003ff00000000 | |
23 | 0000000000000000 0000000000000418 0000000000000000 000003ffcc9fe770 | |
24 | 000003ff93d28f50 000003ff9310acf0 000003ff92b0319a 000003ffcc9fe6d0 | |
25 | User 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 | ||
34 | There are several bugs with control register handling with respect to | |
35 | transactional 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 | ||
59 | Reported-and-tested-by: Dan Horák <dan@danny.cz> | |
60 | Fixes: d35339a42dd1 ("s390: add support for transactional memory") | |
61 | Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
62 | Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> | |
63 | Reviewed-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | |
64 | Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> | |
65 | Signed-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; |