diff options
author | Vincent Chen <vincentc@andestech.com> | 2019-05-20 09:21:12 +0800 |
---|---|---|
committer | Greentime Hu <greentime@andestech.com> | 2019-05-31 15:23:26 +0800 |
commit | ed32949e0acb73e7bc054bb02e0453d4d561ceda (patch) | |
tree | f582241cdd3450e01fe6d1cf508a3e3a8211c675 /arch/nds32/kernel/sys_nds32.c | |
parent | 8183db10db6377ac58ad048a4c827425a614695c (diff) | |
download | linux-stable-ed32949e0acb73e7bc054bb02e0453d4d561ceda.tar.gz linux-stable-ed32949e0acb73e7bc054bb02e0453d4d561ceda.tar.bz2 linux-stable-ed32949e0acb73e7bc054bb02e0453d4d561ceda.zip |
nds32: Avoid IEX status being incorrectly modified
In order for kernel to capture each denormalized output, the UDF
trapping enable bit is always raised in $fpcsr. Because underflow case will
issue not an underflow exception but also an inexact exception, it causes
that the IEX, IEX cumulative exception, flag in $fpcsr to be raised in each
denormalized output handling. To make the emulation transparent to the
user, the emulator needs to clear the IEX flag in $fpcsr if the result is a
denormalized number. However, if the IEX flag has been raised before this
floating point emulation, this cleanup may be incorrect. To avoid the IEX
flags in $fpcsr be raised in each denormalized output handling, the IEX
trap shall be always enabled.
Signed-off-by: Vincent Chen <vincentc@andestech.com>
Acked-by: Greentime Hu <greentime@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
Diffstat (limited to 'arch/nds32/kernel/sys_nds32.c')
-rw-r--r-- | arch/nds32/kernel/sys_nds32.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/arch/nds32/kernel/sys_nds32.c b/arch/nds32/kernel/sys_nds32.c index 0835277636ce..cb2d1e219bb3 100644 --- a/arch/nds32/kernel/sys_nds32.c +++ b/arch/nds32/kernel/sys_nds32.c @@ -6,8 +6,8 @@ #include <asm/cachectl.h> #include <asm/proc-fns.h> -#include <asm/udftrap.h> #include <asm/fpu.h> +#include <asm/fp_udfiex_crtl.h> SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, @@ -51,31 +51,33 @@ SYSCALL_DEFINE3(cacheflush, unsigned int, start, unsigned int, end, int, cache) return 0; } -SYSCALL_DEFINE1(udftrap, int, option) +SYSCALL_DEFINE2(fp_udfiex_crtl, unsigned int, cmd, unsigned int, act) { #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC) - int old_udftrap; + int old_udf_iex; if (!used_math()) { load_fpu(&init_fpuregs); - current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap; + current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap; set_used_math(); } - old_udftrap = current->thread.fpu.UDF_trap; - switch (option) { - case DISABLE_UDFTRAP: - current->thread.fpu.UDF_trap = 0; + old_udf_iex = current->thread.fpu.UDF_IEX_trap; + act &= (FPCSR_mskUDFE | FPCSR_mskIEXE); + + switch (cmd) { + case DISABLE_UDF_IEX_TRAP: + current->thread.fpu.UDF_IEX_trap &= ~act; break; - case ENABLE_UDFTRAP: - current->thread.fpu.UDF_trap = FPCSR_mskUDFE; + case ENABLE_UDF_IEX_TRAP: + current->thread.fpu.UDF_IEX_trap |= act; break; - case GET_UDFTRAP: + case GET_UDF_IEX_TRAP: break; default: return -EINVAL; } - return old_udftrap; + return old_udf_iex; #else return -ENOTSUPP; #endif |