diff options
author | Suresh Siddha <suresh.b.siddha@intel.com> | 2010-02-11 14:50:59 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2010-02-11 18:08:17 -0500 |
commit | 5b3efd500854d45d305b53c54c97db5970959980 (patch) | |
tree | 731629e22791d14b9661cada9c0c69eb38776c3b /arch/x86/kernel/i387.c | |
parent | 676ad585531e965416fd958747894541dabcec96 (diff) |
x86, ptrace: regset extensions to support xstate
Add the xstate regset support which helps extend the kernel ptrace and the
core-dump interfaces to support AVX state etc.
This regset interface is designed to support all the future state that gets
supported using xsave/xrstor infrastructure.
Looking at the memory layout saved by "xsave", one can't say which state
is represented in the memory layout. This is because if a particular state is
in init state, in the xsave hdr it can be represented by bit '0'. And hence
we can't really say by the xsave header wether a state is in init state or
the state is not saved in the memory layout.
And hence the xsave memory layout available through this regset
interface uses SW usable bytes [464..511] to convey what state is represented
in the memory layout.
First 8 bytes of the sw_usable_bytes[464..467] will be set to OS enabled xstate
mask(which is same as the 64bit mask returned by the xgetbv's xCR0).
The note NT_X86_XSTATE represents the extended state information in the
core file, using the above mentioned memory layout.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
LKML-Reference: <20100211195614.802495327@sbs-t61.sc.intel.com>
Signed-off-by: Hongjiu Lu <hjl.tools@gmail.com>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/i387.c')
-rw-r--r-- | arch/x86/kernel/i387.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index f2f8540a7f3d..7a8a193b5144 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
@@ -164,6 +164,11 @@ int init_fpu(struct task_struct *tsk) | |||
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | /* | ||
168 | * The xstateregs_active() routine is the same as the fpregs_active() routine, | ||
169 | * as the "regset->n" for the xstate regset will be updated based on the feature | ||
170 | * capabilites supported by the xsave. | ||
171 | */ | ||
167 | int fpregs_active(struct task_struct *target, const struct user_regset *regset) | 172 | int fpregs_active(struct task_struct *target, const struct user_regset *regset) |
168 | { | 173 | { |
169 | return tsk_used_math(target) ? regset->n : 0; | 174 | return tsk_used_math(target) ? regset->n : 0; |
@@ -224,6 +229,84 @@ int xfpregs_set(struct task_struct *target, const struct user_regset *regset, | |||
224 | return ret; | 229 | return ret; |
225 | } | 230 | } |
226 | 231 | ||
232 | int xstateregs_get(struct task_struct *target, const struct user_regset *regset, | ||
233 | unsigned int pos, unsigned int count, | ||
234 | void *kbuf, void __user *ubuf) | ||
235 | { | ||
236 | int ret; | ||
237 | |||
238 | if (!cpu_has_xsave) | ||
239 | return -ENODEV; | ||
240 | |||
241 | ret = init_fpu(target); | ||
242 | if (ret) | ||
243 | return ret; | ||
244 | |||
245 | /* | ||
246 | * First copy the fxsave bytes 0..463. | ||
247 | */ | ||
248 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
249 | &target->thread.xstate->xsave, 0, | ||
250 | offsetof(struct user_xstateregs, | ||
251 | i387.xstate_fx_sw)); | ||
252 | if (ret) | ||
253 | return ret; | ||
254 | |||
255 | /* | ||
256 | * Copy the 48bytes defined by software. | ||
257 | */ | ||
258 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
259 | xstate_fx_sw_bytes, | ||
260 | offsetof(struct user_xstateregs, | ||
261 | i387.xstate_fx_sw), | ||
262 | offsetof(struct user_xstateregs, | ||
263 | xsave_hdr)); | ||
264 | if (ret) | ||
265 | return ret; | ||
266 | |||
267 | /* | ||
268 | * Copy the rest of xstate memory layout. | ||
269 | */ | ||
270 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | ||
271 | &target->thread.xstate->xsave.xsave_hdr, | ||
272 | offsetof(struct user_xstateregs, | ||
273 | xsave_hdr), -1); | ||
274 | return ret; | ||
275 | } | ||
276 | |||
277 | int xstateregs_set(struct task_struct *target, const struct user_regset *regset, | ||
278 | unsigned int pos, unsigned int count, | ||
279 | const void *kbuf, const void __user *ubuf) | ||
280 | { | ||
281 | int ret; | ||
282 | struct xsave_hdr_struct *xsave_hdr; | ||
283 | |||
284 | if (!cpu_has_xsave) | ||
285 | return -ENODEV; | ||
286 | |||
287 | ret = init_fpu(target); | ||
288 | if (ret) | ||
289 | return ret; | ||
290 | |||
291 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | ||
292 | &target->thread.xstate->xsave, 0, -1); | ||
293 | |||
294 | /* | ||
295 | * mxcsr reserved bits must be masked to zero for security reasons. | ||
296 | */ | ||
297 | target->thread.xstate->fxsave.mxcsr &= mxcsr_feature_mask; | ||
298 | |||
299 | xsave_hdr = &target->thread.xstate->xsave.xsave_hdr; | ||
300 | |||
301 | xsave_hdr->xstate_bv &= pcntxt_mask; | ||
302 | /* | ||
303 | * These bits must be zero. | ||
304 | */ | ||
305 | xsave_hdr->reserved1[0] = xsave_hdr->reserved1[1] = 0; | ||
306 | |||
307 | return ret; | ||
308 | } | ||
309 | |||
227 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION | 310 | #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION |
228 | 311 | ||
229 | /* | 312 | /* |