x86/fpu/xstate: Clean up setup_xstate_comp() call
[firefly-linux-kernel-4.4.55.git] / arch / x86 / include / asm / fpu / xstate.h
1 #ifndef __ASM_X86_XSAVE_H
2 #define __ASM_X86_XSAVE_H
3
4 #include <linux/types.h>
5 #include <asm/processor.h>
6 #include <linux/uaccess.h>
7
8 /* Bit 63 of XCR0 is reserved for future expansion */
9 #define XSTATE_EXTEND_MASK      (~(XSTATE_FPSSE | (1ULL << 63)))
10
11 #define XSTATE_CPUID            0x0000000d
12
13 #define FXSAVE_SIZE     512
14
15 #define XSAVE_HDR_SIZE      64
16 #define XSAVE_HDR_OFFSET    FXSAVE_SIZE
17
18 #define XSAVE_YMM_SIZE      256
19 #define XSAVE_YMM_OFFSET    (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET)
20
21 /* Supported features which support lazy state saving */
22 #define XSTATE_LAZY     (XSTATE_FP | XSTATE_SSE | XSTATE_YMM                  \
23                         | XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM)
24
25 /* Supported features which require eager state saving */
26 #define XSTATE_EAGER    (XSTATE_BNDREGS | XSTATE_BNDCSR)
27
28 /* All currently supported features */
29 #define XCNTXT_MASK     (XSTATE_LAZY | XSTATE_EAGER)
30
31 #ifdef CONFIG_X86_64
32 #define REX_PREFIX      "0x48, "
33 #else
34 #define REX_PREFIX
35 #endif
36
37 extern unsigned int xstate_size;
38 extern u64 xfeatures_mask;
39 extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
40
41 extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
42
43 /* These macros all use (%edi)/(%rdi) as the single memory argument. */
44 #define XSAVE           ".byte " REX_PREFIX "0x0f,0xae,0x27"
45 #define XSAVEOPT        ".byte " REX_PREFIX "0x0f,0xae,0x37"
46 #define XSAVES          ".byte " REX_PREFIX "0x0f,0xc7,0x2f"
47 #define XRSTOR          ".byte " REX_PREFIX "0x0f,0xae,0x2f"
48 #define XRSTORS         ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
49
50 #define xstate_fault    ".section .fixup,\"ax\"\n"      \
51                         "3:  movl $-1,%[err]\n"         \
52                         "    jmp  2b\n"                 \
53                         ".previous\n"                   \
54                         _ASM_EXTABLE(1b, 3b)            \
55                         : [err] "=r" (err)
56
57 /*
58  * This function is called only during boot time when x86 caps are not set
59  * up and alternative can not be used yet.
60  */
61 static inline int copy_xregs_to_kernel_booting(struct xregs_state *fx)
62 {
63         u64 mask = -1;
64         u32 lmask = mask;
65         u32 hmask = mask >> 32;
66         int err = 0;
67
68         WARN_ON(system_state != SYSTEM_BOOTING);
69
70         if (boot_cpu_has(X86_FEATURE_XSAVES))
71                 asm volatile("1:"XSAVES"\n\t"
72                         "2:\n\t"
73                              xstate_fault
74                         : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
75                         :   "memory");
76         else
77                 asm volatile("1:"XSAVE"\n\t"
78                         "2:\n\t"
79                              xstate_fault
80                         : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
81                         :   "memory");
82         return err;
83 }
84
85 /*
86  * This function is called only during boot time when x86 caps are not set
87  * up and alternative can not be used yet.
88  */
89 static inline int copy_kernel_to_xregs_booting(struct xregs_state *fx, u64 mask)
90 {
91         u32 lmask = mask;
92         u32 hmask = mask >> 32;
93         int err = 0;
94
95         WARN_ON(system_state != SYSTEM_BOOTING);
96
97         if (boot_cpu_has(X86_FEATURE_XSAVES))
98                 asm volatile("1:"XRSTORS"\n\t"
99                         "2:\n\t"
100                              xstate_fault
101                         : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
102                         :   "memory");
103         else
104                 asm volatile("1:"XRSTOR"\n\t"
105                         "2:\n\t"
106                              xstate_fault
107                         : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
108                         :   "memory");
109         return err;
110 }
111
112 /*
113  * Save processor xstate to xsave area.
114  */
115 static inline int copy_xregs_to_kernel(struct xregs_state *fx)
116 {
117         u64 mask = -1;
118         u32 lmask = mask;
119         u32 hmask = mask >> 32;
120         int err = 0;
121
122         WARN_ON(!alternatives_patched);
123
124         /*
125          * If xsaves is enabled, xsaves replaces xsaveopt because
126          * it supports compact format and supervisor states in addition to
127          * modified optimization in xsaveopt.
128          *
129          * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave
130          * because xsaveopt supports modified optimization which is not
131          * supported by xsave.
132          *
133          * If none of xsaves and xsaveopt is enabled, use xsave.
134          */
135         alternative_input_2(
136                 "1:"XSAVE,
137                 XSAVEOPT,
138                 X86_FEATURE_XSAVEOPT,
139                 XSAVES,
140                 X86_FEATURE_XSAVES,
141                 [fx] "D" (fx), "a" (lmask), "d" (hmask) :
142                 "memory");
143         asm volatile("2:\n\t"
144                      xstate_fault
145                      : "0" (0)
146                      : "memory");
147
148         return err;
149 }
150
151 /*
152  * Restore processor xstate from xsave area.
153  */
154 static inline int copy_kernel_to_xregs(struct xregs_state *fx, u64 mask)
155 {
156         int err = 0;
157         u32 lmask = mask;
158         u32 hmask = mask >> 32;
159
160         /*
161          * Use xrstors to restore context if it is enabled. xrstors supports
162          * compacted format of xsave area which is not supported by xrstor.
163          */
164         alternative_input(
165                 "1: " XRSTOR,
166                 XRSTORS,
167                 X86_FEATURE_XSAVES,
168                 "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
169                 : "memory");
170
171         asm volatile("2:\n"
172                      xstate_fault
173                      : "0" (0)
174                      : "memory");
175
176         return err;
177 }
178
179 /*
180  * Save xstate to user space xsave area.
181  *
182  * We don't use modified optimization because xrstor/xrstors might track
183  * a different application.
184  *
185  * We don't use compacted format xsave area for
186  * backward compatibility for old applications which don't understand
187  * compacted format of xsave area.
188  */
189 static inline int copy_xregs_to_user(struct xregs_state __user *buf)
190 {
191         int err;
192
193         /*
194          * Clear the xsave header first, so that reserved fields are
195          * initialized to zero.
196          */
197         err = __clear_user(&buf->header, sizeof(buf->header));
198         if (unlikely(err))
199                 return -EFAULT;
200
201         __asm__ __volatile__(ASM_STAC "\n"
202                              "1:"XSAVE"\n"
203                              "2: " ASM_CLAC "\n"
204                              xstate_fault
205                              : "D" (buf), "a" (-1), "d" (-1), "0" (0)
206                              : "memory");
207         return err;
208 }
209
210 /*
211  * Restore xstate from user space xsave area.
212  */
213 static inline int copy_user_to_xregs(struct xregs_state __user *buf, u64 mask)
214 {
215         int err = 0;
216         struct xregs_state *xstate = ((__force struct xregs_state *)buf);
217         u32 lmask = mask;
218         u32 hmask = mask >> 32;
219
220         __asm__ __volatile__(ASM_STAC "\n"
221                              "1:"XRSTOR"\n"
222                              "2: " ASM_CLAC "\n"
223                              xstate_fault
224                              : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0)
225                              : "memory");       /* memory required? */
226         return err;
227 }
228
229 void *get_xsave_addr(struct xregs_state *xsave, int xstate);
230
231 #endif