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 */ 78