aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/i387.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/i387.c')
-rw-r--r--arch/x86/kernel/i387.c105
1 files changed, 9 insertions, 96 deletions
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c
index f7f7568dd7bc..26719bd2c77c 100644
--- a/arch/x86/kernel/i387.c
+++ b/arch/x86/kernel/i387.c
@@ -454,113 +454,26 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf)
454 return err; 454 return err;
455} 455}
456 456
457#endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
458
459#ifdef CONFIG_X86_64
460
461int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *tsk)
462{
463 return xfpregs_get(tsk, NULL, 0, sizeof(*buf), NULL, buf);
464}
465
466int set_fpregs(struct task_struct *tsk, struct user_i387_struct __user *buf)
467{
468 return xfpregs_set(tsk, NULL, 0, sizeof(*buf), NULL, buf);
469}
470
471#else
472
473int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *tsk)
474{
475 return fpregs_get(tsk, NULL, 0, sizeof(*buf), NULL, buf);
476}
477
478int set_fpregs(struct task_struct *tsk, struct user_i387_struct __user *buf)
479{
480 return fpregs_set(tsk, NULL, 0, sizeof(*buf), NULL, buf);
481}
482
483int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *tsk)
484{
485 return xfpregs_get(tsk, NULL, 0, sizeof(*buf), NULL, buf);
486}
487
488int set_fpxregs(struct task_struct *tsk, struct user_fxsr_struct __user *buf)
489{
490 return xfpregs_get(tsk, NULL, 0, sizeof(*buf), NULL, buf);
491}
492
493#endif
494
495/* 457/*
496 * FPU state for core dumps. 458 * FPU state for core dumps.
459 * This is only used for a.out dumps now.
460 * It is declared generically using elf_fpregset_t (which is
461 * struct user_i387_struct) but is in fact only used for 32-bit
462 * dumps, so on 64-bit it is really struct user_i387_ia32_struct.
497 */ 463 */
498
499static inline void copy_fpu_fsave(struct task_struct *tsk,
500 struct user_i387_struct *fpu)
501{
502 memcpy(fpu, &tsk->thread.i387.fsave,
503 sizeof(struct user_i387_struct));
504}
505
506static inline void copy_fpu_fxsave(struct task_struct *tsk,
507 struct user_i387_struct *fpu)
508{
509 unsigned short *to;
510 unsigned short *from;
511 int i;
512
513 memcpy(fpu, &tsk->thread.i387.fxsave, 7 * sizeof(long));
514
515 to = (unsigned short *)&fpu->st_space[0];
516 from = (unsigned short *)&tsk->thread.i387.fxsave.st_space[0];
517 for (i = 0; i < 8; i++, to += 5, from += 8)
518 memcpy(to, from, 5 * sizeof(unsigned short));
519}
520
521int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu) 464int dump_fpu(struct pt_regs *regs, struct user_i387_struct *fpu)
522{ 465{
523 int fpvalid; 466 int fpvalid;
524 struct task_struct *tsk = current; 467 struct task_struct *tsk = current;
525 468
526 fpvalid = !!used_math(); 469 fpvalid = !!used_math();
527 if (fpvalid) { 470 if (fpvalid)
528 unlazy_fpu(tsk); 471 fpvalid = !fpregs_get(tsk, NULL,
529 if (cpu_has_fxsr) { 472 0, sizeof(struct user_i387_ia32_struct),
530 copy_fpu_fxsave(tsk, fpu); 473 fpu, NULL);
531 } else {
532 copy_fpu_fsave(tsk, fpu);
533 }
534 }
535 474
536 return fpvalid; 475 return fpvalid;
537} 476}
538EXPORT_SYMBOL(dump_fpu); 477EXPORT_SYMBOL(dump_fpu);
539 478
540int dump_task_fpu(struct task_struct *tsk, struct user_i387_struct *fpu) 479#endif /* CONFIG_X86_32 || CONFIG_IA32_EMULATION */
541{
542 int fpvalid = !!tsk_used_math(tsk);
543
544 if (fpvalid) {
545 if (tsk == current)
546 unlazy_fpu(tsk);
547 if (cpu_has_fxsr)
548 copy_fpu_fxsave(tsk, fpu);
549 else
550 copy_fpu_fsave(tsk, fpu);
551 }
552 return fpvalid;
553}
554
555int dump_task_extended_fpu(struct task_struct *tsk,
556 struct user32_fxsr_struct *fpu)
557{
558 int fpvalid = tsk_used_math(tsk) && cpu_has_fxsr;
559
560 if (fpvalid) {
561 if (tsk == current)
562 unlazy_fpu(tsk);
563 memcpy(fpu, &tsk->thread.i387.fxsave, sizeof(*fpu));
564 }
565 return fpvalid;
566}