ptrace.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Author: Hanlu Li <[email protected]>
  4. * Huacai Chen <[email protected]>
  5. *
  6. * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  7. *
  8. * Derived from MIPS:
  9. * Copyright (C) 1992 Ross Biro
  10. * Copyright (C) Linus Torvalds
  11. * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle
  12. * Copyright (C) 1996 David S. Miller
  13. * Kevin D. Kissell, [email protected] and Carsten Langgaard, [email protected]
  14. * Copyright (C) 1999 MIPS Technologies, Inc.
  15. * Copyright (C) 2000 Ulf Carlsson
  16. */
  17. #include <linux/kernel.h>
  18. #include <linux/audit.h>
  19. #include <linux/compiler.h>
  20. #include <linux/context_tracking.h>
  21. #include <linux/elf.h>
  22. #include <linux/errno.h>
  23. #include <linux/mm.h>
  24. #include <linux/ptrace.h>
  25. #include <linux/regset.h>
  26. #include <linux/sched.h>
  27. #include <linux/sched/task_stack.h>
  28. #include <linux/security.h>
  29. #include <linux/smp.h>
  30. #include <linux/stddef.h>
  31. #include <linux/seccomp.h>
  32. #include <linux/uaccess.h>
  33. #include <asm/byteorder.h>
  34. #include <asm/cpu.h>
  35. #include <asm/cpu-info.h>
  36. #include <asm/fpu.h>
  37. #include <asm/loongarch.h>
  38. #include <asm/page.h>
  39. #include <asm/pgtable.h>
  40. #include <asm/processor.h>
  41. #include <asm/reg.h>
  42. #include <asm/syscall.h>
  43. static void init_fp_ctx(struct task_struct *target)
  44. {
  45. /* The target already has context */
  46. if (tsk_used_math(target))
  47. return;
  48. /* Begin with data registers set to all 1s... */
  49. memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
  50. set_stopped_child_used_math(target);
  51. }
  52. /*
  53. * Called by kernel/ptrace.c when detaching..
  54. *
  55. * Make sure single step bits etc are not set.
  56. */
  57. void ptrace_disable(struct task_struct *child)
  58. {
  59. /* Don't load the watchpoint registers for the ex-child. */
  60. clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
  61. clear_tsk_thread_flag(child, TIF_SINGLESTEP);
  62. }
  63. /* regset get/set implementations */
  64. static int gpr_get(struct task_struct *target,
  65. const struct user_regset *regset,
  66. struct membuf to)
  67. {
  68. int r;
  69. struct pt_regs *regs = task_pt_regs(target);
  70. r = membuf_write(&to, &regs->regs, sizeof(u64) * GPR_NUM);
  71. r = membuf_write(&to, &regs->orig_a0, sizeof(u64));
  72. r = membuf_write(&to, &regs->csr_era, sizeof(u64));
  73. r = membuf_write(&to, &regs->csr_badvaddr, sizeof(u64));
  74. return r;
  75. }
  76. static int gpr_set(struct task_struct *target,
  77. const struct user_regset *regset,
  78. unsigned int pos, unsigned int count,
  79. const void *kbuf, const void __user *ubuf)
  80. {
  81. int err;
  82. int a0_start = sizeof(u64) * GPR_NUM;
  83. int era_start = a0_start + sizeof(u64);
  84. int badvaddr_start = era_start + sizeof(u64);
  85. struct pt_regs *regs = task_pt_regs(target);
  86. err = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  87. &regs->regs,
  88. 0, a0_start);
  89. err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  90. &regs->orig_a0,
  91. a0_start, a0_start + sizeof(u64));
  92. err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  93. &regs->csr_era,
  94. era_start, era_start + sizeof(u64));
  95. err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  96. &regs->csr_badvaddr,
  97. badvaddr_start, badvaddr_start + sizeof(u64));
  98. return err;
  99. }
  100. /*
  101. * Get the general floating-point registers.
  102. */
  103. static int gfpr_get(struct task_struct *target, struct membuf *to)
  104. {
  105. return membuf_write(to, &target->thread.fpu.fpr,
  106. sizeof(elf_fpreg_t) * NUM_FPU_REGS);
  107. }
  108. static int gfpr_get_simd(struct task_struct *target, struct membuf *to)
  109. {
  110. int i, r;
  111. u64 fpr_val;
  112. BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
  113. for (i = 0; i < NUM_FPU_REGS; i++) {
  114. fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0);
  115. r = membuf_write(to, &fpr_val, sizeof(elf_fpreg_t));
  116. }
  117. return r;
  118. }
  119. /*
  120. * Choose the appropriate helper for general registers, and then copy
  121. * the FCC and FCSR registers separately.
  122. */
  123. static int fpr_get(struct task_struct *target,
  124. const struct user_regset *regset,
  125. struct membuf to)
  126. {
  127. int r;
  128. if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
  129. r = gfpr_get(target, &to);
  130. else
  131. r = gfpr_get_simd(target, &to);
  132. r = membuf_write(&to, &target->thread.fpu.fcc, sizeof(target->thread.fpu.fcc));
  133. r = membuf_write(&to, &target->thread.fpu.fcsr, sizeof(target->thread.fpu.fcsr));
  134. return r;
  135. }
  136. static int gfpr_set(struct task_struct *target,
  137. unsigned int *pos, unsigned int *count,
  138. const void **kbuf, const void __user **ubuf)
  139. {
  140. return user_regset_copyin(pos, count, kbuf, ubuf,
  141. &target->thread.fpu.fpr,
  142. 0, NUM_FPU_REGS * sizeof(elf_fpreg_t));
  143. }
  144. static int gfpr_set_simd(struct task_struct *target,
  145. unsigned int *pos, unsigned int *count,
  146. const void **kbuf, const void __user **ubuf)
  147. {
  148. int i, err;
  149. u64 fpr_val;
  150. BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t));
  151. for (i = 0; i < NUM_FPU_REGS && *count > 0; i++) {
  152. err = user_regset_copyin(pos, count, kbuf, ubuf,
  153. &fpr_val, i * sizeof(elf_fpreg_t),
  154. (i + 1) * sizeof(elf_fpreg_t));
  155. if (err)
  156. return err;
  157. set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val);
  158. }
  159. return 0;
  160. }
  161. /*
  162. * Choose the appropriate helper for general registers, and then copy
  163. * the FCC register separately.
  164. */
  165. static int fpr_set(struct task_struct *target,
  166. const struct user_regset *regset,
  167. unsigned int pos, unsigned int count,
  168. const void *kbuf, const void __user *ubuf)
  169. {
  170. const int fcc_start = NUM_FPU_REGS * sizeof(elf_fpreg_t);
  171. const int fcsr_start = fcc_start + sizeof(u64);
  172. int err;
  173. BUG_ON(count % sizeof(elf_fpreg_t));
  174. if (pos + count > sizeof(elf_fpregset_t))
  175. return -EIO;
  176. init_fp_ctx(target);
  177. if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
  178. err = gfpr_set(target, &pos, &count, &kbuf, &ubuf);
  179. else
  180. err = gfpr_set_simd(target, &pos, &count, &kbuf, &ubuf);
  181. if (err)
  182. return err;
  183. err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  184. &target->thread.fpu.fcc, fcc_start,
  185. fcc_start + sizeof(u64));
  186. err |= user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  187. &target->thread.fpu.fcsr, fcsr_start,
  188. fcsr_start + sizeof(u32));
  189. return err;
  190. }
  191. static int cfg_get(struct task_struct *target,
  192. const struct user_regset *regset,
  193. struct membuf to)
  194. {
  195. int i, r;
  196. u32 cfg_val;
  197. i = 0;
  198. while (to.left > 0) {
  199. cfg_val = read_cpucfg(i++);
  200. r = membuf_write(&to, &cfg_val, sizeof(u32));
  201. }
  202. return r;
  203. }
  204. /*
  205. * CFG registers are read-only.
  206. */
  207. static int cfg_set(struct task_struct *target,
  208. const struct user_regset *regset,
  209. unsigned int pos, unsigned int count,
  210. const void *kbuf, const void __user *ubuf)
  211. {
  212. return 0;
  213. }
  214. struct pt_regs_offset {
  215. const char *name;
  216. int offset;
  217. };
  218. #define REG_OFFSET_NAME(n, r) {.name = #n, .offset = offsetof(struct pt_regs, r)}
  219. #define REG_OFFSET_END {.name = NULL, .offset = 0}
  220. static const struct pt_regs_offset regoffset_table[] = {
  221. REG_OFFSET_NAME(r0, regs[0]),
  222. REG_OFFSET_NAME(r1, regs[1]),
  223. REG_OFFSET_NAME(r2, regs[2]),
  224. REG_OFFSET_NAME(r3, regs[3]),
  225. REG_OFFSET_NAME(r4, regs[4]),
  226. REG_OFFSET_NAME(r5, regs[5]),
  227. REG_OFFSET_NAME(r6, regs[6]),
  228. REG_OFFSET_NAME(r7, regs[7]),
  229. REG_OFFSET_NAME(r8, regs[8]),
  230. REG_OFFSET_NAME(r9, regs[9]),
  231. REG_OFFSET_NAME(r10, regs[10]),
  232. REG_OFFSET_NAME(r11, regs[11]),
  233. REG_OFFSET_NAME(r12, regs[12]),
  234. REG_OFFSET_NAME(r13, regs[13]),
  235. REG_OFFSET_NAME(r14, regs[14]),
  236. REG_OFFSET_NAME(r15, regs[15]),
  237. REG_OFFSET_NAME(r16, regs[16]),
  238. REG_OFFSET_NAME(r17, regs[17]),
  239. REG_OFFSET_NAME(r18, regs[18]),
  240. REG_OFFSET_NAME(r19, regs[19]),
  241. REG_OFFSET_NAME(r20, regs[20]),
  242. REG_OFFSET_NAME(r21, regs[21]),
  243. REG_OFFSET_NAME(r22, regs[22]),
  244. REG_OFFSET_NAME(r23, regs[23]),
  245. REG_OFFSET_NAME(r24, regs[24]),
  246. REG_OFFSET_NAME(r25, regs[25]),
  247. REG_OFFSET_NAME(r26, regs[26]),
  248. REG_OFFSET_NAME(r27, regs[27]),
  249. REG_OFFSET_NAME(r28, regs[28]),
  250. REG_OFFSET_NAME(r29, regs[29]),
  251. REG_OFFSET_NAME(r30, regs[30]),
  252. REG_OFFSET_NAME(r31, regs[31]),
  253. REG_OFFSET_NAME(orig_a0, orig_a0),
  254. REG_OFFSET_NAME(csr_era, csr_era),
  255. REG_OFFSET_NAME(csr_badvaddr, csr_badvaddr),
  256. REG_OFFSET_NAME(csr_crmd, csr_crmd),
  257. REG_OFFSET_NAME(csr_prmd, csr_prmd),
  258. REG_OFFSET_NAME(csr_euen, csr_euen),
  259. REG_OFFSET_NAME(csr_ecfg, csr_ecfg),
  260. REG_OFFSET_NAME(csr_estat, csr_estat),
  261. REG_OFFSET_END,
  262. };
  263. /**
  264. * regs_query_register_offset() - query register offset from its name
  265. * @name: the name of a register
  266. *
  267. * regs_query_register_offset() returns the offset of a register in struct
  268. * pt_regs from its name. If the name is invalid, this returns -EINVAL;
  269. */
  270. int regs_query_register_offset(const char *name)
  271. {
  272. const struct pt_regs_offset *roff;
  273. for (roff = regoffset_table; roff->name != NULL; roff++)
  274. if (!strcmp(roff->name, name))
  275. return roff->offset;
  276. return -EINVAL;
  277. }
  278. enum loongarch_regset {
  279. REGSET_GPR,
  280. REGSET_FPR,
  281. REGSET_CPUCFG,
  282. };
  283. static const struct user_regset loongarch64_regsets[] = {
  284. [REGSET_GPR] = {
  285. .core_note_type = NT_PRSTATUS,
  286. .n = ELF_NGREG,
  287. .size = sizeof(elf_greg_t),
  288. .align = sizeof(elf_greg_t),
  289. .regset_get = gpr_get,
  290. .set = gpr_set,
  291. },
  292. [REGSET_FPR] = {
  293. .core_note_type = NT_PRFPREG,
  294. .n = ELF_NFPREG,
  295. .size = sizeof(elf_fpreg_t),
  296. .align = sizeof(elf_fpreg_t),
  297. .regset_get = fpr_get,
  298. .set = fpr_set,
  299. },
  300. [REGSET_CPUCFG] = {
  301. .core_note_type = NT_LOONGARCH_CPUCFG,
  302. .n = 64,
  303. .size = sizeof(u32),
  304. .align = sizeof(u32),
  305. .regset_get = cfg_get,
  306. .set = cfg_set,
  307. },
  308. };
  309. static const struct user_regset_view user_loongarch64_view = {
  310. .name = "loongarch64",
  311. .e_machine = ELF_ARCH,
  312. .regsets = loongarch64_regsets,
  313. .n = ARRAY_SIZE(loongarch64_regsets),
  314. };
  315. const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  316. {
  317. return &user_loongarch64_view;
  318. }
  319. static inline int read_user(struct task_struct *target, unsigned long addr,
  320. unsigned long __user *data)
  321. {
  322. unsigned long tmp = 0;
  323. switch (addr) {
  324. case 0 ... 31:
  325. tmp = task_pt_regs(target)->regs[addr];
  326. break;
  327. case ARG0:
  328. tmp = task_pt_regs(target)->orig_a0;
  329. break;
  330. case PC:
  331. tmp = task_pt_regs(target)->csr_era;
  332. break;
  333. case BADVADDR:
  334. tmp = task_pt_regs(target)->csr_badvaddr;
  335. break;
  336. default:
  337. return -EIO;
  338. }
  339. return put_user(tmp, data);
  340. }
  341. static inline int write_user(struct task_struct *target, unsigned long addr,
  342. unsigned long data)
  343. {
  344. switch (addr) {
  345. case 0 ... 31:
  346. task_pt_regs(target)->regs[addr] = data;
  347. break;
  348. case ARG0:
  349. task_pt_regs(target)->orig_a0 = data;
  350. break;
  351. case PC:
  352. task_pt_regs(target)->csr_era = data;
  353. break;
  354. case BADVADDR:
  355. task_pt_regs(target)->csr_badvaddr = data;
  356. break;
  357. default:
  358. return -EIO;
  359. }
  360. return 0;
  361. }
  362. long arch_ptrace(struct task_struct *child, long request,
  363. unsigned long addr, unsigned long data)
  364. {
  365. int ret;
  366. unsigned long __user *datap = (void __user *) data;
  367. switch (request) {
  368. case PTRACE_PEEKUSR:
  369. ret = read_user(child, addr, datap);
  370. break;
  371. case PTRACE_POKEUSR:
  372. ret = write_user(child, addr, data);
  373. break;
  374. default:
  375. ret = ptrace_request(child, request, addr, data);
  376. break;
  377. }
  378. return ret;
  379. }