18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 1994 Linus Torvalds
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Pentium III FXSR, SSE support
68c2ecf20Sopenharmony_ci * General FPU state handling cleanups
78c2ecf20Sopenharmony_ci *	Gareth Hughes <gareth@valinux.com>, May 2000
88c2ecf20Sopenharmony_ci * x86-64 work by Andi Kleen 2002
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifndef _ASM_X86_FPU_API_H
128c2ecf20Sopenharmony_ci#define _ASM_X86_FPU_API_H
138c2ecf20Sopenharmony_ci#include <linux/bottom_half.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci * Use kernel_fpu_begin/end() if you intend to use FPU in kernel context. It
178c2ecf20Sopenharmony_ci * disables preemption so be careful if you intend to use it for long periods
188c2ecf20Sopenharmony_ci * of time.
198c2ecf20Sopenharmony_ci * If you intend to use the FPU in irq/softirq you need to check first with
208c2ecf20Sopenharmony_ci * irq_fpu_usable() if it is possible.
218c2ecf20Sopenharmony_ci */
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* Kernel FPU states to initialize in kernel_fpu_begin_mask() */
248c2ecf20Sopenharmony_ci#define KFPU_387	_BITUL(0)	/* 387 state will be initialized */
258c2ecf20Sopenharmony_ci#define KFPU_MXCSR	_BITUL(1)	/* MXCSR will be initialized */
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciextern void kernel_fpu_begin_mask(unsigned int kfpu_mask);
288c2ecf20Sopenharmony_ciextern void kernel_fpu_end(void);
298c2ecf20Sopenharmony_ciextern bool irq_fpu_usable(void);
308c2ecf20Sopenharmony_ciextern void fpregs_mark_activate(void);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/* Code that is unaware of kernel_fpu_begin_mask() can use this */
338c2ecf20Sopenharmony_cistatic inline void kernel_fpu_begin(void)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	kernel_fpu_begin_mask(KFPU_387 | KFPU_MXCSR);
368c2ecf20Sopenharmony_ci}
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/*
398c2ecf20Sopenharmony_ci * Use fpregs_lock() while editing CPU's FPU registers or fpu->state.
408c2ecf20Sopenharmony_ci * A context switch will (and softirq might) save CPU's FPU registers to
418c2ecf20Sopenharmony_ci * fpu->state and set TIF_NEED_FPU_LOAD leaving CPU's FPU registers in
428c2ecf20Sopenharmony_ci * a random state.
438c2ecf20Sopenharmony_ci */
448c2ecf20Sopenharmony_cistatic inline void fpregs_lock(void)
458c2ecf20Sopenharmony_ci{
468c2ecf20Sopenharmony_ci	preempt_disable();
478c2ecf20Sopenharmony_ci	local_bh_disable();
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic inline void fpregs_unlock(void)
518c2ecf20Sopenharmony_ci{
528c2ecf20Sopenharmony_ci	local_bh_enable();
538c2ecf20Sopenharmony_ci	preempt_enable();
548c2ecf20Sopenharmony_ci}
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_DEBUG_FPU
578c2ecf20Sopenharmony_ciextern void fpregs_assert_state_consistent(void);
588c2ecf20Sopenharmony_ci#else
598c2ecf20Sopenharmony_cistatic inline void fpregs_assert_state_consistent(void) { }
608c2ecf20Sopenharmony_ci#endif
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci/*
638c2ecf20Sopenharmony_ci * Load the task FPU state before returning to userspace.
648c2ecf20Sopenharmony_ci */
658c2ecf20Sopenharmony_ciextern void switch_fpu_return(void);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/*
688c2ecf20Sopenharmony_ci * Query the presence of one or more xfeatures. Works on any legacy CPU as well.
698c2ecf20Sopenharmony_ci *
708c2ecf20Sopenharmony_ci * If 'feature_name' is set then put a human-readable description of
718c2ecf20Sopenharmony_ci * the feature there as well - this can be used to print error (or success)
728c2ecf20Sopenharmony_ci * messages.
738c2ecf20Sopenharmony_ci */
748c2ecf20Sopenharmony_ciextern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/*
778c2ecf20Sopenharmony_ci * Tasks that are not using SVA have mm->pasid set to zero to note that they
788c2ecf20Sopenharmony_ci * will not have the valid bit set in MSR_IA32_PASID while they are running.
798c2ecf20Sopenharmony_ci */
808c2ecf20Sopenharmony_ci#define PASID_DISABLED	0
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic inline void update_pasid(void) { }
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci#endif /* _ASM_X86_FPU_API_H */
85