x86/xsaves: Use xsaves/xrstors for context switch
[deliverable/linux.git] / arch / x86 / include / asm / xsave.h
CommitLineData
dc1e35c6
SS
1#ifndef __ASM_X86_XSAVE_H
2#define __ASM_X86_XSAVE_H
3
6152e4b1 4#include <linux/types.h>
dc1e35c6 5#include <asm/processor.h>
dc1e35c6 6
ee813d53 7#define XSTATE_CPUID 0x0000000d
dc1e35c6 8
c2bc11f1
FY
9#define XSTATE_FP 0x1
10#define XSTATE_SSE 0x2
11#define XSTATE_YMM 0x4
12#define XSTATE_BNDREGS 0x8
13#define XSTATE_BNDCSR 0x10
14#define XSTATE_OPMASK 0x20
15#define XSTATE_ZMM_Hi256 0x40
16#define XSTATE_Hi16_ZMM 0x80
dc1e35c6
SS
17
18#define XSTATE_FPSSE (XSTATE_FP | XSTATE_SSE)
56c103ec
LJ
19/* Bit 63 of XCR0 is reserved for future expansion */
20#define XSTATE_EXTEND_MASK (~(XSTATE_FPSSE | (1ULL << 63)))
dc1e35c6
SS
21
22#define FXSAVE_SIZE 512
23
2d5b5a66
SY
24#define XSAVE_HDR_SIZE 64
25#define XSAVE_HDR_OFFSET FXSAVE_SIZE
26
27#define XSAVE_YMM_SIZE 256
28#define XSAVE_YMM_OFFSET (XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET)
5ee481da 29
e7d820a5 30/* Supported features which support lazy state saving */
c2bc11f1
FY
31#define XSTATE_LAZY (XSTATE_FP | XSTATE_SSE | XSTATE_YMM \
32 | XSTATE_OPMASK | XSTATE_ZMM_Hi256 | XSTATE_Hi16_ZMM)
e7d820a5
QR
33
34/* Supported features which require eager state saving */
35#define XSTATE_EAGER (XSTATE_BNDREGS | XSTATE_BNDCSR)
36
37/* All currently supported features */
38#define XCNTXT_MASK (XSTATE_LAZY | XSTATE_EAGER)
dc1e35c6 39
b359e8a4
SS
40#ifdef CONFIG_X86_64
41#define REX_PREFIX "0x48, "
42#else
43#define REX_PREFIX
44#endif
45
6152e4b1
PA
46extern unsigned int xstate_size;
47extern u64 pcntxt_mask;
5b3efd50 48extern u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
304bceda 49extern struct xsave_struct *init_xstate_buf;
dc1e35c6 50
dc1e35c6 51extern void xsave_init(void);
5b3efd50 52extern void update_regset_xstate_info(unsigned int size, u64 xstate_mask);
b359e8a4
SS
53extern int init_fpu(struct task_struct *child);
54
200b08a9
FY
55#define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27"
56#define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37"
57#define XSAVES ".byte " REX_PREFIX "0x0f,0xc7,0x2f"
58#define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f"
59#define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f"
60
b84e7055
FY
61#define xstate_fault ".section .fixup,\"ax\"\n" \
62 "3: movl $-1,%[err]\n" \
63 " jmp 2b\n" \
64 ".previous\n" \
65 _ASM_EXTABLE(1b, 3b) \
66 : [err] "=r" (err)
67
f31a9f7c
FY
68/*
69 * Save processor xstate to xsave area.
70 */
71static inline int xsave_state(struct xsave_struct *fx, u64 mask)
72{
73 u32 lmask = mask;
74 u32 hmask = mask >> 32;
75 int err = 0;
76
77 /*
78 * If xsaves is enabled, xsaves replaces xsaveopt because
79 * it supports compact format and supervisor states in addition to
80 * modified optimization in xsaveopt.
81 *
82 * Otherwise, if xsaveopt is enabled, xsaveopt replaces xsave
83 * because xsaveopt supports modified optimization which is not
84 * supported by xsave.
85 *
86 * If none of xsaves and xsaveopt is enabled, use xsave.
87 */
88 alternative_input_2(
89 "1:"XSAVE,
90 "1:"XSAVEOPT,
91 X86_FEATURE_XSAVEOPT,
92 "1:"XSAVES,
93 X86_FEATURE_XSAVES,
94 [fx] "D" (fx), "a" (lmask), "d" (hmask) :
95 "memory");
96 asm volatile("2:\n\t"
97 xstate_fault
98 : "0" (0)
99 : "memory");
100
101 return err;
102}
103
104/*
105 * Restore processor xstate from xsave area.
106 */
107static inline int xrstor_state(struct xsave_struct *fx, u64 mask)
108{
109 int err = 0;
110 u32 lmask = mask;
111 u32 hmask = mask >> 32;
112
113 /*
114 * Use xrstors to restore context if it is enabled. xrstors supports
115 * compacted format of xsave area which is not supported by xrstor.
116 */
117 alternative_input(
118 "1: " XRSTOR,
119 "1: " XRSTORS,
120 X86_FEATURE_XSAVES,
121 "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
122 : "memory");
123
124 asm volatile("2:\n"
125 xstate_fault
126 : "0" (0)
127 : "memory");
128
129 return err;
130}
131
f9de314b
FY
132/*
133 * Save xstate context for old process during context switch.
134 */
135static inline void fpu_xsave(struct fpu *fpu)
b359e8a4 136{
f9de314b
FY
137 xsave_state(&fpu->state->xsave, -1);
138}
b359e8a4 139
f9de314b
FY
140/*
141 * Restore xstate context for new process during context switch.
142 */
143static inline int fpu_xrstor_checking(struct xsave_struct *fx)
144{
145 return xrstor_state(fx, -1);
b359e8a4
SS
146}
147
c37b5efe 148static inline int xsave_user(struct xsave_struct __user *buf)
9dc89c0f
SS
149{
150 int err;
8e221b6d
SS
151
152 /*
153 * Clear the xsave header first, so that reserved fields are
154 * initialized to zero.
155 */
72a671ce 156 err = __clear_user(&buf->xsave_hdr, sizeof(buf->xsave_hdr));
8e221b6d
SS
157 if (unlikely(err))
158 return -EFAULT;
159
63bcff2a
PA
160 __asm__ __volatile__(ASM_STAC "\n"
161 "1: .byte " REX_PREFIX "0x0f,0xae,0x27\n"
162 "2: " ASM_CLAC "\n"
9dc89c0f
SS
163 ".section .fixup,\"ax\"\n"
164 "3: movl $-1,%[err]\n"
165 " jmp 2b\n"
166 ".previous\n"
7a040a43 167 _ASM_EXTABLE(1b,3b)
9dc89c0f
SS
168 : [err] "=r" (err)
169 : "D" (buf), "a" (-1), "d" (-1), "0" (0)
170 : "memory");
9dc89c0f
SS
171 return err;
172}
173
6152e4b1 174static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
9dc89c0f
SS
175{
176 int err;
177 struct xsave_struct *xstate = ((__force struct xsave_struct *)buf);
6152e4b1
PA
178 u32 lmask = mask;
179 u32 hmask = mask >> 32;
9dc89c0f 180
63bcff2a
PA
181 __asm__ __volatile__(ASM_STAC "\n"
182 "1: .byte " REX_PREFIX "0x0f,0xae,0x2f\n"
183 "2: " ASM_CLAC "\n"
9dc89c0f
SS
184 ".section .fixup,\"ax\"\n"
185 "3: movl $-1,%[err]\n"
186 " jmp 2b\n"
187 ".previous\n"
7a040a43 188 _ASM_EXTABLE(1b,3b)
9dc89c0f
SS
189 : [err] "=r" (err)
190 : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0)
191 : "memory"); /* memory required? */
192 return err;
193}
194
dc1e35c6 195#endif
This page took 0.408069 seconds and 5 git commands to generate.