Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/kernel/fpu/legacy.h
26481 views
1
/* SPDX-License-Identifier: GPL-2.0 */
2
#ifndef __X86_KERNEL_FPU_LEGACY_H
3
#define __X86_KERNEL_FPU_LEGACY_H
4
5
#include <asm/fpu/types.h>
6
7
extern unsigned int mxcsr_feature_mask;
8
9
static inline void ldmxcsr(u32 mxcsr)
10
{
11
asm volatile("ldmxcsr %0" :: "m" (mxcsr));
12
}
13
14
/*
15
* Returns 0 on success or the trap number when the operation raises an
16
* exception.
17
*/
18
#define user_insn(insn, output, input...) \
19
({ \
20
int err; \
21
\
22
might_fault(); \
23
\
24
asm volatile(ASM_STAC "\n" \
25
"1: " #insn "\n" \
26
"2: " ASM_CLAC "\n" \
27
_ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FAULT_MCE_SAFE) \
28
: [err] "=a" (err), output \
29
: "0"(0), input); \
30
err; \
31
})
32
33
#define kernel_insn_err(insn, output, input...) \
34
({ \
35
int err; \
36
asm volatile("1:" #insn "\n\t" \
37
"2:\n" \
38
_ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_EFAULT_REG, %[err]) \
39
: [err] "=r" (err), output \
40
: "0"(0), input); \
41
err; \
42
})
43
44
#define kernel_insn(insn, output, input...) \
45
asm volatile("1:" #insn "\n\t" \
46
"2:\n" \
47
_ASM_EXTABLE_TYPE(1b, 2b, EX_TYPE_FPU_RESTORE) \
48
: output : input)
49
50
static inline int fnsave_to_user_sigframe(struct fregs_state __user *fx)
51
{
52
return user_insn(fnsave %[fx]; fwait, [fx] "=m" (*fx), "m" (*fx));
53
}
54
55
static inline int fxsave_to_user_sigframe(struct fxregs_state __user *fx)
56
{
57
if (IS_ENABLED(CONFIG_X86_32))
58
return user_insn(fxsave %[fx], [fx] "=m" (*fx), "m" (*fx));
59
else
60
return user_insn(fxsaveq %[fx], [fx] "=m" (*fx), "m" (*fx));
61
62
}
63
64
static inline void fxrstor(struct fxregs_state *fx)
65
{
66
if (IS_ENABLED(CONFIG_X86_32))
67
kernel_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
68
else
69
kernel_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
70
}
71
72
static inline int fxrstor_safe(struct fxregs_state *fx)
73
{
74
if (IS_ENABLED(CONFIG_X86_32))
75
return kernel_insn_err(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
76
else
77
return kernel_insn_err(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
78
}
79
80
static inline int fxrstor_from_user_sigframe(struct fxregs_state __user *fx)
81
{
82
if (IS_ENABLED(CONFIG_X86_32))
83
return user_insn(fxrstor %[fx], "=m" (*fx), [fx] "m" (*fx));
84
else
85
return user_insn(fxrstorq %[fx], "=m" (*fx), [fx] "m" (*fx));
86
}
87
88
static inline void frstor(struct fregs_state *fx)
89
{
90
kernel_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
91
}
92
93
static inline int frstor_safe(struct fregs_state *fx)
94
{
95
return kernel_insn_err(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
96
}
97
98
static inline int frstor_from_user_sigframe(struct fregs_state __user *fx)
99
{
100
return user_insn(frstor %[fx], "=m" (*fx), [fx] "m" (*fx));
101
}
102
103
static inline void fxsave(struct fxregs_state *fx)
104
{
105
if (IS_ENABLED(CONFIG_X86_32))
106
asm volatile( "fxsave %[fx]" : [fx] "=m" (*fx));
107
else
108
asm volatile("fxsaveq %[fx]" : [fx] "=m" (*fx));
109
}
110
111
#endif
112
113