File Index
Files and directories
Sign in
FILE

ptrace-view.c

File preview with syntax highlighting.

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