ptrace.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. /* ptrace.c: Sparc process tracing support.
  2. *
  3. * Copyright (C) 1996, 2008 David S. Miller (davem@davemloft.net)
  4. * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  5. *
  6. * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
  7. * and David Mosberger.
  8. *
  9. * Added Linux support -miguel (weird, eh?, the original code was meant
  10. * to emulate SunOS).
  11. */
  12. #include <linux/kernel.h>
  13. #include <linux/sched.h>
  14. #include <linux/mm.h>
  15. #include <linux/errno.h>
  16. #include <linux/ptrace.h>
  17. #include <linux/user.h>
  18. #include <linux/smp.h>
  19. #include <linux/smp_lock.h>
  20. #include <linux/security.h>
  21. #include <linux/seccomp.h>
  22. #include <linux/audit.h>
  23. #include <linux/signal.h>
  24. #include <linux/regset.h>
  25. #include <linux/compat.h>
  26. #include <linux/elf.h>
  27. #include <asm/asi.h>
  28. #include <asm/pgtable.h>
  29. #include <asm/system.h>
  30. #include <asm/uaccess.h>
  31. #include <asm/psrcompat.h>
  32. #include <asm/visasm.h>
  33. #include <asm/spitfire.h>
  34. #include <asm/page.h>
  35. #include <asm/cpudata.h>
  36. #include <asm/cacheflush.h>
  37. #include "entry.h"
  38. /* #define ALLOW_INIT_TRACING */
  39. /*
  40. * Called by kernel/ptrace.c when detaching..
  41. *
  42. * Make sure single step bits etc are not set.
  43. */
  44. void ptrace_disable(struct task_struct *child)
  45. {
  46. /* nothing to do */
  47. }
  48. /* To get the necessary page struct, access_process_vm() first calls
  49. * get_user_pages(). This has done a flush_dcache_page() on the
  50. * accessed page. Then our caller (copy_{to,from}_user_page()) did
  51. * to memcpy to read/write the data from that page.
  52. *
  53. * Now, the only thing we have to do is:
  54. * 1) flush the D-cache if it's possible than an illegal alias
  55. * has been created
  56. * 2) flush the I-cache if this is pre-cheetah and we did a write
  57. */
  58. void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
  59. unsigned long uaddr, void *kaddr,
  60. unsigned long len, int write)
  61. {
  62. BUG_ON(len > PAGE_SIZE);
  63. if (tlb_type == hypervisor)
  64. return;
  65. preempt_disable();
  66. #ifdef DCACHE_ALIASING_POSSIBLE
  67. /* If bit 13 of the kernel address we used to access the
  68. * user page is the same as the virtual address that page
  69. * is mapped to in the user's address space, we can skip the
  70. * D-cache flush.
  71. */
  72. if ((uaddr ^ (unsigned long) kaddr) & (1UL << 13)) {
  73. unsigned long start = __pa(kaddr);
  74. unsigned long end = start + len;
  75. unsigned long dcache_line_size;
  76. dcache_line_size = local_cpu_data().dcache_line_size;
  77. if (tlb_type == spitfire) {
  78. for (; start < end; start += dcache_line_size)
  79. spitfire_put_dcache_tag(start & 0x3fe0, 0x0);
  80. } else {
  81. start &= ~(dcache_line_size - 1);
  82. for (; start < end; start += dcache_line_size)
  83. __asm__ __volatile__(
  84. "stxa %%g0, [%0] %1\n\t"
  85. "membar #Sync"
  86. : /* no outputs */
  87. : "r" (start),
  88. "i" (ASI_DCACHE_INVALIDATE));
  89. }
  90. }
  91. #endif
  92. if (write && tlb_type == spitfire) {
  93. unsigned long start = (unsigned long) kaddr;
  94. unsigned long end = start + len;
  95. unsigned long icache_line_size;
  96. icache_line_size = local_cpu_data().icache_line_size;
  97. for (; start < end; start += icache_line_size)
  98. flushi(start);
  99. }
  100. preempt_enable();
  101. }
  102. enum sparc_regset {
  103. REGSET_GENERAL,
  104. REGSET_FP,
  105. };
  106. static int genregs64_get(struct task_struct *target,
  107. const struct user_regset *regset,
  108. unsigned int pos, unsigned int count,
  109. void *kbuf, void __user *ubuf)
  110. {
  111. const struct pt_regs *regs = task_pt_regs(target);
  112. int ret;
  113. if (target == current)
  114. flushw_user();
  115. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  116. regs->u_regs,
  117. 0, 16 * sizeof(u64));
  118. if (!ret) {
  119. unsigned long __user *reg_window = (unsigned long __user *)
  120. (regs->u_regs[UREG_I6] + STACK_BIAS);
  121. unsigned long window[16];
  122. if (target == current) {
  123. if (copy_from_user(window, reg_window, sizeof(window)))
  124. return -EFAULT;
  125. } else {
  126. if (access_process_vm(target,
  127. (unsigned long) reg_window,
  128. window,
  129. sizeof(window), 0) !=
  130. sizeof(window))
  131. return -EFAULT;
  132. }
  133. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  134. window,
  135. 16 * sizeof(u64),
  136. 32 * sizeof(u64));
  137. }
  138. if (!ret) {
  139. /* TSTATE, TPC, TNPC */
  140. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  141. &regs->tstate,
  142. 32 * sizeof(u64),
  143. 35 * sizeof(u64));
  144. }
  145. if (!ret) {
  146. unsigned long y = regs->y;
  147. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  148. &y,
  149. 35 * sizeof(u64),
  150. 36 * sizeof(u64));
  151. }
  152. if (!ret)
  153. ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  154. 36 * sizeof(u64), -1);
  155. return ret;
  156. }
  157. static int genregs64_set(struct task_struct *target,
  158. const struct user_regset *regset,
  159. unsigned int pos, unsigned int count,
  160. const void *kbuf, const void __user *ubuf)
  161. {
  162. struct pt_regs *regs = task_pt_regs(target);
  163. int ret;
  164. if (target == current)
  165. flushw_user();
  166. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  167. regs->u_regs,
  168. 0, 16 * sizeof(u64));
  169. if (!ret && count > 0) {
  170. unsigned long __user *reg_window = (unsigned long __user *)
  171. (regs->u_regs[UREG_I6] + STACK_BIAS);
  172. unsigned long window[16];
  173. if (target == current) {
  174. if (copy_from_user(window, reg_window, sizeof(window)))
  175. return -EFAULT;
  176. } else {
  177. if (access_process_vm(target,
  178. (unsigned long) reg_window,
  179. window,
  180. sizeof(window), 0) !=
  181. sizeof(window))
  182. return -EFAULT;
  183. }
  184. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  185. window,
  186. 16 * sizeof(u64),
  187. 32 * sizeof(u64));
  188. if (!ret) {
  189. if (target == current) {
  190. if (copy_to_user(reg_window, window,
  191. sizeof(window)))
  192. return -EFAULT;
  193. } else {
  194. if (access_process_vm(target,
  195. (unsigned long)
  196. reg_window,
  197. window,
  198. sizeof(window), 1) !=
  199. sizeof(window))
  200. return -EFAULT;
  201. }
  202. }
  203. }
  204. if (!ret && count > 0) {
  205. unsigned long tstate;
  206. /* TSTATE */
  207. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  208. &tstate,
  209. 32 * sizeof(u64),
  210. 33 * sizeof(u64));
  211. if (!ret) {
  212. /* Only the condition codes can be modified
  213. * in the %tstate register.
  214. */
  215. tstate &= (TSTATE_ICC | TSTATE_XCC);
  216. regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
  217. regs->tstate |= tstate;
  218. }
  219. }
  220. if (!ret) {
  221. /* TPC, TNPC */
  222. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  223. &regs->tpc,
  224. 33 * sizeof(u64),
  225. 35 * sizeof(u64));
  226. }
  227. if (!ret) {
  228. unsigned long y;
  229. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  230. &y,
  231. 35 * sizeof(u64),
  232. 36 * sizeof(u64));
  233. if (!ret)
  234. regs->y = y;
  235. }
  236. if (!ret)
  237. ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  238. 36 * sizeof(u64), -1);
  239. return ret;
  240. }
  241. static int fpregs64_get(struct task_struct *target,
  242. const struct user_regset *regset,
  243. unsigned int pos, unsigned int count,
  244. void *kbuf, void __user *ubuf)
  245. {
  246. const unsigned long *fpregs = task_thread_info(target)->fpregs;
  247. unsigned long fprs, fsr, gsr;
  248. int ret;
  249. if (target == current)
  250. save_and_clear_fpu();
  251. fprs = task_thread_info(target)->fpsaved[0];
  252. if (fprs & FPRS_DL)
  253. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  254. fpregs,
  255. 0, 16 * sizeof(u64));
  256. else
  257. ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  258. 0,
  259. 16 * sizeof(u64));
  260. if (!ret) {
  261. if (fprs & FPRS_DU)
  262. ret = user_regset_copyout(&pos, &count,
  263. &kbuf, &ubuf,
  264. fpregs + 16,
  265. 16 * sizeof(u64),
  266. 32 * sizeof(u64));
  267. else
  268. ret = user_regset_copyout_zero(&pos, &count,
  269. &kbuf, &ubuf,
  270. 16 * sizeof(u64),
  271. 32 * sizeof(u64));
  272. }
  273. if (fprs & FPRS_FEF) {
  274. fsr = task_thread_info(target)->xfsr[0];
  275. gsr = task_thread_info(target)->gsr[0];
  276. } else {
  277. fsr = gsr = 0;
  278. }
  279. if (!ret)
  280. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  281. &fsr,
  282. 32 * sizeof(u64),
  283. 33 * sizeof(u64));
  284. if (!ret)
  285. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  286. &gsr,
  287. 33 * sizeof(u64),
  288. 34 * sizeof(u64));
  289. if (!ret)
  290. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  291. &fprs,
  292. 34 * sizeof(u64),
  293. 35 * sizeof(u64));
  294. if (!ret)
  295. ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  296. 35 * sizeof(u64), -1);
  297. return ret;
  298. }
  299. static int fpregs64_set(struct task_struct *target,
  300. const struct user_regset *regset,
  301. unsigned int pos, unsigned int count,
  302. const void *kbuf, const void __user *ubuf)
  303. {
  304. unsigned long *fpregs = task_thread_info(target)->fpregs;
  305. unsigned long fprs;
  306. int ret;
  307. if (target == current)
  308. save_and_clear_fpu();
  309. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  310. fpregs,
  311. 0, 32 * sizeof(u64));
  312. if (!ret)
  313. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  314. task_thread_info(target)->xfsr,
  315. 32 * sizeof(u64),
  316. 33 * sizeof(u64));
  317. if (!ret)
  318. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  319. task_thread_info(target)->gsr,
  320. 33 * sizeof(u64),
  321. 34 * sizeof(u64));
  322. fprs = task_thread_info(target)->fpsaved[0];
  323. if (!ret && count > 0) {
  324. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  325. &fprs,
  326. 34 * sizeof(u64),
  327. 35 * sizeof(u64));
  328. }
  329. fprs |= (FPRS_FEF | FPRS_DL | FPRS_DU);
  330. task_thread_info(target)->fpsaved[0] = fprs;
  331. if (!ret)
  332. ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  333. 35 * sizeof(u64), -1);
  334. return ret;
  335. }
  336. static const struct user_regset sparc64_regsets[] = {
  337. /* Format is:
  338. * G0 --> G7
  339. * O0 --> O7
  340. * L0 --> L7
  341. * I0 --> I7
  342. * TSTATE, TPC, TNPC, Y
  343. */
  344. [REGSET_GENERAL] = {
  345. .core_note_type = NT_PRSTATUS,
  346. .n = 36 * sizeof(u64),
  347. .size = sizeof(u64), .align = sizeof(u64),
  348. .get = genregs64_get, .set = genregs64_set
  349. },
  350. /* Format is:
  351. * F0 --> F63
  352. * FSR
  353. * GSR
  354. * FPRS
  355. */
  356. [REGSET_FP] = {
  357. .core_note_type = NT_PRFPREG,
  358. .n = 35 * sizeof(u64),
  359. .size = sizeof(u64), .align = sizeof(u64),
  360. .get = fpregs64_get, .set = fpregs64_set
  361. },
  362. };
  363. static const struct user_regset_view user_sparc64_view = {
  364. .name = "sparc64", .e_machine = EM_SPARCV9,
  365. .regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
  366. };
  367. #ifdef CONFIG_COMPAT
  368. static int genregs32_get(struct task_struct *target,
  369. const struct user_regset *regset,
  370. unsigned int pos, unsigned int count,
  371. void *kbuf, void __user *ubuf)
  372. {
  373. const struct pt_regs *regs = task_pt_regs(target);
  374. compat_ulong_t __user *reg_window;
  375. compat_ulong_t *k = kbuf;
  376. compat_ulong_t __user *u = ubuf;
  377. compat_ulong_t reg;
  378. if (target == current)
  379. flushw_user();
  380. pos /= sizeof(reg);
  381. count /= sizeof(reg);
  382. if (kbuf) {
  383. for (; count > 0 && pos < 16; count--)
  384. *k++ = regs->u_regs[pos++];
  385. reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  386. if (target == current) {
  387. for (; count > 0 && pos < 32; count--) {
  388. if (get_user(*k++, &reg_window[pos++]))
  389. return -EFAULT;
  390. }
  391. } else {
  392. for (; count > 0 && pos < 32; count--) {
  393. if (access_process_vm(target,
  394. (unsigned long)
  395. &reg_window[pos],
  396. k, sizeof(*k), 0)
  397. != sizeof(*k))
  398. return -EFAULT;
  399. k++;
  400. pos++;
  401. }
  402. }
  403. } else {
  404. for (; count > 0 && pos < 16; count--) {
  405. if (put_user((compat_ulong_t) regs->u_regs[pos++], u++))
  406. return -EFAULT;
  407. }
  408. reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  409. if (target == current) {
  410. for (; count > 0 && pos < 32; count--) {
  411. if (get_user(reg, &reg_window[pos++]) ||
  412. put_user(reg, u++))
  413. return -EFAULT;
  414. }
  415. } else {
  416. for (; count > 0 && pos < 32; count--) {
  417. if (access_process_vm(target,
  418. (unsigned long)
  419. &reg_window[pos],
  420. &reg, sizeof(reg), 0)
  421. != sizeof(reg))
  422. return -EFAULT;
  423. if (access_process_vm(target,
  424. (unsigned long) u,
  425. &reg, sizeof(reg), 1)
  426. != sizeof(reg))
  427. return -EFAULT;
  428. pos++;
  429. u++;
  430. }
  431. }
  432. }
  433. while (count > 0) {
  434. switch (pos) {
  435. case 32: /* PSR */
  436. reg = tstate_to_psr(regs->tstate);
  437. break;
  438. case 33: /* PC */
  439. reg = regs->tpc;
  440. break;
  441. case 34: /* NPC */
  442. reg = regs->tnpc;
  443. break;
  444. case 35: /* Y */
  445. reg = regs->y;
  446. break;
  447. case 36: /* WIM */
  448. case 37: /* TBR */
  449. reg = 0;
  450. break;
  451. default:
  452. goto finish;
  453. }
  454. if (kbuf)
  455. *k++ = reg;
  456. else if (put_user(reg, u++))
  457. return -EFAULT;
  458. pos++;
  459. count--;
  460. }
  461. finish:
  462. pos *= sizeof(reg);
  463. count *= sizeof(reg);
  464. return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  465. 38 * sizeof(reg), -1);
  466. }
  467. static int genregs32_set(struct task_struct *target,
  468. const struct user_regset *regset,
  469. unsigned int pos, unsigned int count,
  470. const void *kbuf, const void __user *ubuf)
  471. {
  472. struct pt_regs *regs = task_pt_regs(target);
  473. compat_ulong_t __user *reg_window;
  474. const compat_ulong_t *k = kbuf;
  475. const compat_ulong_t __user *u = ubuf;
  476. compat_ulong_t reg;
  477. if (target == current)
  478. flushw_user();
  479. pos /= sizeof(reg);
  480. count /= sizeof(reg);
  481. if (kbuf) {
  482. for (; count > 0 && pos < 16; count--)
  483. regs->u_regs[pos++] = *k++;
  484. reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  485. if (target == current) {
  486. for (; count > 0 && pos < 32; count--) {
  487. if (put_user(*k++, &reg_window[pos++]))
  488. return -EFAULT;
  489. }
  490. } else {
  491. for (; count > 0 && pos < 32; count--) {
  492. if (access_process_vm(target,
  493. (unsigned long)
  494. &reg_window[pos],
  495. (void *) k,
  496. sizeof(*k), 1)
  497. != sizeof(*k))
  498. return -EFAULT;
  499. k++;
  500. pos++;
  501. }
  502. }
  503. } else {
  504. for (; count > 0 && pos < 16; count--) {
  505. if (get_user(reg, u++))
  506. return -EFAULT;
  507. regs->u_regs[pos++] = reg;
  508. }
  509. reg_window = (compat_ulong_t __user *) regs->u_regs[UREG_I6];
  510. if (target == current) {
  511. for (; count > 0 && pos < 32; count--) {
  512. if (get_user(reg, u++) ||
  513. put_user(reg, &reg_window[pos++]))
  514. return -EFAULT;
  515. }
  516. } else {
  517. for (; count > 0 && pos < 32; count--) {
  518. if (access_process_vm(target,
  519. (unsigned long)
  520. u,
  521. &reg, sizeof(reg), 0)
  522. != sizeof(reg))
  523. return -EFAULT;
  524. if (access_process_vm(target,
  525. (unsigned long)
  526. &reg_window[pos],
  527. &reg, sizeof(reg), 1)
  528. != sizeof(reg))
  529. return -EFAULT;
  530. pos++;
  531. u++;
  532. }
  533. }
  534. }
  535. while (count > 0) {
  536. unsigned long tstate;
  537. if (kbuf)
  538. reg = *k++;
  539. else if (get_user(reg, u++))
  540. return -EFAULT;
  541. switch (pos) {
  542. case 32: /* PSR */
  543. tstate = regs->tstate;
  544. tstate &= ~(TSTATE_ICC | TSTATE_XCC);
  545. tstate |= psr_to_tstate_icc(reg);
  546. regs->tstate = tstate;
  547. break;
  548. case 33: /* PC */
  549. regs->tpc = reg;
  550. break;
  551. case 34: /* NPC */
  552. regs->tnpc = reg;
  553. break;
  554. case 35: /* Y */
  555. regs->y = reg;
  556. break;
  557. case 36: /* WIM */
  558. case 37: /* TBR */
  559. break;
  560. default:
  561. goto finish;
  562. }
  563. pos++;
  564. count--;
  565. }
  566. finish:
  567. pos *= sizeof(reg);
  568. count *= sizeof(reg);
  569. return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  570. 38 * sizeof(reg), -1);
  571. }
  572. static int fpregs32_get(struct task_struct *target,
  573. const struct user_regset *regset,
  574. unsigned int pos, unsigned int count,
  575. void *kbuf, void __user *ubuf)
  576. {
  577. const unsigned long *fpregs = task_thread_info(target)->fpregs;
  578. compat_ulong_t enabled;
  579. unsigned long fprs;
  580. compat_ulong_t fsr;
  581. int ret = 0;
  582. if (target == current)
  583. save_and_clear_fpu();
  584. fprs = task_thread_info(target)->fpsaved[0];
  585. if (fprs & FPRS_FEF) {
  586. fsr = task_thread_info(target)->xfsr[0];
  587. enabled = 1;
  588. } else {
  589. fsr = 0;
  590. enabled = 0;
  591. }
  592. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  593. fpregs,
  594. 0, 32 * sizeof(u32));
  595. if (!ret)
  596. ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  597. 32 * sizeof(u32),
  598. 33 * sizeof(u32));
  599. if (!ret)
  600. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  601. &fsr,
  602. 33 * sizeof(u32),
  603. 34 * sizeof(u32));
  604. if (!ret) {
  605. compat_ulong_t val;
  606. val = (enabled << 8) | (8 << 16);
  607. ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
  608. &val,
  609. 34 * sizeof(u32),
  610. 35 * sizeof(u32));
  611. }
  612. if (!ret)
  613. ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
  614. 35 * sizeof(u32), -1);
  615. return ret;
  616. }
  617. static int fpregs32_set(struct task_struct *target,
  618. const struct user_regset *regset,
  619. unsigned int pos, unsigned int count,
  620. const void *kbuf, const void __user *ubuf)
  621. {
  622. unsigned long *fpregs = task_thread_info(target)->fpregs;
  623. unsigned long fprs;
  624. int ret;
  625. if (target == current)
  626. save_and_clear_fpu();
  627. fprs = task_thread_info(target)->fpsaved[0];
  628. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  629. fpregs,
  630. 0, 32 * sizeof(u32));
  631. if (!ret)
  632. user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  633. 32 * sizeof(u32),
  634. 33 * sizeof(u32));
  635. if (!ret && count > 0) {
  636. compat_ulong_t fsr;
  637. unsigned long val;
  638. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  639. &fsr,
  640. 33 * sizeof(u32),
  641. 34 * sizeof(u32));
  642. if (!ret) {
  643. val = task_thread_info(target)->xfsr[0];
  644. val &= 0xffffffff00000000UL;
  645. val |= fsr;
  646. task_thread_info(target)->xfsr[0] = val;
  647. }
  648. }
  649. fprs |= (FPRS_FEF | FPRS_DL);
  650. task_thread_info(target)->fpsaved[0] = fprs;
  651. if (!ret)
  652. ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  653. 34 * sizeof(u32), -1);
  654. return ret;
  655. }
  656. static const struct user_regset sparc32_regsets[] = {
  657. /* Format is:
  658. * G0 --> G7
  659. * O0 --> O7
  660. * L0 --> L7
  661. * I0 --> I7
  662. * PSR, PC, nPC, Y, WIM, TBR
  663. */
  664. [REGSET_GENERAL] = {
  665. .core_note_type = NT_PRSTATUS,
  666. .n = 38 * sizeof(u32),
  667. .size = sizeof(u32), .align = sizeof(u32),
  668. .get = genregs32_get, .set = genregs32_set
  669. },
  670. /* Format is:
  671. * F0 --> F31
  672. * empty 32-bit word
  673. * FSR (32--bit word)
  674. * FPU QUEUE COUNT (8-bit char)
  675. * FPU QUEUE ENTRYSIZE (8-bit char)
  676. * FPU ENABLED (8-bit char)
  677. * empty 8-bit char
  678. * FPU QUEUE (64 32-bit ints)
  679. */
  680. [REGSET_FP] = {
  681. .core_note_type = NT_PRFPREG,
  682. .n = 99 * sizeof(u32),
  683. .size = sizeof(u32), .align = sizeof(u32),
  684. .get = fpregs32_get, .set = fpregs32_set
  685. },
  686. };
  687. static const struct user_regset_view user_sparc32_view = {
  688. .name = "sparc", .e_machine = EM_SPARC,
  689. .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
  690. };
  691. #endif /* CONFIG_COMPAT */
  692. const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  693. {
  694. #ifdef CONFIG_COMPAT
  695. if (test_tsk_thread_flag(task, TIF_32BIT))
  696. return &user_sparc32_view;
  697. #endif
  698. return &user_sparc64_view;
  699. }
  700. #ifdef CONFIG_COMPAT
  701. struct compat_fps {
  702. unsigned int regs[32];
  703. unsigned int fsr;
  704. unsigned int flags;
  705. unsigned int extra;
  706. unsigned int fpqd;
  707. struct compat_fq {
  708. unsigned int insnaddr;
  709. unsigned int insn;
  710. } fpq[16];
  711. };
  712. long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
  713. compat_ulong_t caddr, compat_ulong_t cdata)
  714. {
  715. const struct user_regset_view *view = task_user_regset_view(child);
  716. compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4];
  717. struct pt_regs32 __user *pregs;
  718. struct compat_fps __user *fps;
  719. unsigned long addr2 = caddr2;
  720. unsigned long addr = caddr;
  721. unsigned long data = cdata;
  722. int ret;
  723. pregs = (struct pt_regs32 __user *) addr;
  724. fps = (struct compat_fps __user *) addr;
  725. switch (request) {
  726. case PTRACE_PEEKUSR:
  727. ret = (addr != 0) ? -EIO : 0;
  728. break;
  729. case PTRACE_GETREGS:
  730. ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  731. 32 * sizeof(u32),
  732. 4 * sizeof(u32),
  733. &pregs->psr);
  734. if (!ret)
  735. ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  736. 1 * sizeof(u32),
  737. 15 * sizeof(u32),
  738. &pregs->u_regs[0]);
  739. break;
  740. case PTRACE_SETREGS:
  741. ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  742. 32 * sizeof(u32),
  743. 4 * sizeof(u32),
  744. &pregs->psr);
  745. if (!ret)
  746. ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  747. 1 * sizeof(u32),
  748. 15 * sizeof(u32),
  749. &pregs->u_regs[0]);
  750. break;
  751. case PTRACE_GETFPREGS:
  752. ret = copy_regset_to_user(child, view, REGSET_FP,
  753. 0 * sizeof(u32),
  754. 32 * sizeof(u32),
  755. &fps->regs[0]);
  756. if (!ret)
  757. ret = copy_regset_to_user(child, view, REGSET_FP,
  758. 33 * sizeof(u32),
  759. 1 * sizeof(u32),
  760. &fps->fsr);
  761. if (!ret) {
  762. if (__put_user(0, &fps->flags) ||
  763. __put_user(0, &fps->extra) ||
  764. __put_user(0, &fps->fpqd) ||
  765. clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
  766. ret = -EFAULT;
  767. }
  768. break;
  769. case PTRACE_SETFPREGS:
  770. ret = copy_regset_from_user(child, view, REGSET_FP,
  771. 0 * sizeof(u32),
  772. 32 * sizeof(u32),
  773. &fps->regs[0]);
  774. if (!ret)
  775. ret = copy_regset_from_user(child, view, REGSET_FP,
  776. 33 * sizeof(u32),
  777. 1 * sizeof(u32),
  778. &fps->fsr);
  779. break;
  780. case PTRACE_READTEXT:
  781. case PTRACE_READDATA:
  782. ret = ptrace_readdata(child, addr,
  783. (char __user *)addr2, data);
  784. if (ret == data)
  785. ret = 0;
  786. else if (ret >= 0)
  787. ret = -EIO;
  788. break;
  789. case PTRACE_WRITETEXT:
  790. case PTRACE_WRITEDATA:
  791. ret = ptrace_writedata(child, (char __user *) addr2,
  792. addr, data);
  793. if (ret == data)
  794. ret = 0;
  795. else if (ret >= 0)
  796. ret = -EIO;
  797. break;
  798. default:
  799. ret = compat_ptrace_request(child, request, addr, data);
  800. break;
  801. }
  802. return ret;
  803. }
  804. #endif /* CONFIG_COMPAT */
  805. struct fps {
  806. unsigned int regs[64];
  807. unsigned long fsr;
  808. };
  809. long arch_ptrace(struct task_struct *child, long request, long addr, long data)
  810. {
  811. const struct user_regset_view *view = task_user_regset_view(child);
  812. unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
  813. struct pt_regs __user *pregs;
  814. struct fps __user *fps;
  815. int ret;
  816. pregs = (struct pt_regs __user *) (unsigned long) addr;
  817. fps = (struct fps __user *) (unsigned long) addr;
  818. switch (request) {
  819. case PTRACE_PEEKUSR:
  820. ret = (addr != 0) ? -EIO : 0;
  821. break;
  822. case PTRACE_GETREGS64:
  823. ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  824. 1 * sizeof(u64),
  825. 15 * sizeof(u64),
  826. &pregs->u_regs[0]);
  827. if (!ret) {
  828. /* XXX doesn't handle 'y' register correctly XXX */
  829. ret = copy_regset_to_user(child, view, REGSET_GENERAL,
  830. 32 * sizeof(u64),
  831. 4 * sizeof(u64),
  832. &pregs->tstate);
  833. }
  834. break;
  835. case PTRACE_SETREGS64:
  836. ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  837. 1 * sizeof(u64),
  838. 15 * sizeof(u64),
  839. &pregs->u_regs[0]);
  840. if (!ret) {
  841. /* XXX doesn't handle 'y' register correctly XXX */
  842. ret = copy_regset_from_user(child, view, REGSET_GENERAL,
  843. 32 * sizeof(u64),
  844. 4 * sizeof(u64),
  845. &pregs->tstate);
  846. }
  847. break;
  848. case PTRACE_GETFPREGS64:
  849. ret = copy_regset_to_user(child, view, REGSET_FP,
  850. 0 * sizeof(u64),
  851. 33 * sizeof(u64),
  852. fps);
  853. break;
  854. case PTRACE_SETFPREGS64:
  855. ret = copy_regset_to_user(child, view, REGSET_FP,
  856. 0 * sizeof(u64),
  857. 33 * sizeof(u64),
  858. fps);
  859. break;
  860. case PTRACE_READTEXT:
  861. case PTRACE_READDATA:
  862. ret = ptrace_readdata(child, addr,
  863. (char __user *)addr2, data);
  864. if (ret == data)
  865. ret = 0;
  866. else if (ret >= 0)
  867. ret = -EIO;
  868. break;
  869. case PTRACE_WRITETEXT:
  870. case PTRACE_WRITEDATA:
  871. ret = ptrace_writedata(child, (char __user *) addr2,
  872. addr, data);
  873. if (ret == data)
  874. ret = 0;
  875. else if (ret >= 0)
  876. ret = -EIO;
  877. break;
  878. default:
  879. ret = ptrace_request(child, request, addr, data);
  880. break;
  881. }
  882. return ret;
  883. }
  884. asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)
  885. {
  886. /* do the secure computing check first */
  887. secure_computing(regs->u_regs[UREG_G1]);
  888. if (unlikely(current->audit_context) && syscall_exit_p) {
  889. unsigned long tstate = regs->tstate;
  890. int result = AUDITSC_SUCCESS;
  891. if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
  892. result = AUDITSC_FAILURE;
  893. audit_syscall_exit(result, regs->u_regs[UREG_I0]);
  894. }
  895. if (!(current->ptrace & PT_PTRACED))
  896. goto out;
  897. if (!test_thread_flag(TIF_SYSCALL_TRACE))
  898. goto out;
  899. ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
  900. ? 0x80 : 0));
  901. /*
  902. * this isn't the same as continuing with a signal, but it will do
  903. * for normal use. strace only continues with a signal if the
  904. * stopping signal is not SIGTRAP. -brl
  905. */
  906. if (current->exit_code) {
  907. send_sig(current->exit_code, current, 1);
  908. current->exit_code = 0;
  909. }
  910. out:
  911. if (unlikely(current->audit_context) && !syscall_exit_p)
  912. audit_syscall_entry((test_thread_flag(TIF_32BIT) ?
  913. AUDIT_ARCH_SPARC :
  914. AUDIT_ARCH_SPARC64),
  915. regs->u_regs[UREG_G1],
  916. regs->u_regs[UREG_I0],
  917. regs->u_regs[UREG_I1],
  918. regs->u_regs[UREG_I2],
  919. regs->u_regs[UREG_I3]);
  920. }