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_save(struct task_struct *task, 23 struct pt_regs *regs) 24 { 25 if ((regs->sstatus & SR_FS) == SR_FS_DIRTY) { 26 __fstate_save(task); 27 __fstate_clean(regs); 28 } 29 } 30 31 static inline void fstate_restore(struct task_struct *task, 32 struct pt_regs *regs) 33 { 34 if ((regs->sstatus & SR_FS) != SR_FS_OFF) { 35 __fstate_restore(task); 36 __fstate_clean(regs); 37 } 38 } 39 40 static inline void __switch_to_aux(struct task_struct *prev, 41 struct task_struct *next) 42 { 43 struct pt_regs *regs; 44 45 regs = task_pt_regs(prev); 46 if (unlikely(regs->sstatus & SR_SD)) 47 fstate_save(prev, regs); 48 fstate_restore(next, task_pt_regs(next)); 49 } 50 51 extern bool has_fpu; 52 #else 53 #define has_fpu false 54 #define fstate_save(task, regs) do { } while (0) 55 #define fstate_restore(task, regs) do { } while (0) 56 #define __switch_to_aux(__prev, __next) do { } while (0) 57 #endif 58 59 extern struct task_struct *__switch_to(struct task_struct *, 60 struct task_struct *); 61 62 #define switch_to(prev, next, last) \ 63 do { \ 64 struct task_struct *__prev = (prev); \ 65 struct task_struct *__next = (next); \ 66 if (has_fpu) \ 67 __switch_to_aux(__prev, __next); \ 68 ((last) = __switch_to(__prev, __next)); \ 69 } while (0) 70 71 #endif /* _ASM_RISCV_SWITCH_TO_H */ 72