nds32: nds32 FPU port
This patch set contains basic components for supporting the nds32 FPU, such as exception handlers and context switch for FPU registers. By default, the lazy FPU scheme is supported and the user can configure it via CONFIG_LZAY_FPU. Signed-off-by: Vincent Chen <vincentc@andestech.com> Acked-by: Greentime Hu <greentime@andestech.com> Signed-off-by: Greentime Hu <greentime@andestech.com>
This commit is contained in:

committed by
Greentime Hu

parent
4f014a41b4
commit
e46bf83c18
@@ -12,6 +12,7 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/ucontext.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/fpu.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/vdso.h>
|
||||
@@ -20,6 +21,60 @@ struct rt_sigframe {
|
||||
struct siginfo info;
|
||||
struct ucontext uc;
|
||||
};
|
||||
#if IS_ENABLED(CONFIG_FPU)
|
||||
static inline int restore_sigcontext_fpu(struct pt_regs *regs,
|
||||
struct sigcontext __user *sc)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
unsigned long used_math_flag;
|
||||
int ret = 0;
|
||||
|
||||
clear_used_math();
|
||||
__get_user_error(used_math_flag, &sc->used_math_flag, ret);
|
||||
|
||||
if (!used_math_flag)
|
||||
return 0;
|
||||
set_used_math();
|
||||
|
||||
#if IS_ENABLED(CONFIG_LAZY_FPU)
|
||||
preempt_disable();
|
||||
if (current == last_task_used_math) {
|
||||
last_task_used_math = NULL;
|
||||
disable_ptreg_fpu(regs);
|
||||
}
|
||||
preempt_enable();
|
||||
#else
|
||||
clear_fpu(regs);
|
||||
#endif
|
||||
|
||||
return __copy_from_user(&tsk->thread.fpu, &sc->fpu,
|
||||
sizeof(struct fpu_struct));
|
||||
}
|
||||
|
||||
static inline int setup_sigcontext_fpu(struct pt_regs *regs,
|
||||
struct sigcontext __user *sc)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
int ret = 0;
|
||||
|
||||
__put_user_error(used_math(), &sc->used_math_flag, ret);
|
||||
|
||||
if (!used_math())
|
||||
return ret;
|
||||
|
||||
preempt_disable();
|
||||
#if IS_ENABLED(CONFIG_LAZY_FPU)
|
||||
if (last_task_used_math == tsk)
|
||||
save_fpu(last_task_used_math);
|
||||
#else
|
||||
unlazy_fpu(tsk);
|
||||
#endif
|
||||
ret = __copy_to_user(&sc->fpu, &tsk->thread.fpu,
|
||||
sizeof(struct fpu_struct));
|
||||
preempt_enable();
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int restore_sigframe(struct pt_regs *regs,
|
||||
struct rt_sigframe __user * sf)
|
||||
@@ -69,7 +124,9 @@ static int restore_sigframe(struct pt_regs *regs,
|
||||
__get_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
|
||||
__get_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_FPU)
|
||||
err |= restore_sigcontext_fpu(regs, &sf->uc.uc_mcontext);
|
||||
#endif
|
||||
/*
|
||||
* Avoid sys_rt_sigreturn() restarting.
|
||||
*/
|
||||
@@ -153,6 +210,9 @@ setup_sigframe(struct rt_sigframe __user * sf, struct pt_regs *regs,
|
||||
__put_user_error(regs->le, &sf->uc.uc_mcontext.zol.nds32_le, err);
|
||||
__put_user_error(regs->lb, &sf->uc.uc_mcontext.zol.nds32_lb, err);
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_FPU)
|
||||
err |= setup_sigcontext_fpu(regs, &sf->uc.uc_mcontext);
|
||||
#endif
|
||||
|
||||
__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no,
|
||||
err);
|
||||
|
Reference in New Issue
Block a user