]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - arch/nds32/include/asm/fpu.h
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-jammy-kernel.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 */