riscv: Correct the initialized flow of FP register
[sfrench/cifs-2.6.git] / arch / riscv / include / asm / switch_to.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2012 Regents of the University of California
4  */
5
6 #ifndef _ASM_RISCV_SWITCH_TO_H
7 #define _ASM_RISCV_SWITCH_TO_H
8
9 #include <asm/processor.h>
10 #include <asm/ptrace.h>
11 #include <asm/csr.h>
12
13 #ifdef CONFIG_FPU
14 extern void __fstate_save(struct task_struct *save_to);
15 extern void __fstate_restore(struct task_struct *restore_from);
16
17 static inline void __fstate_clean(struct pt_regs *regs)
18 {
19         regs->sstatus |= (regs->sstatus & ~(SR_FS)) | SR_FS_CLEAN;
20 }
21
22 static inline void fstate_off(struct task_struct *task,
23                               struct pt_regs *regs)
24 {
25         regs->sstatus = (regs->sstatus & ~SR_FS) | SR_FS_OFF;
26 }
27
28 static inline void fstate_save(struct task_struct *task,
29                                struct pt_regs *regs)
30 {
31         if ((regs->sstatus & SR_FS) == SR_FS_DIRTY) {
32                 __fstate_save(task);
33                 __fstate_clean(regs);
34         }
35 }
36
37 static inline void fstate_restore(struct task_struct *task,
38                                   struct pt_regs *regs)
39 {
40         if ((regs->sstatus & SR_FS) != SR_FS_OFF) {
41                 __fstate_restore(task);
42                 __fstate_clean(regs);
43         }
44 }
45
46 static inline void __switch_to_aux(struct task_struct *prev,
47                                    struct task_struct *next)
48 {
49         struct pt_regs *regs;
50
51         regs = task_pt_regs(prev);
52         if (unlikely(regs->sstatus & SR_SD))
53                 fstate_save(prev, regs);
54         fstate_restore(next, task_pt_regs(next));
55 }
56
57 extern bool has_fpu;
58 #else
59 #define has_fpu false
60 #define fstate_save(task, regs) do { } while (0)
61 #define fstate_restore(task, regs) do { } while (0)
62 #define __switch_to_aux(__prev, __next) do { } while (0)
63 #endif
64
65 extern struct task_struct *__switch_to(struct task_struct *,
66                                        struct task_struct *);
67
68 #define switch_to(prev, next, last)                     \
69 do {                                                    \
70         struct task_struct *__prev = (prev);            \
71         struct task_struct *__next = (next);            \
72         if (has_fpu)                                    \
73                 __switch_to_aux(__prev, __next);        \
74         ((last) = __switch_to(__prev, __next));         \
75 } while (0)
76
77 #endif /* _ASM_RISCV_SWITCH_TO_H */