ptrace-view.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. #include <linux/regset.h>
  3. #include <linux/elf.h>
  4. #include <linux/nospec.h>
  5. #include <linux/pkeys.h>
  6. #include "ptrace-decl.h"
  7. struct pt_regs_offset {
  8. const char *name;
  9. int offset;
  10. };
  11. #define STR(s) #s /* convert to string */
  12. #define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
  13. #define GPR_OFFSET_NAME(num) \
  14. {.name = STR(r##num), .offset = offsetof(struct pt_regs, gpr[num])}, \
  15. {.name = STR(gpr##num), .offset = offsetof(struct pt_regs, gpr[num])}
  16. #define REG_OFFSET_END {.name = NULL, .offset = 0}
  17. static const struct pt_regs_offset regoffset_table[] = {
  18. GPR_OFFSET_NAME(0),
  19. GPR_OFFSET_NAME(1),
  20. GPR_OFFSET_NAME(2),
  21. GPR_OFFSET_NAME(3),
  22. GPR_OFFSET_NAME(4),
  23. GPR_OFFSET_NAME(5),
  24. GPR_OFFSET_NAME(6),
  25. GPR_OFFSET_NAME(7),
  26. GPR_OFFSET_NAME(8),
  27. GPR_OFFSET_NAME(9),
  28. GPR_OFFSET_NAME(10),
  29. GPR_OFFSET_NAME(11),
  30. GPR_OFFSET_NAME(12),
  31. GPR_OFFSET_NAME(13),
  32. GPR_OFFSET_NAME(14),
  33. GPR_OFFSET_NAME(15),
  34. GPR_OFFSET_NAME(16),
  35. GPR_OFFSET_NAME(17),
  36. GPR_OFFSET_NAME(18),
  37. GPR_OFFSET_NAME(19),
  38. GPR_OFFSET_NAME(20),
  39. GPR_OFFSET_NAME(21),
  40. GPR_OFFSET_NAME(22),
  41. GPR_OFFSET_NAME(23),
  42. GPR_OFFSET_NAME(24),
  43. GPR_OFFSET_NAME(25),
  44. GPR_OFFSET_NAME(26),
  45. GPR_OFFSET_NAME(27),
  46. GPR_OFFSET_NAME(28),
  47. GPR_OFFSET_NAME(29),
  48. GPR_OFFSET_NAME(30),
  49. GPR_OFFSET_NAME(31),
  50. REG_OFFSET_NAME(nip),
  51. REG_OFFSET_NAME(msr),
  52. REG_OFFSET_NAME(ctr),
  53. REG_OFFSET_NAME(link),
  54. REG_OFFSET_NAME(xer),
  55. REG_OFFSET_NAME(ccr),
  56. #ifdef CONFIG_PPC64
  57. REG_OFFSET_NAME(softe),
  58. #else
  59. REG_OFFSET_NAME(mq),
  60. #endif
  61. REG_OFFSET_NAME(trap),
  62. REG_OFFSET_NAME(dar),
  63. REG_OFFSET_NAME(dsisr),
  64. REG_OFFSET_END,
  65. };
  66. /**
  67. * regs_query_register_offset() - query register offset from its name
  68. * @name: the name of a register
  69. *
  70. * regs_query_register_offset() returns the offset of a register in struct
  71. * pt_regs from its name. If the name is invalid, this returns -EINVAL;
  72. */
  73. int regs_query_register_offset(const char *name)
  74. {
  75. const struct pt_regs_offset *roff;
  76. for (roff = regoffset_table; roff->name != NULL; roff++)
  77. if (!strcmp(roff->name, name))
  78. return roff->offset;
  79. return -EINVAL;
  80. }
  81. /**
  82. * regs_query_register_name() - query register name from its offset
  83. * @offset: the offset of a register in struct pt_regs.
  84. *
  85. * regs_query_register_name() returns the name of a register from its
  86. * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
  87. */
  88. const char *regs_query_register_name(unsigned int offset)
  89. {
  90. const struct pt_regs_offset *roff;
  91. for (roff = regoffset_table; roff->name != NULL; roff++)
  92. if (roff->offset == offset)
  93. return roff->name;
  94. return NULL;
  95. }
  96. /*
  97. * does not yet catch signals sent when the child dies.
  98. * in exit.c or in signal.c.
  99. */
  100. static unsigned long get_user_msr(struct task_struct *task)
  101. {
  102. return task->thread.regs->msr | task->thread.fpexc_mode;
  103. }
  104. static __always_inline int set_user_msr(struct task_struct *task, unsigned long msr)
  105. {
  106. unsigned long newmsr = (task->thread.regs->msr & ~MSR_DEBUGCHANGE) |
  107. (msr & MSR_DEBUGCHANGE);
  108. regs_set_return_msr(task->thread.regs, newmsr);
  109. return 0;
  110. }
  111. #ifdef CONFIG_PPC64
  112. static int get_user_dscr(struct task_struct *task, unsigned long *data)
  113. {
  114. *data = task->thread.dscr;
  115. return 0;
  116. }
  117. static int set_user_dscr(struct task_struct *task, unsigned long dscr)
  118. {
  119. task->thread.dscr = dscr;
  120. task->thread.dscr_inherit = 1;
  121. return 0;
  122. }
  123. #else
  124. static int get_user_dscr(struct task_struct *task, unsigned long *data)
  125. {
  126. return -EIO;
  127. }
  128. static int set_user_dscr(struct task_struct *task, unsigned long dscr)
  129. {
  130. return -EIO;
  131. }
  132. #endif
  133. /*
  134. * We prevent mucking around with the reserved area of trap
  135. * which are used internally by the kernel.
  136. */
  137. static __always_inline int set_user_trap(struct task_struct *task, unsigned long trap)
  138. {
  139. set_trap(task->thread.regs, trap);
  140. return 0;
  141. }
  142. /*
  143. * Get contents of register REGNO in task TASK.
  144. */
  145. int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
  146. {
  147. unsigned int regs_max;
  148. if (task->thread.regs == NULL || !data)
  149. return -EIO;
  150. if (regno == PT_MSR) {
  151. *data = get_user_msr(task);
  152. return 0;
  153. }
  154. if (regno == PT_DSCR)
  155. return get_user_dscr(task, data);
  156. /*
  157. * softe copies paca->irq_soft_mask variable state. Since irq_soft_mask is
  158. * no more used as a flag, lets force usr to always see the softe value as 1
  159. * which means interrupts are not soft disabled.
  160. */
  161. if (IS_ENABLED(CONFIG_PPC64) && regno == PT_SOFTE) {
  162. *data = 1;
  163. return 0;
  164. }
  165. regs_max = sizeof(struct user_pt_regs) / sizeof(unsigned long);
  166. if (regno < regs_max) {
  167. regno = array_index_nospec(regno, regs_max);
  168. *data = ((unsigned long *)task->thread.regs)[regno];
  169. return 0;
  170. }
  171. return -EIO;
  172. }
  173. /*
  174. * Write contents of register REGNO in task TASK.
  175. */
  176. int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data)
  177. {
  178. if (task->thread.regs == NULL)
  179. return -EIO;
  180. if (regno == PT_MSR)
  181. return set_user_msr(task, data);
  182. if (regno == PT_TRAP)
  183. return set_user_trap(task, data);
  184. if (regno == PT_DSCR)
  185. return set_user_dscr(task, data);
  186. if (regno <= PT_MAX_PUT_REG) {
  187. regno = array_index_nospec(regno, PT_MAX_PUT_REG + 1);
  188. ((unsigned long *)task->thread.regs)[regno] = data;
  189. return 0;
  190. }
  191. return -EIO;
  192. }
  193. static int gpr_get(struct task_struct *target, const struct user_regset *regset,
  194. struct membuf to)
  195. {
  196. struct membuf to_msr = membuf_at(&to, offsetof(struct pt_regs, msr));
  197. #ifdef CONFIG_PPC64
  198. struct membuf to_softe = membuf_at(&to, offsetof(struct pt_regs, softe));
  199. #endif
  200. if (target->thread.regs == NULL)
  201. return -EIO;
  202. membuf_write(&to, target->thread.regs, sizeof(struct user_pt_regs));
  203. membuf_store(&to_msr, get_user_msr(target));
  204. #ifdef CONFIG_PPC64
  205. membuf_store(&to_softe, 0x1ul);
  206. #endif
  207. return membuf_zero(&to, ELF_NGREG * sizeof(unsigned long) -
  208. sizeof(struct user_pt_regs));
  209. }
  210. static int gpr_set(struct task_struct *target, const struct user_regset *regset,
  211. unsigned int pos, unsigned int count, const void *kbuf,
  212. const void __user *ubuf)
  213. {
  214. unsigned long reg;
  215. int ret;
  216. if (target->thread.regs == NULL)
  217. return -EIO;
  218. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  219. target->thread.regs,
  220. 0, PT_MSR * sizeof(reg));
  221. if (!ret && count > 0) {
  222. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
  223. PT_MSR * sizeof(reg),
  224. (PT_MSR + 1) * sizeof(reg));
  225. if (!ret)
  226. ret = set_user_msr(target, reg);
  227. }
  228. BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) !=
  229. offsetof(struct pt_regs, msr) + sizeof(long));
  230. if (!ret)
  231. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  232. &target->thread.regs->orig_gpr3,
  233. PT_ORIG_R3 * sizeof(reg),
  234. (PT_MAX_PUT_REG + 1) * sizeof(reg));
  235. if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
  236. ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  237. (PT_MAX_PUT_REG + 1) * sizeof(reg),
  238. PT_TRAP * sizeof(reg));
  239. if (!ret && count > 0) {
  240. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
  241. PT_TRAP * sizeof(reg),
  242. (PT_TRAP + 1) * sizeof(reg));
  243. if (!ret)
  244. ret = set_user_trap(target, reg);
  245. }
  246. if (!ret)
  247. ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  248. (PT_TRAP + 1) * sizeof(reg), -1);
  249. return ret;
  250. }
  251. #ifdef CONFIG_PPC64
  252. static int ppr_get(struct task_struct *target, const struct user_regset *regset,
  253. struct membuf to)
  254. {
  255. if (!target->thread.regs)
  256. return -EINVAL;
  257. return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64));
  258. }
  259. static int ppr_set(struct task_struct *target, const struct user_regset *regset,
  260. unsigned int pos, unsigned int count, const void *kbuf,
  261. const void __user *ubuf)
  262. {
  263. if (!target->thread.regs)
  264. return -EINVAL;
  265. return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  266. &target->thread.regs->ppr, 0, sizeof(u64));
  267. }
  268. static int dscr_get(struct task_struct *target, const struct user_regset *regset,
  269. struct membuf to)
  270. {
  271. return membuf_write(&to, &target->thread.dscr, sizeof(u64));
  272. }
  273. static int dscr_set(struct task_struct *target, const struct user_regset *regset,
  274. unsigned int pos, unsigned int count, const void *kbuf,
  275. const void __user *ubuf)
  276. {
  277. return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  278. &target->thread.dscr, 0, sizeof(u64));
  279. }
  280. #endif
  281. #ifdef CONFIG_PPC_BOOK3S_64
  282. static int tar_get(struct task_struct *target, const struct user_regset *regset,
  283. struct membuf to)
  284. {
  285. return membuf_write(&to, &target->thread.tar, sizeof(u64));
  286. }
  287. static int tar_set(struct task_struct *target, const struct user_regset *regset,
  288. unsigned int pos, unsigned int count, const void *kbuf,
  289. const void __user *ubuf)
  290. {
  291. return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  292. &target->thread.tar, 0, sizeof(u64));
  293. }
  294. static int ebb_active(struct task_struct *target, const struct user_regset *regset)
  295. {
  296. if (!cpu_has_feature(CPU_FTR_ARCH_207S))
  297. return -ENODEV;
  298. if (target->thread.used_ebb)
  299. return regset->n;
  300. return 0;
  301. }
  302. static int ebb_get(struct task_struct *target, const struct user_regset *regset,
  303. struct membuf to)
  304. {
  305. /* Build tests */
  306. BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
  307. BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
  308. if (!cpu_has_feature(CPU_FTR_ARCH_207S))
  309. return -ENODEV;
  310. if (!target->thread.used_ebb)
  311. return -ENODATA;
  312. return membuf_write(&to, &target->thread.ebbrr, 3 * sizeof(unsigned long));
  313. }
  314. static int ebb_set(struct task_struct *target, const struct user_regset *regset,
  315. unsigned int pos, unsigned int count, const void *kbuf,
  316. const void __user *ubuf)
  317. {
  318. int ret = 0;
  319. /* Build tests */
  320. BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
  321. BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
  322. if (!cpu_has_feature(CPU_FTR_ARCH_207S))
  323. return -ENODEV;
  324. if (target->thread.used_ebb)
  325. return -ENODATA;
  326. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr,
  327. 0, sizeof(unsigned long));
  328. if (!ret)
  329. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  330. &target->thread.ebbhr, sizeof(unsigned long),
  331. 2 * sizeof(unsigned long));
  332. if (!ret)
  333. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  334. &target->thread.bescr, 2 * sizeof(unsigned long),
  335. 3 * sizeof(unsigned long));
  336. return ret;
  337. }
  338. static int pmu_active(struct task_struct *target, const struct user_regset *regset)
  339. {
  340. if (!cpu_has_feature(CPU_FTR_ARCH_207S))
  341. return -ENODEV;
  342. return regset->n;
  343. }
  344. static int pmu_get(struct task_struct *target, const struct user_regset *regset,
  345. struct membuf to)
  346. {
  347. /* Build tests */
  348. BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
  349. BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
  350. BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
  351. BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
  352. if (!cpu_has_feature(CPU_FTR_ARCH_207S))
  353. return -ENODEV;
  354. return membuf_write(&to, &target->thread.siar, 5 * sizeof(unsigned long));
  355. }
  356. static int pmu_set(struct task_struct *target, const struct user_regset *regset,
  357. unsigned int pos, unsigned int count, const void *kbuf,
  358. const void __user *ubuf)
  359. {
  360. int ret = 0;
  361. /* Build tests */
  362. BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
  363. BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
  364. BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
  365. BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
  366. if (!cpu_has_feature(CPU_FTR_ARCH_207S))
  367. return -ENODEV;
  368. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.siar,
  369. 0, sizeof(unsigned long));
  370. if (!ret)
  371. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  372. &target->thread.sdar, sizeof(unsigned long),
  373. 2 * sizeof(unsigned long));
  374. if (!ret)
  375. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  376. &target->thread.sier, 2 * sizeof(unsigned long),
  377. 3 * sizeof(unsigned long));
  378. if (!ret)
  379. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  380. &target->thread.mmcr2, 3 * sizeof(unsigned long),
  381. 4 * sizeof(unsigned long));
  382. if (!ret)
  383. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  384. &target->thread.mmcr0, 4 * sizeof(unsigned long),
  385. 5 * sizeof(unsigned long));
  386. return ret;
  387. }
  388. #endif
  389. #ifdef CONFIG_PPC_MEM_KEYS
  390. static int pkey_active(struct task_struct *target, const struct user_regset *regset)
  391. {
  392. if (!arch_pkeys_enabled())
  393. return -ENODEV;
  394. return regset->n;
  395. }
  396. static int pkey_get(struct task_struct *target, const struct user_regset *regset,
  397. struct membuf to)
  398. {
  399. if (!arch_pkeys_enabled())
  400. return -ENODEV;
  401. membuf_store(&to, target->thread.regs->amr);
  402. membuf_store(&to, target->thread.regs->iamr);
  403. return membuf_store(&to, default_uamor);
  404. }
  405. static int pkey_set(struct task_struct *target, const struct user_regset *regset,
  406. unsigned int pos, unsigned int count, const void *kbuf,
  407. const void __user *ubuf)
  408. {
  409. u64 new_amr;
  410. int ret;
  411. if (!arch_pkeys_enabled())
  412. return -ENODEV;
  413. /* Only the AMR can be set from userspace */
  414. if (pos != 0 || count != sizeof(new_amr))
  415. return -EINVAL;
  416. ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
  417. &new_amr, 0, sizeof(new_amr));
  418. if (ret)
  419. return ret;
  420. /*
  421. * UAMOR determines which bits of the AMR can be set from userspace.
  422. * UAMOR value 0b11 indicates that the AMR value can be modified
  423. * from userspace. If the kernel is using a specific key, we avoid
  424. * userspace modifying the AMR value for that key by masking them
  425. * via UAMOR 0b00.
  426. *
  427. * Pick the AMR values for the keys that kernel is using. This
  428. * will be indicated by the ~default_uamor bits.
  429. */
  430. target->thread.regs->amr = (new_amr & default_uamor) |
  431. (target->thread.regs->amr & ~default_uamor);
  432. return 0;
  433. }
  434. #endif /* CONFIG_PPC_MEM_KEYS */
  435. static const struct user_regset native_regsets[] = {
  436. [REGSET_GPR] = {
  437. .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
  438. .size = sizeof(long), .align = sizeof(long),
  439. .regset_get = gpr_get, .set = gpr_set
  440. },
  441. [REGSET_FPR] = {
  442. .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
  443. .size = sizeof(double), .align = sizeof(double),
  444. .regset_get = fpr_get, .set = fpr_set
  445. },
  446. #ifdef CONFIG_ALTIVEC
  447. [REGSET_VMX] = {
  448. .core_note_type = NT_PPC_VMX, .n = 34,
  449. .size = sizeof(vector128), .align = sizeof(vector128),
  450. .active = vr_active, .regset_get = vr_get, .set = vr_set
  451. },
  452. #endif
  453. #ifdef CONFIG_VSX
  454. [REGSET_VSX] = {
  455. .core_note_type = NT_PPC_VSX, .n = 32,
  456. .size = sizeof(double), .align = sizeof(double),
  457. .active = vsr_active, .regset_get = vsr_get, .set = vsr_set
  458. },
  459. #endif
  460. #ifdef CONFIG_SPE
  461. [REGSET_SPE] = {
  462. .core_note_type = NT_PPC_SPE, .n = 35,
  463. .size = sizeof(u32), .align = sizeof(u32),
  464. .active = evr_active, .regset_get = evr_get, .set = evr_set
  465. },
  466. #endif
  467. #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
  468. [REGSET_TM_CGPR] = {
  469. .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
  470. .size = sizeof(long), .align = sizeof(long),
  471. .active = tm_cgpr_active, .regset_get = tm_cgpr_get, .set = tm_cgpr_set
  472. },
  473. [REGSET_TM_CFPR] = {
  474. .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
  475. .size = sizeof(double), .align = sizeof(double),
  476. .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set
  477. },
  478. [REGSET_TM_CVMX] = {
  479. .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
  480. .size = sizeof(vector128), .align = sizeof(vector128),
  481. .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set
  482. },
  483. [REGSET_TM_CVSX] = {
  484. .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
  485. .size = sizeof(double), .align = sizeof(double),
  486. .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set
  487. },
  488. [REGSET_TM_SPR] = {
  489. .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
  490. .size = sizeof(u64), .align = sizeof(u64),
  491. .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set
  492. },
  493. [REGSET_TM_CTAR] = {
  494. .core_note_type = NT_PPC_TM_CTAR, .n = 1,
  495. .size = sizeof(u64), .align = sizeof(u64),
  496. .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set
  497. },
  498. [REGSET_TM_CPPR] = {
  499. .core_note_type = NT_PPC_TM_CPPR, .n = 1,
  500. .size = sizeof(u64), .align = sizeof(u64),
  501. .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set
  502. },
  503. [REGSET_TM_CDSCR] = {
  504. .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
  505. .size = sizeof(u64), .align = sizeof(u64),
  506. .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set
  507. },
  508. #endif
  509. #ifdef CONFIG_PPC64
  510. [REGSET_PPR] = {
  511. .core_note_type = NT_PPC_PPR, .n = 1,
  512. .size = sizeof(u64), .align = sizeof(u64),
  513. .regset_get = ppr_get, .set = ppr_set
  514. },
  515. [REGSET_DSCR] = {
  516. .core_note_type = NT_PPC_DSCR, .n = 1,
  517. .size = sizeof(u64), .align = sizeof(u64),
  518. .regset_get = dscr_get, .set = dscr_set
  519. },
  520. #endif
  521. #ifdef CONFIG_PPC_BOOK3S_64
  522. [REGSET_TAR] = {
  523. .core_note_type = NT_PPC_TAR, .n = 1,
  524. .size = sizeof(u64), .align = sizeof(u64),
  525. .regset_get = tar_get, .set = tar_set
  526. },
  527. [REGSET_EBB] = {
  528. .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
  529. .size = sizeof(u64), .align = sizeof(u64),
  530. .active = ebb_active, .regset_get = ebb_get, .set = ebb_set
  531. },
  532. [REGSET_PMR] = {
  533. .core_note_type = NT_PPC_PMU, .n = ELF_NPMU,
  534. .size = sizeof(u64), .align = sizeof(u64),
  535. .active = pmu_active, .regset_get = pmu_get, .set = pmu_set
  536. },
  537. #endif
  538. #ifdef CONFIG_PPC_MEM_KEYS
  539. [REGSET_PKEY] = {
  540. .core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY,
  541. .size = sizeof(u64), .align = sizeof(u64),
  542. .active = pkey_active, .regset_get = pkey_get, .set = pkey_set
  543. },
  544. #endif
  545. };
  546. const struct user_regset_view user_ppc_native_view = {
  547. .name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
  548. .regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
  549. };
  550. #include <linux/compat.h>
  551. int gpr32_get_common(struct task_struct *target,
  552. const struct user_regset *regset,
  553. struct membuf to, unsigned long *regs)
  554. {
  555. int i;
  556. for (i = 0; i < PT_MSR; i++)
  557. membuf_store(&to, (u32)regs[i]);
  558. membuf_store(&to, (u32)get_user_msr(target));
  559. for (i++ ; i < PT_REGS_COUNT; i++)
  560. membuf_store(&to, (u32)regs[i]);
  561. return membuf_zero(&to, (ELF_NGREG - PT_REGS_COUNT) * sizeof(u32));
  562. }
  563. int gpr32_set_common(struct task_struct *target,
  564. const struct user_regset *regset,
  565. unsigned int pos, unsigned int count,
  566. const void *kbuf, const void __user *ubuf,
  567. unsigned long *regs)
  568. {
  569. const compat_ulong_t *k = kbuf;
  570. const compat_ulong_t __user *u = ubuf;
  571. compat_ulong_t reg;
  572. if (!kbuf && !user_read_access_begin(u, count))
  573. return -EFAULT;
  574. pos /= sizeof(reg);
  575. count /= sizeof(reg);
  576. if (kbuf)
  577. for (; count > 0 && pos < PT_MSR; --count)
  578. regs[pos++] = *k++;
  579. else
  580. for (; count > 0 && pos < PT_MSR; --count) {
  581. unsafe_get_user(reg, u++, Efault);
  582. regs[pos++] = reg;
  583. }
  584. if (count > 0 && pos == PT_MSR) {
  585. if (kbuf)
  586. reg = *k++;
  587. else
  588. unsafe_get_user(reg, u++, Efault);
  589. set_user_msr(target, reg);
  590. ++pos;
  591. --count;
  592. }
  593. if (kbuf) {
  594. for (; count > 0 && pos <= PT_MAX_PUT_REG; --count)
  595. regs[pos++] = *k++;
  596. for (; count > 0 && pos < PT_TRAP; --count, ++pos)
  597. ++k;
  598. } else {
  599. for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
  600. unsafe_get_user(reg, u++, Efault);
  601. regs[pos++] = reg;
  602. }
  603. for (; count > 0 && pos < PT_TRAP; --count, ++pos)
  604. unsafe_get_user(reg, u++, Efault);
  605. }
  606. if (count > 0 && pos == PT_TRAP) {
  607. if (kbuf)
  608. reg = *k++;
  609. else
  610. unsafe_get_user(reg, u++, Efault);
  611. set_user_trap(target, reg);
  612. ++pos;
  613. --count;
  614. }
  615. if (!kbuf)
  616. user_read_access_end();
  617. kbuf = k;
  618. ubuf = u;
  619. pos *= sizeof(reg);
  620. count *= sizeof(reg);
  621. return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
  622. (PT_TRAP + 1) * sizeof(reg), -1);
  623. Efault:
  624. user_read_access_end();
  625. return -EFAULT;
  626. }
  627. static int gpr32_get(struct task_struct *target,
  628. const struct user_regset *regset,
  629. struct membuf to)
  630. {
  631. if (target->thread.regs == NULL)
  632. return -EIO;
  633. return gpr32_get_common(target, regset, to,
  634. &target->thread.regs->gpr[0]);
  635. }
  636. static int gpr32_set(struct task_struct *target,
  637. const struct user_regset *regset,
  638. unsigned int pos, unsigned int count,
  639. const void *kbuf, const void __user *ubuf)
  640. {
  641. if (target->thread.regs == NULL)
  642. return -EIO;
  643. return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
  644. &target->thread.regs->gpr[0]);
  645. }
  646. /*
  647. * These are the regset flavors matching the CONFIG_PPC32 native set.
  648. */
  649. static const struct user_regset compat_regsets[] = {
  650. [REGSET_GPR] = {
  651. .core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
  652. .size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
  653. .regset_get = gpr32_get, .set = gpr32_set
  654. },
  655. [REGSET_FPR] = {
  656. .core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
  657. .size = sizeof(double), .align = sizeof(double),
  658. .regset_get = fpr_get, .set = fpr_set
  659. },
  660. #ifdef CONFIG_ALTIVEC
  661. [REGSET_VMX] = {
  662. .core_note_type = NT_PPC_VMX, .n = 34,
  663. .size = sizeof(vector128), .align = sizeof(vector128),
  664. .active = vr_active, .regset_get = vr_get, .set = vr_set
  665. },
  666. #endif
  667. #ifdef CONFIG_SPE
  668. [REGSET_SPE] = {
  669. .core_note_type = NT_PPC_SPE, .n = 35,
  670. .size = sizeof(u32), .align = sizeof(u32),
  671. .active = evr_active, .regset_get = evr_get, .set = evr_set
  672. },
  673. #endif
  674. #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
  675. [REGSET_TM_CGPR] = {
  676. .core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
  677. .size = sizeof(long), .align = sizeof(long),
  678. .active = tm_cgpr_active,
  679. .regset_get = tm_cgpr32_get, .set = tm_cgpr32_set
  680. },
  681. [REGSET_TM_CFPR] = {
  682. .core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
  683. .size = sizeof(double), .align = sizeof(double),
  684. .active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set
  685. },
  686. [REGSET_TM_CVMX] = {
  687. .core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
  688. .size = sizeof(vector128), .align = sizeof(vector128),
  689. .active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set
  690. },
  691. [REGSET_TM_CVSX] = {
  692. .core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
  693. .size = sizeof(double), .align = sizeof(double),
  694. .active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set
  695. },
  696. [REGSET_TM_SPR] = {
  697. .core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
  698. .size = sizeof(u64), .align = sizeof(u64),
  699. .active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set
  700. },
  701. [REGSET_TM_CTAR] = {
  702. .core_note_type = NT_PPC_TM_CTAR, .n = 1,
  703. .size = sizeof(u64), .align = sizeof(u64),
  704. .active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set
  705. },
  706. [REGSET_TM_CPPR] = {
  707. .core_note_type = NT_PPC_TM_CPPR, .n = 1,
  708. .size = sizeof(u64), .align = sizeof(u64),
  709. .active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set
  710. },
  711. [REGSET_TM_CDSCR] = {
  712. .core_note_type = NT_PPC_TM_CDSCR, .n = 1,
  713. .size = sizeof(u64), .align = sizeof(u64),
  714. .active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set
  715. },
  716. #endif
  717. #ifdef CONFIG_PPC64
  718. [REGSET_PPR] = {
  719. .core_note_type = NT_PPC_PPR, .n = 1,
  720. .size = sizeof(u64), .align = sizeof(u64),
  721. .regset_get = ppr_get, .set = ppr_set
  722. },
  723. [REGSET_DSCR] = {
  724. .core_note_type = NT_PPC_DSCR, .n = 1,
  725. .size = sizeof(u64), .align = sizeof(u64),
  726. .regset_get = dscr_get, .set = dscr_set
  727. },
  728. #endif
  729. #ifdef CONFIG_PPC_BOOK3S_64
  730. [REGSET_TAR] = {
  731. .core_note_type = NT_PPC_TAR, .n = 1,
  732. .size = sizeof(u64), .align = sizeof(u64),
  733. .regset_get = tar_get, .set = tar_set
  734. },
  735. [REGSET_EBB] = {
  736. .core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
  737. .size = sizeof(u64), .align = sizeof(u64),
  738. .active = ebb_active, .regset_get = ebb_get, .set = ebb_set
  739. },
  740. #endif
  741. };
  742. static const struct user_regset_view user_ppc_compat_view = {
  743. .name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI,
  744. .regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets)
  745. };
  746. const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  747. {
  748. if (IS_ENABLED(CONFIG_COMPAT) && is_tsk_32bit_task(task))
  749. return &user_ppc_compat_view;
  750. return &user_ppc_native_view;
  751. }