linux/arch/riscv/include/asm/switch_to.h
<<
>>
Prefs
   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 <linux/jump_label.h>
  10#include <linux/sched/task_stack.h>
  11#include <asm/processor.h>
  12#include <asm/ptrace.h>
  13#include <asm/csr.h>
  14
  15#ifdef CONFIG_FPU
  16extern void __fstate_save(struct task_struct *save_to);
  17extern void __fstate_restore(struct task_struct *restore_from);
  18
  19static inline void __fstate_clean(struct pt_regs *regs)
  20{
  21        regs->status = (regs->status & ~SR_FS) | SR_FS_CLEAN;
  22}
  23
  24static inline void fstate_off(struct task_struct *task,
  25                              struct pt_regs *regs)
  26{
  27        regs->status = (regs->status & ~SR_FS) | SR_FS_OFF;
  28}
  29
  30static inline void fstate_save(struct task_struct *task,
  31                               struct pt_regs *regs)
  32{
  33        if ((regs->status & SR_FS) == SR_FS_DIRTY) {
  34                __fstate_save(task);
  35                __fstate_clean(regs);
  36        }
  37}
  38
  39static inline void fstate_restore(struct task_struct *task,
  40                                  struct pt_regs *regs)
  41{
  42        if ((regs->status & SR_FS) != SR_FS_OFF) {
  43                __fstate_restore(task);
  44                __fstate_clean(regs);
  45        }
  46}
  47
  48static inline void __switch_to_aux(struct task_struct *prev,
  49                                   struct task_struct *next)
  50{
  51        struct pt_regs *regs;
  52
  53        regs = task_pt_regs(prev);
  54        if (unlikely(regs->status & SR_SD))
  55                fstate_save(prev, regs);
  56        fstate_restore(next, task_pt_regs(next));
  57}
  58
  59extern struct static_key_false cpu_hwcap_fpu;
  60static __always_inline bool has_fpu(void)
  61{
  62        return static_branch_likely(&cpu_hwcap_fpu);
  63}
  64#else
  65static __always_inline bool has_fpu(void) { return false; }
  66#define fstate_save(task, regs) do { } while (0)
  67#define fstate_restore(task, regs) do { } while (0)
  68#define __switch_to_aux(__prev, __next) do { } while (0)
  69#endif
  70
  71extern struct task_struct *__switch_to(struct task_struct *,
  72                                       struct task_struct *);
  73
  74#define switch_to(prev, next, last)                     \
  75do {                                                    \
  76        struct task_struct *__prev = (prev);            \
  77        struct task_struct *__next = (next);            \
  78        if (has_fpu())                                  \
  79                __switch_to_aux(__prev, __next);        \
  80        ((last) = __switch_to(__prev, __next));         \
  81} while (0)
  82
  83#endif /* _ASM_RISCV_SWITCH_TO_H */
  84