Skip to content

Commit

Permalink
Merge tag 'nds32-for-linux-5.2-rc3' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/greentime/linux

Pull nds32 fixes from Greentime Hu:

 - fix warning for math-emu

 - fix nds32 fpu exception handling

 - fix nds32 fpu emulation implementation

* tag 'nds32-for-linux-5.2-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/greentime/linux:
  nds32: add new emulations for floating point instruction
  nds32: Avoid IEX status being incorrectly modified
  math-emu: Use statement expressions to fix Wshift-count-overflow warning
  • Loading branch information
torvalds committed Jun 3, 2019
2 parents 01e7a84 + 9322961 commit 30d1d92
Show file tree
Hide file tree
Showing 26 changed files with 464 additions and 66 deletions.
2 changes: 1 addition & 1 deletion arch/nds32/include/asm/bitfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -937,7 +937,7 @@
#define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT )
#define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT )
#define FPCSR_mskALL (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
#define FPCSR_mskALLE_NO_UDFE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskIEXE)
#define FPCSR_mskALLE_NO_UDF_IEXE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE)
#define FPCSR_mskALLE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
#define FPCSR_mskALLT (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)

Expand Down
2 changes: 1 addition & 1 deletion arch/nds32/include/asm/fpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extern int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu);
* enabled by default and kerenl will re-execute it by fpu emulator
* when getting underflow exception.
*/
#define FPCSR_INIT FPCSR_mskUDFE
#define FPCSR_INIT (FPCSR_mskUDFE | FPCSR_mskIEXE)
#else
#define FPCSR_INIT 0x0UL
#endif
Expand Down
12 changes: 12 additions & 0 deletions arch/nds32/include/asm/fpuemu.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ void fsubs(void *ft, void *fa, void *fb);
void fmuls(void *ft, void *fa, void *fb);
void fdivs(void *ft, void *fa, void *fb);
void fs2d(void *ft, void *fa);
void fs2si(void *ft, void *fa);
void fs2si_z(void *ft, void *fa);
void fs2ui(void *ft, void *fa);
void fs2ui_z(void *ft, void *fa);
void fsi2s(void *ft, void *fa);
void fui2s(void *ft, void *fa);
void fsqrts(void *ft, void *fa);
void fnegs(void *ft, void *fa);
int fcmps(void *ft, void *fa, void *fb, int cop);
Expand All @@ -26,6 +32,12 @@ void fmuld(void *ft, void *fa, void *fb);
void fdivd(void *ft, void *fa, void *fb);
void fsqrtd(void *ft, void *fa);
void fd2s(void *ft, void *fa);
void fd2si(void *ft, void *fa);
void fd2si_z(void *ft, void *fa);
void fd2ui(void *ft, void *fa);
void fd2ui_z(void *ft, void *fa);
void fsi2d(void *ft, void *fa);
void fui2d(void *ft, void *fa);
void fnegd(void *ft, void *fa);
int fcmpd(void *ft, void *fa, void *fb, int cop);

Expand Down
2 changes: 1 addition & 1 deletion arch/nds32/include/asm/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
asmlinkage long sys_cacheflush(unsigned long addr, unsigned long len, unsigned int op);
asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset, loff_t len);
asmlinkage long sys_rt_sigreturn_wrapper(void);
asmlinkage long sys_udftrap(int option);
asmlinkage long sys_fp_udfiex_crtl(int cmd, int act);

#include <asm-generic/syscalls.h>

Expand Down
16 changes: 16 additions & 0 deletions arch/nds32/include/uapi/asm/fp_udfiex_crtl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2005-2019 Andes Technology Corporation */
#ifndef _FP_UDF_IEX_CRTL_H
#define _FP_UDF_IEX_CRTL_H

/*
* The cmd list of sys_fp_udfiex_crtl()
*/
/* Disable UDF or IEX trap based on the content of parameter act */
#define DISABLE_UDF_IEX_TRAP 0
/* Enable UDF or IEX trap based on the content of parameter act */
#define ENABLE_UDF_IEX_TRAP 1
/* Get current status of UDF and IEX trap */
#define GET_UDF_IEX_TRAP 2

