Merge tag 'trace-v5.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[sfrench/cifs-2.6.git] / arch / nds32 / include / asm / fpu.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (C) 2005-2018 Andes Technology Corporation */
3
4 #ifndef __ASM_NDS32_FPU_H
5 #define __ASM_NDS32_FPU_H
6
7 #if IS_ENABLED(CONFIG_FPU)
8 #ifndef __ASSEMBLY__
9 #include <linux/sched/task_stack.h>
10 #include <linux/preempt.h>
11 #include <asm/ptrace.h>
12
13 extern bool has_fpu;
14
15 extern void save_fpu(struct task_struct *__tsk);
16 extern void load_fpu(const struct fpu_struct *fpregs);
17 extern bool do_fpu_exception(unsigned int subtype, struct pt_regs *regs);
18 extern int do_fpuemu(struct pt_regs *regs, struct fpu_struct *fpu);
19
20 #define test_tsk_fpu(regs)      (regs->fucop_ctl & FUCOP_CTL_mskCP0EN)
21
22 /*
23  * Initially load the FPU with signalling NANS.  This bit pattern
24  * has the property that no matter whether considered as single or as
25  * double precision, it still represents a signalling NAN.
26  */
27
28 #define sNAN64    0xFFFFFFFFFFFFFFFFULL
29 #define sNAN32    0xFFFFFFFFUL
30
31 #if IS_ENABLED(CONFIG_SUPPORT_DENORMAL_ARITHMETIC)
32 /*
33  * Denormalized number is unsupported by nds32 FPU. Hence the operation
34  * is treated as underflow cases when the final result is a denormalized
35  * number. To enhance precision, underflow exception trap should be
36  * enabled by default and kerenl will re-execute it by fpu emulator
37  * when getting underflow exception.
38  */
39 #define FPCSR_INIT  (FPCSR_mskUDFE | FPCSR_mskIEXE)
40 #else
41 #define FPCSR_INIT  0x0UL
42 #endif
43
44 extern const struct fpu_struct init_fpuregs;
45
46 static inline void disable_ptreg_fpu(struct pt_regs *regs)
47 {
48         regs->fucop_ctl &= ~FUCOP_CTL_mskCP0EN;
49 }
50
51 static inline void enable_ptreg_fpu(struct pt_regs *regs)
52 {
53         regs->fucop_ctl |= FUCOP_CTL_mskCP0EN;
54 }
55
56 static inline void enable_fpu(void)
57 {
58         unsigned long fucop_ctl;
59
60         fucop_ctl = __nds32__mfsr(NDS32_SR_FUCOP_CTL) | FUCOP_CTL_mskCP0EN;
61         __nds32__mtsr(fucop_ctl, NDS32_SR_FUCOP_CTL);
62         __nds32__isb();
63 }
64
65 static inline void disable_fpu(void)
66 {
67         unsigned long fucop_ctl;
68
69         fucop_ctl = __nds32__mfsr(NDS32_SR_FUCOP_CTL) & ~FUCOP_CTL_mskCP0EN;
70         __nds32__mtsr(fucop_ctl, NDS32_SR_FUCOP_CTL);
71         __nds32__isb();
72 }
73
74 static inline void lose_fpu(void)
75 {
76         preempt_disable();
77 #if IS_ENABLED(CONFIG_LAZY_FPU)
78         if (last_task_used_math == current) {
79                 last_task_used_math = NULL;
80 #else
81         if (test_tsk_fpu(task_pt_regs(current))) {
82 #endif
83                 save_fpu(current);
84         }
85         disable_ptreg_fpu(task_pt_regs(current));
86         preempt_enable();
87 }
88
89 static inline void own_fpu(void)
90 {
91         preempt_disable();
92 #if IS_ENABLED(CONFIG_LAZY_FPU)
93         if (last_task_used_math != current) {
94                 if (last_task_used_math != NULL)
95                         save_fpu(last_task_used_math);
96                 load_fpu(&current->thread.fpu);
97                 last_task_used_math = current;
98         }
99 #else
100         if (!test_tsk_fpu(task_pt_regs(current))) {
101                 load_fpu(&current->thread.fpu);
102         }
103 #endif
104         enable_ptreg_fpu(task_pt_regs(current));
105         preempt_enable();
106 }
107
108 #if !IS_ENABLED(CONFIG_LAZY_FPU)
109 static inline void unlazy_fpu(struct task_struct *tsk)
110 {
111         preempt_disable();
112         if (test_tsk_fpu(task_pt_regs(tsk)))
113                 save_fpu(tsk);
114         preempt_enable();
115 }
116 #endif /* !CONFIG_LAZY_FPU */
117 static inline void clear_fpu(struct pt_regs *regs)
118 {
119         preempt_disable();
120         if (test_tsk_fpu(regs))
121                 disable_ptreg_fpu(regs);
122         preempt_enable();
123 }
124 #endif /* CONFIG_FPU */
125 #endif /* __ASSEMBLY__ */
126 #endif /* __ASM_NDS32_FPU_H */