at master 5.7 kB view raw
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#include <asm/fpu/types.h> 16 17/* 18 * Use kernel_fpu_begin/end() if you intend to use FPU in kernel context. It 19 * disables preemption and softirq processing, so be careful if you intend to 20 * use it for long periods of time. Kernel-mode FPU cannot be used in all 21 * contexts -- see irq_fpu_usable() for details. 22 */ 23 24/* Kernel FPU states to initialize in kernel_fpu_begin_mask() */ 25#define KFPU_387 _BITUL(0) /* 387 state will be initialized */ 26#define KFPU_MXCSR _BITUL(1) /* MXCSR will be initialized */ 27 28extern void kernel_fpu_begin_mask(unsigned int kfpu_mask); 29extern void kernel_fpu_end(void); 30extern bool irq_fpu_usable(void); 31extern void fpregs_mark_activate(void); 32 33/* Code that is unaware of kernel_fpu_begin_mask() can use this */ 34static inline void kernel_fpu_begin(void) 35{ 36#ifdef CONFIG_X86_64 37 /* 38 * Any 64-bit code that uses 387 instructions must explicitly request 39 * KFPU_387. 40 */ 41 kernel_fpu_begin_mask(KFPU_MXCSR); 42#else 43 /* 44 * 32-bit kernel code may use 387 operations as well as SSE2, etc, 45 * as long as it checks that the CPU has the required capability. 46 */ 47 kernel_fpu_begin_mask(KFPU_387 | KFPU_MXCSR); 48#endif 49} 50 51/* 52 * Use fpregs_lock() while editing CPU's FPU registers or fpu->fpstate, or while 53 * using the FPU in kernel mode. A context switch will (and softirq might) save 54 * CPU's FPU registers to fpu->fpstate.regs and set TIF_NEED_FPU_LOAD leaving 55 * CPU's FPU registers in a random state. 56 * 57 * local_bh_disable() protects against both preemption and soft interrupts 58 * on !RT kernels. 59 * 60 * On RT kernels local_bh_disable() is not sufficient because it only 61 * serializes soft interrupt related sections via a local lock, but stays 62 * preemptible. Disabling preemption is the right choice here as bottom 63 * half processing is always in thread context on RT kernels so it 64 * implicitly prevents bottom half processing as well. 65 */ 66static inline void fpregs_lock(void) 67{ 68 if (!IS_ENABLED(CONFIG_PREEMPT_RT)) 69 local_bh_disable(); 70 else 71 preempt_disable(); 72} 73 74static inline void fpregs_unlock(void) 75{ 76 if (!IS_ENABLED(CONFIG_PREEMPT_RT)) 77 local_bh_enable(); 78 else 79 preempt_enable(); 80} 81 82/* 83 * FPU state gets lazily restored before returning to userspace. So when in the 84 * kernel, the valid FPU state may be kept in the buffer. This function will force 85 * restore all the fpu state to the registers early if needed, and lock them from 86 * being automatically saved/restored. Then FPU state can be modified safely in the 87 * registers, before unlocking with fpregs_unlock(). 88 */ 89void fpregs_lock_and_load(void); 90 91#ifdef CONFIG_X86_DEBUG_FPU 92extern void fpregs_assert_state_consistent(void); 93#else 94static inline void fpregs_assert_state_consistent(void) { } 95#endif 96 97/* 98 * Load the task FPU state before returning to userspace. 99 */ 100extern void switch_fpu_return(void); 101 102/* 103 * Query the presence of one or more xfeatures. Works on any legacy CPU as well. 104 * 105 * If 'feature_name' is set then put a human-readable description of 106 * the feature there as well - this can be used to print error (or success) 107 * messages. 108 */ 109extern int cpu_has_xfeatures(u64 xfeatures_mask, const char **feature_name); 110 111/* Trap handling */ 112extern int fpu__exception_code(struct fpu *fpu, int trap_nr); 113extern void fpu_sync_fpstate(struct fpu *fpu); 114extern void fpu_reset_from_exception_fixup(void); 115 116/* Boot, hotplug and resume */ 117extern void fpu__init_cpu(void); 118extern void fpu__init_system(void); 119extern void fpu__init_check_bugs(void); 120extern void fpu__resume_cpu(void); 121 122#ifdef CONFIG_MATH_EMULATION 123extern void fpstate_init_soft(struct swregs_state *soft); 124#else 125static inline void fpstate_init_soft(struct swregs_state *soft) {} 126#endif 127 128/* State tracking */ 129DECLARE_PER_CPU(bool, kernel_fpu_allowed); 130DECLARE_PER_CPU(struct fpu *, fpu_fpregs_owner_ctx); 131 132/* Process cleanup */ 133#ifdef CONFIG_X86_64 134extern void fpstate_free(struct fpu *fpu); 135#else 136static inline void fpstate_free(struct fpu *fpu) { } 137#endif 138 139/* fpstate-related functions which are exported to KVM */ 140extern void fpstate_clear_xstate_component(struct fpstate *fpstate, unsigned int xfeature); 141 142extern u64 xstate_get_guest_group_perm(void); 143 144extern void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr); 145 146 147/* KVM specific functions */ 148extern bool fpu_alloc_guest_fpstate(struct fpu_guest *gfpu); 149extern void fpu_free_guest_fpstate(struct fpu_guest *gfpu); 150extern int fpu_swap_kvm_fpstate(struct fpu_guest *gfpu, bool enter_guest); 151extern int fpu_enable_guest_xfd_features(struct fpu_guest *guest_fpu, u64 xfeatures); 152 153#ifdef CONFIG_X86_64 154extern void fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xfd); 155extern void fpu_sync_guest_vmexit_xfd_state(void); 156#else 157static inline void fpu_update_guest_xfd(struct fpu_guest *guest_fpu, u64 xfd) { } 158static inline void fpu_sync_guest_vmexit_xfd_state(void) { } 159#endif 160 161extern void fpu_copy_guest_fpstate_to_uabi(struct fpu_guest *gfpu, void *buf, 162 unsigned int size, u64 xfeatures, u32 pkru); 163extern int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf, u64 xcr0, u32 *vpkru); 164 165static inline void fpstate_set_confidential(struct fpu_guest *gfpu) 166{ 167 gfpu->fpstate->is_confidential = true; 168} 169 170static inline bool fpstate_is_confidential(struct fpu_guest *gfpu) 171{ 172 return gfpu->fpstate->is_confidential; 173} 174 175/* prctl */ 176extern long fpu_xstate_prctl(int option, unsigned long arg2); 177 178extern void fpu_idle_fpregs(void); 179 180#endif /* _ASM_X86_FPU_API_H */