b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
| 2 | /* |
| 3 | * Copyright (C) 1994 Linus Torvalds |
| 4 | * |
| 5 | * Pentium III FXSR, SSE support |
| 6 | * General FPU state handling cleanups |
| 7 | * Gareth Hughes <gareth@valinux.com>, May 2000 |
| 8 | * x86-64 work by Andi Kleen 2002 |
| 9 | */ |
| 10 | |
| 11 | #ifndef _ASM_X86_FPU_API_H |
| 12 | #define _ASM_X86_FPU_API_H |
| 13 | #include <linux/bottom_half.h> |
| 14 | |
| 15 | /* |
| 16 | * Use kernel_fpu_begin/end() if you intend to use FPU in kernel context. It |
| 17 | * disables preemption so be careful if you intend to use it for long periods |
| 18 | * of time. |
| 19 | * If you intend to use the FPU in irq/softirq you need to check first with |
| 20 | * irq_fpu_usable() if it is possible. |
| 21 | */ |
| 22 | |
| 23 | /* Kernel FPU states to initialize in kernel_fpu_begin_mask() */ |
| 24 | #define KFPU_387 _BITUL(0) /* 387 state will be initialized */ |
| 25 | #define KFPU_MXCSR _BITUL(1) /* MXCSR will be initialized */ |
| 26 | |
| 27 | extern void kernel_fpu_begin_mask(unsigned int kfpu_mask); |
| 28 | extern void kernel_fpu_end(void); |
| 29 | extern bool irq_fpu_usable(void); |
| 30 | extern void fpregs_mark_activate(void); |
| 31 | |
| 32 | /* Code that is unaware of kernel_fpu_begin_mask() can use this */ |
| 33 | static inline void kernel_fpu_begin(void) |
| 34 | { |
| 35 | kernel_fpu_begin_mask(KFPU_387 | KFPU_MXCSR); |
| 36 | } |
| 37 | |
| 38 | /* |
| 39 | * Use fpregs_lock() while editing CPU's FPU registers or fpu->state. |
| 40 | * A context switch will (and softirq might) save CPU's FPU registers to |
| 41 | * fpu->state and set TIF_NEED_FPU_LOAD leaving CPU's FPU registers in |
| 42 | * a random state. |
| 43 | */ |
| 44 | static inline void fpregs_lock(void) |
| 45 | { |
| 46 | preempt_disable(); |
| 47 | local_bh_disable(); |
| 48 | } |
| 49 | |
| 50 | static inline void fpregs_unlock(void) |
| 51 | { |
| 52 | local_bh_enable(); |
| 53 | preempt_enable(); |
| 54 | } |
| 55 | |
| 56 | #ifdef CONFIG_X86_DEBUG_FPU |
| 57 | extern void fpregs_assert_state_consistent(void); |
| 58 | #else |
| 59 | static inline void fpregs_assert_state_consistent(void) { } |
| 60 | #endif |
| 61 | |
| 62 | /* |
| 63 | * Load the task FPU state before returning to userspace. |
| 64 | */ |
| 65 | extern void switch_fpu_return(void); |
| 66 | |
| 67 | /* |
| 68 | * Query the presence of one or more xfeatures. Works on any legacy CPU as well. |
| 69 | * |
| 70 | * If 'feature_name' is set then put a human-readable description of |
| 71 | * the feature there as well - this can be used to print error (or success) |
| 72 | * messages. |
| 73 | */ |
| 74 | extern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name); |
| 75 | |
| 76 | #endif /* _ASM_X86_FPU_API_H */ |