#endif /* _FP_UDF_IEX_CRTL_H */
24 changes: 17 additions & 7 deletions arch/nds32/include/uapi/asm/sigcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,24 @@ struct fpu_struct {
unsigned long long fd_regs[32];
unsigned long fpcsr;
/*
* UDF_trap is used to recognize whether underflow trap is enabled
* or not. When UDF_trap == 1, this process will be traped and then
* get a SIGFPE signal when encountering an underflow exception.
* UDF_trap is only modified through setfputrap syscall. Therefore,
* UDF_trap needn't be saved or loaded to context in each context
* switch.
* When CONFIG_SUPPORT_DENORMAL_ARITHMETIC is defined, kernel prevents
* hardware from treating the denormalized output as an underflow case
* and rounding it to a normal number. Hence kernel enables the UDF and
* IEX trap in the fpcsr register to step in the calculation.
* However, the UDF and IEX trap enable bit in $fpcsr also lose
* their use.
*
* UDF_IEX_trap replaces the feature of UDF and IEX trap enable bit in
* $fpcsr to control the trap of underflow and inexact. The bit filed
* of UDF_IEX_trap is the same as $fpcsr, 10th bit is used to enable UDF
* exception trapping and 11th bit is used to enable IEX exception
* trapping.
*
* UDF_IEX_trap is only modified through fp_udfiex_crtl syscall.
* Therefore, UDF_IEX_trap needn't be saved and restored in each
* context switch.
*/
unsigned long UDF_trap;
unsigned long UDF_IEX_trap;
};

struct zol_struct {
Expand Down
13 changes: 0 additions & 13 deletions arch/nds32/include/uapi/asm/udftrap.h

This file was deleted.

4 changes: 2 additions & 2 deletions arch/nds32/include/uapi/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@

/* Additional NDS32 specific syscalls. */
#define __NR_cacheflush (__NR_arch_specific_syscall)
#define __NR_udftrap (__NR_arch_specific_syscall + 1)
#define __NR_fp_udfiex_crtl (__NR_arch_specific_syscall + 1)
__SYSCALL(__NR_cacheflush, sys_cacheflush)
__SYSCALL(__NR_udftrap, sys_udftrap)
__SYSCALL(__NR_fp_udfiex_crtl, sys_fp_udfiex_crtl)
15 changes: 6 additions & 9 deletions arch/nds32/kernel/fpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const struct fpu_struct init_fpuregs = {
.fd_regs = {[0 ... 31] = sNAN64},
.fpcsr = FPCSR_INIT,
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
.UDF_trap = 0
.UDF_IEX_trap = 0
#endif
};

Expand Down Expand Up @@ -178,7 +178,7 @@ inline void do_fpu_context_switch(struct pt_regs *regs)
/* First time FPU user. */
load_fpu(&init_fpuregs);
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
current->thread.fpu.UDF_trap = init_fpuregs.UDF_trap;
current->thread.fpu.UDF_IEX_trap = init_fpuregs.UDF_IEX_trap;
#endif
set_used_math();
}
Expand Down Expand Up @@ -206,7 +206,7 @@ inline void handle_fpu_exception(struct pt_regs *regs)
unsigned int fpcsr;
int si_code = 0, si_signo = SIGFPE;
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT;
unsigned long redo_except = FPCSR_mskDNIT|FPCSR_mskUDFT|FPCSR_mskIEXT;
#else
unsigned long redo_except = FPCSR_mskDNIT;
#endif
Expand All @@ -215,21 +215,18 @@ inline void handle_fpu_exception(struct pt_regs *regs)
fpcsr = current->thread.fpu.fpcsr;

if (fpcsr & redo_except) {
#if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
if (fpcsr & FPCSR_mskUDFT)
current->thread.fpu.fpcsr &= ~FPCSR_mskIEX;
#endif
si_signo = do_fpuemu(regs, &current->thread.fpu);
fpcsr = current->thread.fpu.fpcsr;
if (!si_signo)
if (!si_signo) {
current->thread.fpu.fpcsr &= ~(redo_except);
goto done;
}
} else if (fpcsr & FPCSR_mskRIT) {
if (!user_mode(regs))
do_exit(SIGILL);
si_signo = SIGILL;
}


