ptrace-vsx.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <linux/regset.h>
  3. #include <asm/switch_to.h>
  4. #include "ptrace-decl.h"
  5. /*
  6. * Regardless of transactions, 'fp_state' holds the current running
  7. * value of all FPR registers and 'ckfp_state' holds the last checkpointed
  8. * value of all FPR registers for the current transaction.
  9. *
  10. * Userspace interface buffer layout:
  11. *
  12. * struct data {
  13. * u64 fpr[32];
  14. * u64 fpscr;
  15. * };
  16. */
  17. int fpr_get(struct task_struct *target, const struct user_regset *regset,
  18. struct membuf to)
  19. {
  20. u64 buf[33];
  21. int i;
  22. flush_fp_to_thread(target);
  23. /* copy to local buffer then write that out */
  24. for (i = 0; i < 32 ; i++)
  25. buf[i] = target->thread.TS_FPR(i);
  26. buf[32] = target->thread.fp_state.fpscr;
  27. return membuf_write(&to, buf, 33 * sizeof(u64));
  28. }
  29. /*
  30. * Regardless of transactions, 'fp_state' holds the current running
  31. * value of all FPR registers and 'ckfp_state' holds the last checkpointed
  32. * value of all FPR registers for the current transaction.
  33. *
  34. * Userspace interface buffer layout:
  35. *
  36. * struct data {
  37. * u64 fpr[32];
  38. * u64 fpscr;
  39. * };
  40. *
  41. */
  42. int fpr_set(struct task_struct *target, const struct user_regset *regset,
  43. unsigned int pos, unsigned int count,
  44. const void *kbuf, const void __user *ubuf)
  45. {
  46. u64 buf[33];
  47. int i;
  48. flush_fp_to_thread(target);
  49. for (i = 0; i < 32 ; i++)
  50. buf[i] = target->thread.TS_FPR(i);
  51. buf[32] = target->thread.fp_state.fpscr;
  52. /* copy to local buffer then write that out */
  53. i = user_regset_copyin(&pos, &count, &kbuf, &ubuf, buf, 0, -1);
  54. if (i)
  55. return i;
  56. for (i = 0; i < 32 ; i++)
  57. target->thread.TS_FPR(i) = buf[i];
  58. target->thread.fp_state.fpscr = buf[32];
  59. return 0;
  60. }
  61. /*
  62. * Currently to set and get all the vsx state, you need to call
  63. * the fp and VMX calls as well. This only get/sets the lower 32
  64. * 128bit VSX registers.
  65. */
  66. int vsr_active(struct task_struct *target, const struct user_regset *regset)
  67. {
  68. flush_vsx_to_thread(target);
  69. return target->thread.used_vsr ? regset->n : 0;
  70. }
  71. /*
  72. * Regardless of transactions, 'fp_state' holds the current running
  73. * value of all FPR registers and 'ckfp_state' holds the last
  74. * checkpointed value of all FPR registers for the current
  75. * transaction.
  76. *
  77. * Userspace interface buffer layout:
  78. *
  79. * struct data {
  80. * u64 vsx[32];
  81. * };
  82. */
  83. int vsr_get(struct task_struct *target, const struct user_regset *regset,
  84. struct membuf to)
  85. {
  86. u64 buf[32];
  87. int i;
  88. flush_tmregs_to_thread(target);
  89. flush_fp_to_thread(target);
  90. flush_altivec_to_thread(target);
  91. flush_vsx_to_thread(target);
  92. for (i = 0; i < 32 ; i++)
  93. buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
  94. return membuf_write(&to, buf, 32 * sizeof(double));
  95. }
  96. /*
  97. * Regardless of transactions, 'fp_state' holds the current running
  98. * value of all FPR registers and 'ckfp_state' holds the last
  99. * checkpointed value of all FPR registers for the current
  100. * transaction.
  101. *
  102. * Userspace interface buffer layout:
  103. *
  104. * struct data {
  105. * u64 vsx[32];
  106. * };
  107. */
  108. int vsr_set(struct task_struct *target, const struct user_regset *regset,
  109. unsigned int pos, unsigned int count,
  110. const void *kbuf, const void __user *ubuf)
  111. {
  112. u64 buf[32];
  113. int ret, i;
  114. flush_tmregs_to_thread(target);
  115. flush_fp_to_thread(target);
  116. flush_altivec_to_thread(target);
  117. flush_vsx_to_thread(target);
  118. for (i = 0; i < 32 ; i++)
  119. buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET];
  120. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  121. buf, 0, 32 * sizeof(double));
  122. if (!ret)
  123. for (i = 0; i < 32 ; i++)
  124. target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i];
  125. return ret;
  126. }