ptrace.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright 2010 Tilera Corporation. All Rights Reserved.
  4. * Copyright 2015 Regents of the University of California
  5. * Copyright 2017 SiFive
  6. *
  7. * Copied from arch/tile/kernel/ptrace.c
  8. */
  9. #include <asm/vector.h>
  10. #include <asm/ptrace.h>
  11. #include <asm/syscall.h>
  12. #include <asm/thread_info.h>
  13. #include <asm/switch_to.h>
  14. #include <linux/audit.h>
  15. #include <linux/compat.h>
  16. #include <linux/ptrace.h>
  17. #include <linux/elf.h>
  18. #include <linux/regset.h>
  19. #include <linux/sched.h>
  20. #include <linux/sched/task_stack.h>
  21. enum riscv_regset {
  22. REGSET_X,
  23. #ifdef CONFIG_FPU
  24. REGSET_F,
  25. #endif
  26. #ifdef CONFIG_RISCV_ISA_V
  27. REGSET_V,
  28. #endif
  29. };
  30. static int riscv_gpr_get(struct task_struct *target,
  31. const struct user_regset *regset,
  32. struct membuf to)
  33. {
  34. return membuf_write(&to, task_pt_regs(target),
  35. sizeof(struct user_regs_struct));
  36. }
  37. static int riscv_gpr_set(struct task_struct *target,
  38. const struct user_regset *regset,
  39. unsigned int pos, unsigned int count,
  40. const void *kbuf, const void __user *ubuf)
  41. {
  42. struct pt_regs *regs;
  43. regs = task_pt_regs(target);
  44. return user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 0, -1);
  45. }
  46. #ifdef CONFIG_FPU
  47. static int riscv_fpr_get(struct task_struct *target,
  48. const struct user_regset *regset,
  49. struct membuf to)
  50. {
  51. struct __riscv_d_ext_state *fstate = &target->thread.fstate;
  52. if (target == current)
  53. fstate_save(current, task_pt_regs(current));
  54. membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
  55. membuf_store(&to, fstate->fcsr);
  56. return membuf_zero(&to, 4); // explicitly pad
  57. }
  58. static int riscv_fpr_set(struct task_struct *target,
  59. const struct user_regset *regset,
  60. unsigned int pos, unsigned int count,
  61. const void *kbuf, const void __user *ubuf)
  62. {
  63. int ret;
  64. struct __riscv_d_ext_state *fstate = &target->thread.fstate;
  65. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
  66. offsetof(struct __riscv_d_ext_state, fcsr));
  67. if (!ret) {
  68. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fstate, 0,
  69. offsetof(struct __riscv_d_ext_state, fcsr) +
  70. sizeof(fstate->fcsr));
  71. }
  72. return ret;
  73. }
  74. #endif
  75. #ifdef CONFIG_RISCV_ISA_V
  76. static int riscv_vr_get(struct task_struct *target,
  77. const struct user_regset *regset,
  78. struct membuf to)
  79. {
  80. struct __riscv_v_ext_state *vstate = &target->thread.vstate;
  81. struct __riscv_v_regset_state ptrace_vstate;
  82. if (!riscv_v_vstate_query(task_pt_regs(target)))
  83. return -EINVAL;
  84. /*
  85. * Ensure the vector registers have been saved to the memory before
  86. * copying them to membuf.
  87. */
  88. if (target == current) {
  89. get_cpu_vector_context();
  90. riscv_v_vstate_save(&current->thread.vstate, task_pt_regs(current));
  91. put_cpu_vector_context();
  92. }
  93. ptrace_vstate.vstart = vstate->vstart;
  94. ptrace_vstate.vl = vstate->vl;
  95. ptrace_vstate.vtype = vstate->vtype;
  96. ptrace_vstate.vcsr = vstate->vcsr;
  97. ptrace_vstate.vlenb = vstate->vlenb;
  98. /* Copy vector header from vstate. */
  99. membuf_write(&to, &ptrace_vstate, sizeof(struct __riscv_v_regset_state));
  100. /* Copy all the vector registers from vstate. */
  101. return membuf_write(&to, vstate->datap, riscv_v_vsize);
  102. }
  103. static int riscv_vr_set(struct task_struct *target,
  104. const struct user_regset *regset,
  105. unsigned int pos, unsigned int count,
  106. const void *kbuf, const void __user *ubuf)
  107. {
  108. int ret;
  109. struct __riscv_v_ext_state *vstate = &target->thread.vstate;
  110. struct __riscv_v_regset_state ptrace_vstate;
  111. if (!riscv_v_vstate_query(task_pt_regs(target)))
  112. return -EINVAL;
  113. /* Copy rest of the vstate except datap */
  114. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ptrace_vstate, 0,
  115. sizeof(struct __riscv_v_regset_state));
  116. if (unlikely(ret))
  117. return ret;
  118. if (vstate->vlenb != ptrace_vstate.vlenb)
  119. return -EINVAL;
  120. vstate->vstart = ptrace_vstate.vstart;
  121. vstate->vl = ptrace_vstate.vl;
  122. vstate->vtype = ptrace_vstate.vtype;
  123. vstate->vcsr = ptrace_vstate.vcsr;
  124. /* Copy all the vector registers. */
  125. pos = 0;
  126. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, vstate->datap,
  127. 0, riscv_v_vsize);
  128. return ret;
  129. }
  130. #endif
  131. static const struct user_regset riscv_user_regset[] = {
  132. [REGSET_X] = {
  133. .core_note_type = NT_PRSTATUS,
  134. .n = ELF_NGREG,
  135. .size = sizeof(elf_greg_t),
  136. .align = sizeof(elf_greg_t),
  137. .regset_get = riscv_gpr_get,
  138. .set = riscv_gpr_set,
  139. },
  140. #ifdef CONFIG_FPU
  141. [REGSET_F] = {
  142. .core_note_type = NT_PRFPREG,
  143. .n = ELF_NFPREG,
  144. .size = sizeof(elf_fpreg_t),
  145. .align = sizeof(elf_fpreg_t),
  146. .regset_get = riscv_fpr_get,
  147. .set = riscv_fpr_set,
  148. },
  149. #endif
  150. #ifdef CONFIG_RISCV_ISA_V
  151. [REGSET_V] = {
  152. .core_note_type = NT_RISCV_VECTOR,
  153. .align = 16,
  154. .n = ((32 * RISCV_MAX_VLENB) +
  155. sizeof(struct __riscv_v_regset_state)) / sizeof(__u32),
  156. .size = sizeof(__u32),
  157. .regset_get = riscv_vr_get,
  158. .set = riscv_vr_set,
  159. },
  160. #endif
  161. };
  162. static const struct user_regset_view riscv_user_native_view = {
  163. .name = "riscv",
  164. .e_machine = EM_RISCV,
  165. .regsets = riscv_user_regset,
  166. .n = ARRAY_SIZE(riscv_user_regset),
  167. };
  168. struct pt_regs_offset {
  169. const char *name;
  170. int offset;
  171. };
  172. #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
  173. #define REG_OFFSET_END {.name = NULL, .offset = 0}
  174. static const struct pt_regs_offset regoffset_table[] = {
  175. REG_OFFSET_NAME(epc),
  176. REG_OFFSET_NAME(ra),
  177. REG_OFFSET_NAME(sp),
  178. REG_OFFSET_NAME(gp),
  179. REG_OFFSET_NAME(tp),
  180. REG_OFFSET_NAME(t0),
  181. REG_OFFSET_NAME(t1),
  182. REG_OFFSET_NAME(t2),
  183. REG_OFFSET_NAME(s0),
  184. REG_OFFSET_NAME(s1),
  185. REG_OFFSET_NAME(a0),
  186. REG_OFFSET_NAME(a1),
  187. REG_OFFSET_NAME(a2),
  188. REG_OFFSET_NAME(a3),
  189. REG_OFFSET_NAME(a4),
  190. REG_OFFSET_NAME(a5),
  191. REG_OFFSET_NAME(a6),
  192. REG_OFFSET_NAME(a7),
  193. REG_OFFSET_NAME(s2),
  194. REG_OFFSET_NAME(s3),
  195. REG_OFFSET_NAME(s4),
  196. REG_OFFSET_NAME(s5),
  197. REG_OFFSET_NAME(s6),
  198. REG_OFFSET_NAME(s7),
  199. REG_OFFSET_NAME(s8),
  200. REG_OFFSET_NAME(s9),
  201. REG_OFFSET_NAME(s10),
  202. REG_OFFSET_NAME(s11),
  203. REG_OFFSET_NAME(t3),
  204. REG_OFFSET_NAME(t4),
  205. REG_OFFSET_NAME(t5),
  206. REG_OFFSET_NAME(t6),
  207. REG_OFFSET_NAME(status),
  208. REG_OFFSET_NAME(badaddr),
  209. REG_OFFSET_NAME(cause),
  210. REG_OFFSET_NAME(orig_a0),
  211. REG_OFFSET_END,
  212. };
  213. /**
  214. * regs_query_register_offset() - query register offset from its name
  215. * @name: the name of a register
  216. *
  217. * regs_query_register_offset() returns the offset of a register in struct
  218. * pt_regs from its name. If the name is invalid, this returns -EINVAL;
  219. */
  220. int regs_query_register_offset(const char *name)
  221. {
  222. const struct pt_regs_offset *roff;
  223. for (roff = regoffset_table; roff->name != NULL; roff++)
  224. if (!strcmp(roff->name, name))
  225. return roff->offset;
  226. return -EINVAL;
  227. }
  228. /**
  229. * regs_within_kernel_stack() - check the address in the stack
  230. * @regs: pt_regs which contains kernel stack pointer.
  231. * @addr: address which is checked.
  232. *
  233. * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
  234. * If @addr is within the kernel stack, it returns true. If not, returns false.
  235. */
  236. static bool regs_within_kernel_stack(struct pt_regs *regs, unsigned long addr)
  237. {
  238. return (addr & ~(THREAD_SIZE - 1)) ==
  239. (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1));
  240. }
  241. /**
  242. * regs_get_kernel_stack_nth() - get Nth entry of the stack
  243. * @regs: pt_regs which contains kernel stack pointer.
  244. * @n: stack entry number.
  245. *
  246. * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
  247. * is specified by @regs. If the @n th entry is NOT in the kernel stack,
  248. * this returns 0.
  249. */
  250. unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs, unsigned int n)
  251. {
  252. unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
  253. addr += n;
  254. if (regs_within_kernel_stack(regs, (unsigned long)addr))
  255. return *addr;
  256. else
  257. return 0;
  258. }
  259. void ptrace_disable(struct task_struct *child)
  260. {
  261. }
  262. long arch_ptrace(struct task_struct *child, long request,
  263. unsigned long addr, unsigned long data)
  264. {
  265. long ret = -EIO;
  266. switch (request) {
  267. default:
  268. ret = ptrace_request(child, request, addr, data);
  269. break;
  270. }
  271. return ret;
  272. }
  273. #ifdef CONFIG_COMPAT
  274. static int compat_riscv_gpr_get(struct task_struct *target,
  275. const struct user_regset *regset,
  276. struct membuf to)
  277. {
  278. struct compat_user_regs_struct cregs;
  279. regs_to_cregs(&cregs, task_pt_regs(target));
  280. return membuf_write(&to, &cregs,
  281. sizeof(struct compat_user_regs_struct));
  282. }
  283. static int compat_riscv_gpr_set(struct task_struct *target,
  284. const struct user_regset *regset,
  285. unsigned int pos, unsigned int count,
  286. const void *kbuf, const void __user *ubuf)
  287. {
  288. int ret;
  289. struct compat_user_regs_struct cregs;
  290. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &cregs, 0, -1);
  291. cregs_to_regs(&cregs, task_pt_regs(target));
  292. return ret;
  293. }
  294. static const struct user_regset compat_riscv_user_regset[] = {
  295. [REGSET_X] = {
  296. .core_note_type = NT_PRSTATUS,
  297. .n = ELF_NGREG,
  298. .size = sizeof(compat_elf_greg_t),
  299. .align = sizeof(compat_elf_greg_t),
  300. .regset_get = compat_riscv_gpr_get,
  301. .set = compat_riscv_gpr_set,
  302. },
  303. #ifdef CONFIG_FPU
  304. [REGSET_F] = {
  305. .core_note_type = NT_PRFPREG,
  306. .n = ELF_NFPREG,
  307. .size = sizeof(elf_fpreg_t),
  308. .align = sizeof(elf_fpreg_t),
  309. .regset_get = riscv_fpr_get,
  310. .set = riscv_fpr_set,
  311. },
  312. #endif
  313. };
  314. static const struct user_regset_view compat_riscv_user_native_view = {
  315. .name = "riscv",
  316. .e_machine = EM_RISCV,
  317. .regsets = compat_riscv_user_regset,
  318. .n = ARRAY_SIZE(compat_riscv_user_regset),
  319. };
  320. long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
  321. compat_ulong_t caddr, compat_ulong_t cdata)
  322. {
  323. long ret = -EIO;
  324. switch (request) {
  325. default:
  326. ret = compat_ptrace_request(child, request, caddr, cdata);
  327. break;
  328. }
  329. return ret;
  330. }
  331. #else
  332. static const struct user_regset_view compat_riscv_user_native_view = {};
  333. #endif /* CONFIG_COMPAT */
  334. const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  335. {
  336. if (is_compat_thread(&task->thread_info))
  337. return &compat_riscv_user_native_view;
  338. else
  339. return &riscv_user_native_view;
  340. }