switch (si_signo) {
case SIGFPE:
fill_sigfpe_signo(fpcsr, &si_code);
Expand Down
26 changes: 14 additions & 12 deletions arch/nds32/kernel/sys_nds32.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion arch/nds32/math-emu/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@

obj-y := fpuemu.o \
fdivd.o fmuld.o fsubd.o faddd.o fs2d.o fsqrtd.o fcmpd.o fnegs.o \
fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o
fd2si.o fd2ui.o fd2siz.o fd2uiz.o fsi2d.o fui2d.o \
fdivs.o fmuls.o fsubs.o fadds.o fd2s.o fsqrts.o fcmps.o fnegd.o \
fs2si.o fs2ui.o fs2siz.o fs2uiz.o fsi2s.o fui2s.o
30 changes: 30 additions & 0 deletions arch/nds32/math-emu/fd2si.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2019 Andes Technology Corporation
#include <linux/uaccess.h>

#include <asm/sfp-machine.h>
#include <math-emu/soft-fp.h>
#include <math-emu/double.h>

void fd2si(void *ft, void *fa)
{
int r;

FP_DECL_D(A);
FP_DECL_EX;

FP_UNPACK_DP(A, fa);

if (A_c == FP_CLS_INF) {
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
__FPU_FPCSR |= FP_EX_INVALID;
} else if (A_c == FP_CLS_NAN) {
*(int *)ft = 0xffffffff;
__FPU_FPCSR |= FP_EX_INVALID;
} else {
FP_TO_INT_ROUND_D(r, A, 32, 1);
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
*(int *)ft = r;
}

}
30 changes: 30 additions & 0 deletions arch/nds32/math-emu/fd2siz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2019 Andes Technology Corporation
#include <linux/uaccess.h>

#include <asm/sfp-machine.h>
#include <math-emu/soft-fp.h>
#include <math-emu/double.h>

void fd2si_z(void *ft, void *fa)
{
int r;

FP_DECL_D(A);
FP_DECL_EX;

FP_UNPACK_DP(A, fa);

if (A_c == FP_CLS_INF) {
*(int *)ft = (A_s == 0) ? 0x7fffffff : 0x80000000;
__FPU_FPCSR |= FP_EX_INVALID;
} else if (A_c == FP_CLS_NAN) {
*(int *)ft = 0xffffffff;
__FPU_FPCSR |= FP_EX_INVALID;
} else {
FP_TO_INT_D(r, A, 32, 1);
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
*(int *)ft = r;
}

}
30 changes: 30 additions & 0 deletions arch/nds32/math-emu/fd2ui.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2019 Andes Technology Corporation
#include <linux/uaccess.h>

#include <asm/sfp-machine.h>
#include <math-emu/soft-fp.h>
#include <math-emu/double.h>

void fd2ui(void *ft, void *fa)
{
unsigned int r;

FP_DECL_D(A);
FP_DECL_EX;

FP_UNPACK_DP(A, fa);

if (A_c == FP_CLS_INF) {
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
__FPU_FPCSR |= FP_EX_INVALID;
} else if (A_c == FP_CLS_NAN) {
*(unsigned int *)ft = 0xffffffff;
__FPU_FPCSR |= FP_EX_INVALID;
} else {
FP_TO_INT_ROUND_D(r, A, 32, 0);
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
*(unsigned int *)ft = r;
}

}
30 changes: 30 additions & 0 deletions arch/nds32/math-emu/fd2uiz.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2005-2019 Andes Technology Corporation
#include <linux/uaccess.h>

#include <asm/sfp-machine.h>
#include <math-emu/soft-fp.h>
#include <math-emu/double.h>

void fd2ui_z(void *ft, void *fa)
{
unsigned int r;

FP_DECL_D(A);
FP_DECL_EX;

FP_UNPACK_DP(A, fa);

if (A_c == FP_CLS_INF) {
*(unsigned int *)ft = (A_s == 0) ? 0xffffffff : 0x00000000;
__FPU_FPCSR |= FP_EX_INVALID;
} else if (A_c == FP_CLS_NAN) {
*(unsigned int *)ft = 0xffffffff;
__FPU_FPCSR |= FP_EX_INVALID;
} else {
FP_TO_INT_D(r, A, 32, 0);
__FPU_FPCSR |= FP_CUR_EXCEPTIONS;
*(unsigned int *)ft = r;
}

}
Loading

0 comments on commit 30d1d92

Please sign in to comment.