]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.1/nds32-avoid-iex-status-being-incorrectly-modified.patch
4.19-stable patches
[thirdparty/kernel/stable-queue.git] / queue-5.1 / nds32-avoid-iex-status-being-incorrectly-modified.patch
1 From 7f214592e69ae8ea788b0a1413191e9de05190d3 Mon Sep 17 00:00:00 2001
2 From: Vincent Chen <vincentc@andestech.com>
3 Date: Mon, 20 May 2019 09:21:12 +0800
4 Subject: nds32: Avoid IEX status being incorrectly modified
5
6 [ Upstream commit ed32949e0acb73e7bc054bb02e0453d4d561ceda ]
7
8 In order for kernel to capture each denormalized output, the UDF
9 trapping enable bit is always raised in $fpcsr. Because underflow case will
10 issue not an underflow exception but also an inexact exception, it causes
11 that the IEX, IEX cumulative exception, flag in $fpcsr to be raised in each
12 denormalized output handling. To make the emulation transparent to the
13 user, the emulator needs to clear the IEX flag in $fpcsr if the result is a
14 denormalized number. However, if the IEX flag has been raised before this
15 floating point emulation, this cleanup may be incorrect. To avoid the IEX
16 flags in $fpcsr be raised in each denormalized output handling, the IEX
17 trap shall be always enabled.
18
19 Signed-off-by: Vincent Chen <vincentc@andestech.com>
20 Acked-by: Greentime Hu <greentime@andestech.com>
21 Signed-off-by: Greentime Hu <greentime@andestech.com>
22 Signed-off-by: Sasha Levin <sashal@kernel.org>
23 ---
24 arch/nds32/include/asm/bitfield.h | 2 +-
25 arch/nds32/include/asm/fpu.h | 2 +-
26 arch/nds32/include/asm/syscalls.h | 2 +-
27 arch/nds32/include/uapi/asm/fp_udfiex_crtl.h | 16 ++++++++++++
28 arch/nds32/include/uapi/asm/sigcontext.h | 24 ++++++++++++------
29 arch/nds32/include/uapi/asm/udftrap.h | 13 ----------
30 arch/nds32/include/uapi/asm/unistd.h | 4 +--
31 arch/nds32/kernel/fpu.c | 15 +++++------
32 arch/nds32/kernel/sys_nds32.c | 26 +++++++++++---------
33 9 files changed, 58 insertions(+), 46 deletions(-)
34 create mode 100644 arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
35 delete mode 100644 arch/nds32/include/uapi/asm/udftrap.h
36
37 diff --git a/arch/nds32/include/asm/bitfield.h b/arch/nds32/include/asm/bitfield.h
38 index 7414fcbbab4e..03bbb6d27828 100644
39 --- a/arch/nds32/include/asm/bitfield.h
40 +++ b/arch/nds32/include/asm/bitfield.h
41 @@ -937,7 +937,7 @@
42 #define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT )
43 #define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT )
44 #define FPCSR_mskALL (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
45 -#define FPCSR_mskALLE_NO_UDFE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskIEXE)
46 +#define FPCSR_mskALLE_NO_UDF_IEXE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE)
47 #define FPCSR_mskALLE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
48 #define FPCSR_mskALLT (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)
49
50 diff --git a/arch/nds32/include/asm/fpu.h b/arch/nds32/include/asm/fpu.h
51 index 019f1bcfc5ee..8294ed4aaa2c 100644
52 --- a/arch/nds32/include/asm/fpu.h
53 +++ b/arch/nds32/include/asm/fpu.h
54 @@ -36,7 +36,7 @@ extern int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu);
55 * enabled by default and kerenl will re-execute it by fpu emulator
56 * when getting underflow exception.
57 */
58 -#define FPCSR_INIT FPCSR_mskUDFE
59 +#define FPCSR_INIT (FPCSR_mskUDFE | FPCSR_mskIEXE)
60 #else
61 #define FPCSR_INIT 0x0UL
62 #endif
63 diff --git a/arch/nds32/include/asm/syscalls.h b/arch/nds32/include/asm/syscalls.h
64 index da32101b455d..b9c9becce5d6 100644
65 --- a/arch/nds32/include/asm/syscalls.h
66 +++ b/arch/nds32/include/asm/syscalls.h
67 @@ -7,7 +7,7 @@
68 asmlinkage long sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op);
69 asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len);
70 asmlinkage long sys_rt_sigreturn_wrapper(void);
71 -asmlinkage long sys_udftrap(int option);
72 +asmlinkage long sys_fp_udfiex_crtl(int cmd, int act);
73
74 #include <asm-generic/syscalls.h>
75
76 diff --git a/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h b/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
77 new file mode 100644
78 index 000000000000..d54a5d6c6538
79 --- /dev/null
80 +++ b/arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
81 @@ -0,0 +1,16 @@
82 +/* SPDX-License-Identifier: GPL-2.0 */
83 +/* Copyright (C) 2005-2019 Andes Technology Corporation */
84 +#ifndef _FP_UDF_IEX_CRTL_H
85 +#define _FP_UDF_IEX_CRTL_H
86 +
87 +/*
88 + * The cmd list of sys_fp_udfiex_crtl()
89 + */
90 +/* Disable UDF or IEX trap based on the content of parameter act */
91 +#define DISABLE_UDF_IEX_TRAP 0
92 +/* Enable UDF or IEX trap based on the content of parameter act */
93 +#define ENABLE_UDF_IEX_TRAP 1
94 +/* Get current status of UDF and IEX trap */
95 +#define GET_UDF_IEX_TRAP 2
96 +
97 +#endif /* _FP_UDF_IEX_CRTL_H */
98 diff --git a/arch/nds32/include/uapi/asm/sigcontext.h b/arch/nds32/include/uapi/asm/sigcontext.h
99 index 58afc416473e..b53634033e32 100644
100 --- a/arch/nds32/include/uapi/asm/sigcontext.h
101 +++ b/arch/nds32/include/uapi/asm/sigcontext.h
102 @@ -13,14 +13,24 @@ struct fpu_struct {
103 unsigned long long fd_regs[32];
104 unsigned long fpcsr;
105 /*
106 - * UDF_trap is used to recognize whether underflow trap is enabled
107 - * or not. When UDF_trap == 1, this process will be traped and then
108 - * get a SIGFPE signal when encountering an underflow exception.
109 - * UDF_trap is only modified through setfputrap syscall. Therefore,
110 - * UDF_trap needn't be saved or loaded to context in each context
111 - * switch.
112 + * When CONFIG_SUPPORT_DENORMAL_ARITHMETIC is defined, kernel prevents
113 + * hardware from treating the denormalized output as an underflow case
114 + * and rounding it to a normal number. Hence kernel enables the UDF and
115 + * IEX trap in the fpcsr register to step in the calculation.
116 + * However, the UDF and IEX trap enable bit in $fpcsr also lose
117 + * their use.
118 + *
119 + * UDF_IEX_trap replaces the feature of UDF and IEX trap enable bit in
120 + * $fpcsr to control the trap of underflow and inexact. The bit filed
121 + * of UDF_IEX_trap is the same as $fpcsr, 10th bit is used to enable UDF
122 + * exception trapping and 11th bit is used to enable IEX exception
123 + * trapping.
124 + *
125 + * UDF_IEX_trap is only modified through fp_udfiex_crtl syscall.
126 + * Therefore, UDF_IEX_trap needn't be saved and restored in each
127 + * context switch.
128 */
129 - unsigned long UDF_trap;
130 + unsigned long UDF_IEX_trap;
131 };
132
133 struct zol_struct {
134 diff --git a/arch/nds32/include/uapi/asm/udftrap.h b/arch/nds32/include/uapi/asm/udftrap.h
135 deleted file mode 100644
136 index 433f79d679c0..000000000000
137 --- a/arch/nds32/include/uapi/asm/udftrap.h
138 +++ /dev/null
139 @@ -1,13 +0,0 @@
140 -/* SPDX-License-Identifier: GPL-2.0 */
141 -/* Copyright (C) 2005-2018 Andes Technology Corporation */
142 -#ifndef _ASM_SETFPUTRAP
143 -#define _ASM_SETFPUTRAP
144 -
145 -/*
146 - * Options for setfputrap system call
147 - */
148 -#define DISABLE_UDFTRAP 0 /* disable underflow exception trap */
149 -#define ENABLE_UDFTRAP 1 /* enable undeflos exception trap */
150 -#define GET_UDFTRAP 2 /* only get undeflos exception trap status */
151 -
152 -#endif /* _ASM_CACHECTL */
153 diff --git a/arch/nds32/include/uapi/asm/unistd.h b/arch/nds32/include/uapi/asm/unistd.h
154 index 4ec8f543103f..6b9ff90e3ae5 100644
155 --- a/arch/nds32/include/uapi/asm/unistd.h
156 +++ b/arch/nds32/include/uapi/asm/unistd.h
157 @@ -11,6 +11,6 @@
158
159 /* Additional NDS32 specific syscalls. */
160 #define __NR_cacheflush (__NR_arch_specific_syscall)
161 -#define __NR_udftrap (__NR_arch_specific_syscall + 1)
162 +#define __NR_fp_udfiex_crtl (__NR_arch_specific_syscall + 1)
163 __SYSCALL(__NR_cacheflush, sys_cacheflush)
164 -__SYSCALL(__NR_udftrap, sys_udftrap)
165 +__SYSCALL(__NR_fp_udfiex_crtl, sys_fp_udfiex_crtl)
166 diff --git a/arch/nds32/kernel/fpu.c b/arch/nds32/kernel/fpu.c
167 index fddd40c7a16f..cf0b8760f261 100644
168 --- a/arch/nds32/kernel/fpu.c
169 +++ b/arch/nds32/kernel/fpu.c
170 @@ -14,7 +14,7 @@ const struct fpu_struct init_fpuregs = {
171 .fd_regs = {[0 ... 31] = sNAN64},
172 .fpcsr = FPCSR_INIT,
173 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
174 - .UDF_trap = 0
175 + .UDF_IEX_trap = 0
176 #endif
177 };
178
179 @@ -178,7 +178,7 @@ inline void do_fpu_context_switch(struct pt_regs *regs)
180 /* First time FPU user. */
181 load_fpu(&init_fpuregs);
182 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
183 - current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap;
184 + current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap;
185 #endif
186 set_used_math();
187 }
188 @@ -206,7 +206,7 @@ inline void handle_fpu_exception(struct pt_regs *regs)
189 unsigned int fpcsr;
190 int si_code = 0, si_signo = SIGFPE;
191 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
192 - unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT;
193 + unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT|FPCSR_mskIEXT;
194 #else
195 unsigned long redo_except = FPCSR_mskDNIT;
196 #endif
197 @@ -215,21 +215,18 @@ inline void handle_fpu_exception(struct pt_regs *regs)
198 fpcsr = current->thread.fpu.fpcsr;
199
200 if (fpcsr & redo_except) {
201 -#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
202 - if (fpcsr & FPCSR_mskUDFT)
203 - current->thread.fpu.fpcsr &= ~FPCSR_mskIEX;
204 -#endif
205 si_signo = do_fpuemu(regs, &current->thread.fpu);
206 fpcsr = current->thread.fpu.fpcsr;
207 - if (!si_signo)
208 + if (!si_signo) {
209 + current->thread.fpu.fpcsr &= ~(redo_except);
210 goto done;
211 + }
212 } else if (fpcsr & FPCSR_mskRIT) {
213 if (!user_mode(regs))
214 do_exit(SIGILL);
215 si_signo = SIGILL;
216 }
217
218 -
219 switch (si_signo) {
220 case SIGFPE:
221 fill_sigfpe_signo(fpcsr, &si_code);
222 diff --git a/arch/nds32/kernel/sys_nds32.c b/arch/nds32/kernel/sys_nds32.c
223 index 0835277636ce..cb2d1e219bb3 100644
224 --- a/arch/nds32/kernel/sys_nds32.c
225 +++ b/arch/nds32/kernel/sys_nds32.c
226 @@ -6,8 +6,8 @@
227
228 #include <asm/cachectl.h>
229 #include <asm/proc-fns.h>
230 -#include <asm/udftrap.h>
231 #include <asm/fpu.h>
232 +#include <asm/fp_udfiex_crtl.h>
233
234 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
235 unsigned long, prot, unsigned long, flags,
236 @@ -51,31 +51,33 @@ SYSCALL_DEFINE3(cacheflush, unsigned int, start, unsigned int, end, int, cache)
237 return 0;
238 }
239
240 -SYSCALL_DEFINE1(udftrap, int, option)
241 +SYSCALL_DEFINE2(fp_udfiex_crtl, unsigned int, cmd, unsigned int, act)
242 {
243 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
244 - int old_udftrap;
245 + int old_udf_iex;
246
247 if (!used_math()) {
248 load_fpu(&init_fpuregs);
249 - current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap;
250 + current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap;
251 set_used_math();
252 }
253
254 - old_udftrap = current->thread.fpu.UDF_trap;
255 - switch (option) {
256 - case DISABLE_UDFTRAP:
257 - current->thread.fpu.UDF_trap = 0;
258 + old_udf_iex = current->thread.fpu.UDF_IEX_trap;
259 + act &= (FPCSR_mskUDFE | FPCSR_mskIEXE);
260 +
261 + switch (cmd) {
262 + case DISABLE_UDF_IEX_TRAP:
263 + current->thread.fpu.UDF_IEX_trap &= ~act;
264 break;
265 - case ENABLE_UDFTRAP:
266 - current->thread.fpu.UDF_trap = FPCSR_mskUDFE;
267 + case ENABLE_UDF_IEX_TRAP:
268 + current->thread.fpu.UDF_IEX_trap |= act;
269 break;
270 - case GET_UDFTRAP:
271 + case GET_UDF_IEX_TRAP:
272 break;
273 default:
274 return -EINVAL;
275 }
276 - return old_udftrap;
277 + return old_udf_iex;
278 #else
279 return -ENOTSUPP;
280 #endif
281 --
282 2.20.1
283