sigutil_64.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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. if (((unsigned long) fpu) & 7)
  34. return -EFAULT;
  35. err = get_user(fprs, &fpu->si_fprs);
  36. fprs_write(0);
  37. regs->tstate &= ~TSTATE_PEF;
  38. if (fprs & FPRS_DL)
  39. err |= copy_from_user(fpregs, &fpu->si_float_regs[0],
  40. (sizeof(unsigned int) * 32));
  41. if (fprs & FPRS_DU)
  42. err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],
  43. (sizeof(unsigned int) * 32));
  44. err |= __get_user(current_thread_info()->xfsr[0], &fpu->si_fsr);
  45. err |= __get_user(current_thread_info()->gsr[0], &fpu->si_gsr);
  46. current_thread_info()->fpsaved[0] |= fprs;
  47. return err;
  48. }
  49. int save_rwin_state(int wsaved, __siginfo_rwin_t __user *rwin)
  50. {
  51. int i, err = __put_user(wsaved, &rwin->wsaved);
  52. for (i = 0; i < wsaved; i++) {
  53. struct reg_window *rp = &current_thread_info()->reg_window[i];
  54. unsigned long fp = current_thread_info()->rwbuf_stkptrs[i];
  55. err |= copy_to_user(&rwin->reg_window[i], rp,
  56. sizeof(struct reg_window));
  57. err |= __put_user(fp, &rwin->rwbuf_stkptrs[i]);
  58. }
  59. return err;
  60. }
  61. int restore_rwin_state(__siginfo_rwin_t __user *rp)
  62. {
  63. struct thread_info *t = current_thread_info();
  64. int i, wsaved, err;
  65. if (((unsigned long) rp) & 7)
  66. return -EFAULT;
  67. get_user(wsaved, &rp->wsaved);
  68. if (wsaved > NSWINS)
  69. return -EFAULT;
  70. err = 0;
  71. for (i = 0; i < wsaved; i++) {
  72. err |= copy_from_user(&t->reg_window[i],
  73. &rp->reg_window[i],
  74. sizeof(struct reg_window));
  75. err |= __get_user(t->rwbuf_stkptrs[i],
  76. &rp->rwbuf_stkptrs[i]);
  77. }
  78. if (err)
  79. return err;
  80. set_thread_wsaved(wsaved);
  81. synchronize_user_stack();
  82. if (get_thread_wsaved())
  83. return -EFAULT;
  84. return 0;
  85. }