sigutil_64.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include <linux/kernel.h>
  2. #include <linux/types.h>
  3. #include <linux/thread_info.h>
  4. #include <linux/uaccess.h>
  5. #include <linux/errno.h>
  6. #include <asm/sigcontext.h>
  7. #include <asm/fpumacro.h>
  8. #include <asm/ptrace.h>
  9. #include <asm/switch_to.h>
  10. #include "sigutil.h"
  11. int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
  12. {
  13. unsigned long *fpregs = current_thread_info()->fpregs;
  14. unsigned long fprs;
  15. int err = 0;
  16. fprs = current_thread_info()->fpsaved[0];
  17. if (fprs & FPRS_DL)
  18. err |= copy_to_user(&fpu->si_float_regs[0], fpregs,
  19. (sizeof(unsigned int) * 32));
  20. if (fprs & FPRS_DU)
  21. err |= copy_to_user(&fpu->si_float_regs[32], fpregs+16,
  22. (sizeof(unsigned int) * 32));
  23. err |= __put_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
  24. err |= __put_user(current_thread_info()->gsr[0], &fpu->si_gsr);
  25. err |= __put_user(fprs, &fpu->si_fprs);
  26. return err;
  27. }
  28. int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
  29. {
  30. unsigned long *fpregs = current_thread_info()->fpregs;
  31. unsigned long fprs;
  32. int err;
  33. err = __get_user(fprs, &fpu->si_fprs);
  34. fprs_write(0);
  35. regs->tstate &= ~TSTATE_PEF;
  36. if (fprs & FPRS_DL)
  37. err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
  38. (sizeof(unsigned int) * 32));
  39. if (fprs & FPRS_DU)
  40. err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
  41. (sizeof(unsigned int) * 32));
  42. err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
  43. err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
  44. current_thread_info()->fpsaved[0] |= fprs;
  45. return err;
  46. }
  47. int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
  48. {
  49. int i, err = __put_user(wsaved, &rwin->wsaved);
  50. for (i = 0; i < wsaved; i++) {
  51. struct reg_window *rp = &current_thread_info()->reg_window[i];
  52. unsigned long fp = current_thread_info()->rwbuf_stkptrs[i];
  53. err |= copy_to_user(&rwin->reg_window[i], rp,
  54. sizeof(struct reg_window));
  55. err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
  56. }
  57. return err;
  58. }
  59. int restore_rwin_state(__siginfo_rwin_t __user *rp)
  60. {
  61. struct thread_info *t = current_thread_info();
  62. int i, wsaved, err;
  63. __get_user(wsaved, &rp->wsaved);
  64. if (wsaved > NSWINS)
  65. return -EFAULT;
  66. err = 0;
  67. for (i = 0; i < wsaved; i++) {
  68. err |= copy_from_user(&t->reg_window[i],
  69. &rp->reg_window[i],
  70. sizeof(struct reg_window));
  71. err |= __get_user(t->rwbuf_stkptrs[i],
  72. &rp->rwbuf_stkptrs[i]);
  73. }
  74. if (err)
  75. return err;
  76. set_thread_wsaved(wsaved);
  77. synchronize_user_stack();
  78. if (get_thread_wsaved())
  79. return -EFAULT;
  80. return 0;
  81. }