cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

fpu.h (2675B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/*
      3 * Author: Huacai Chen <chenhuacai@loongson.cn>
      4 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
      5 */
      6#ifndef _ASM_FPU_H
      7#define _ASM_FPU_H
      8
      9#include <linux/sched.h>
     10#include <linux/sched/task_stack.h>
     11#include <linux/ptrace.h>
     12#include <linux/thread_info.h>
     13#include <linux/bitops.h>
     14
     15#include <asm/cpu.h>
     16#include <asm/cpu-features.h>
     17#include <asm/current.h>
     18#include <asm/loongarch.h>
     19#include <asm/processor.h>
     20#include <asm/ptrace.h>
     21
     22struct sigcontext;
     23
     24extern void _init_fpu(unsigned int);
     25extern void _save_fp(struct loongarch_fpu *);
     26extern void _restore_fp(struct loongarch_fpu *);
     27
     28/*
     29 * Mask the FCSR Cause bits according to the Enable bits, observing
     30 * that Unimplemented is always enabled.
     31 */
     32static inline unsigned long mask_fcsr_x(unsigned long fcsr)
     33{
     34	return fcsr & ((fcsr & FPU_CSR_ALL_E) <<
     35			(ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)));
     36}
     37
     38static inline int is_fp_enabled(void)
     39{
     40	return (csr_read32(LOONGARCH_CSR_EUEN) & CSR_EUEN_FPEN) ?
     41		1 : 0;
     42}
     43
     44#define enable_fpu()		set_csr_euen(CSR_EUEN_FPEN)
     45
     46#define disable_fpu()		clear_csr_euen(CSR_EUEN_FPEN)
     47
     48#define clear_fpu_owner()	clear_thread_flag(TIF_USEDFPU)
     49
     50static inline int is_fpu_owner(void)
     51{
     52	return test_thread_flag(TIF_USEDFPU);
     53}
     54
     55static inline void __own_fpu(void)
     56{
     57	enable_fpu();
     58	set_thread_flag(TIF_USEDFPU);
     59	KSTK_EUEN(current) |= CSR_EUEN_FPEN;
     60}
     61
     62static inline void own_fpu_inatomic(int restore)
     63{
     64	if (cpu_has_fpu && !is_fpu_owner()) {
     65		__own_fpu();
     66		if (restore)
     67			_restore_fp(&current->thread.fpu);
     68	}
     69}
     70
     71static inline void own_fpu(int restore)
     72{
     73	preempt_disable();
     74	own_fpu_inatomic(restore);
     75	preempt_enable();
     76}
     77
     78static inline void lose_fpu_inatomic(int save, struct task_struct *tsk)
     79{
     80	if (is_fpu_owner()) {
     81		if (save)
     82			_save_fp(&tsk->thread.fpu);
     83		disable_fpu();
     84		clear_tsk_thread_flag(tsk, TIF_USEDFPU);
     85	}
     86	KSTK_EUEN(tsk) &= ~(CSR_EUEN_FPEN | CSR_EUEN_LSXEN | CSR_EUEN_LASXEN);
     87}
     88
     89static inline void lose_fpu(int save)
     90{
     91	preempt_disable();
     92	lose_fpu_inatomic(save, current);
     93	preempt_enable();
     94}
     95
     96static inline void init_fpu(void)
     97{
     98	unsigned int fcsr = current->thread.fpu.fcsr;
     99
    100	__own_fpu();
    101	_init_fpu(fcsr);
    102	set_used_math();
    103}
    104
    105static inline void save_fp(struct task_struct *tsk)
    106{
    107	if (cpu_has_fpu)
    108		_save_fp(&tsk->thread.fpu);
    109}
    110
    111static inline void restore_fp(struct task_struct *tsk)
    112{
    113	if (cpu_has_fpu)
    114		_restore_fp(&tsk->thread.fpu);
    115}
    116
    117static inline union fpureg *get_fpu_regs(struct task_struct *tsk)
    118{
    119	if (tsk == current) {
    120		preempt_disable();
    121		if (is_fpu_owner())
    122			_save_fp(&current->thread.fpu);
    123		preempt_enable();
    124	}
    125
    126	return tsk->thread.fpu.fpr;
    127}
    128
    129#endif /* _ASM_FPU_H */