diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2020-01-18 00:04:03 +0100 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2020-01-18 01:53:44 +0100 |
commit | f45ba2bd6da0dc8000aa7ea7a3858fb51608f766 (patch) | |
tree | 3be8113cb45459531bc5ffee5bbbb1de38d5d234 /arch/arc/kernel | |
parent | ARC: fpu: declutter code, move bits out into fpu.h (diff) | |
download | linux-f45ba2bd6da0dc8000aa7ea7a3858fb51608f766.tar.xz linux-f45ba2bd6da0dc8000aa7ea7a3858fb51608f766.zip |
ARCv2: fpu: preserve userspace fpu state
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc/kernel')
-rw-r--r-- | arch/arc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arc/kernel/fpu.c | 27 | ||||
-rw-r--r-- | arch/arc/kernel/process.c | 6 |
3 files changed, 34 insertions, 1 deletions
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index e784f5396dda..75539670431a 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile @@ -23,7 +23,9 @@ obj-$(CONFIG_PERF_EVENTS) += perf_event.o obj-$(CONFIG_JUMP_LABEL) += jump_label.o obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o +ifdef CONFIG_ISA_ARCOMPACT CFLAGS_fpu.o += -mdpfp +endif ifdef CONFIG_ARC_DW2_UNWIND CFLAGS_ctx_sw.o += -fno-omit-frame-pointer diff --git a/arch/arc/kernel/fpu.c b/arch/arc/kernel/fpu.c index 7a3b56ce56bb..c67c0f0f5f77 100644 --- a/arch/arc/kernel/fpu.c +++ b/arch/arc/kernel/fpu.c @@ -8,6 +8,8 @@ #include <linux/sched.h> #include <asm/fpu.h> +#ifdef CONFIG_ISA_ARCOMPACT + /* * To save/restore FPU regs, simplest scheme would use LR/SR insns. * However since SR serializes the pipeline, an alternate "hack" can be used @@ -50,3 +52,28 @@ void fpu_save_restore(struct task_struct *prev, struct task_struct *next) : "r" (zero), "r" (*(readfrom + 3)), "r" (*(readfrom + 2)) ); } + +#else + +void fpu_init_task(struct pt_regs *regs) +{ + /* default rounding mode */ + write_aux_reg(ARC_REG_FPU_CTRL, 0x100); + + /* set "Write enable" to allow explicit write to exception flags */ + write_aux_reg(ARC_REG_FPU_STATUS, 0x80000000); +} + +void fpu_save_restore(struct task_struct *prev, struct task_struct *next) +{ + struct arc_fpu *save = &prev->thread.fpu; + struct arc_fpu *restore = &next->thread.fpu; + + save->ctrl = read_aux_reg(ARC_REG_FPU_CTRL); + save->status = read_aux_reg(ARC_REG_FPU_STATUS); + + write_aux_reg(ARC_REG_FPU_CTRL, restore->ctrl); + write_aux_reg(ARC_REG_FPU_STATUS, restore->status); +} + +#endif diff --git a/arch/arc/kernel/process.c b/arch/arc/kernel/process.c index bfd4cbe74aa3..315528f04bc1 100644 --- a/arch/arc/kernel/process.c +++ b/arch/arc/kernel/process.c @@ -20,6 +20,8 @@ #include <linux/elf.h> #include <linux/tick.h> +#include <asm/fpu.h> + SYSCALL_DEFINE1(arc_settls, void *, user_tls_data_ptr) { task_thread_info(current)->thr_ptr = (unsigned int)user_tls_data_ptr; @@ -263,7 +265,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp, /* * Do necessary setup to start up a new user task */ -void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp) +void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp) { regs->sp = usp; regs->ret = pc; @@ -279,6 +281,8 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp) regs->eflags = 0; #endif + fpu_init_task(regs); + /* bogus seed values for debugging */ regs->lp_start = 0x10; regs->lp_end = 0x80; |