cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ptrace-view.c (23667B)


      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		ret = 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		ret = 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	return membuf_write(&to, &target->thread.regs->ppr, sizeof(u64));
    294}
    295
    296static int ppr_set(struct task_struct *target, const struct user_regset *regset,
    297		   unsigned int pos, unsigned int count, const void *kbuf,
    298		   const void __user *ubuf)
    299{
    300	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    301				  &target->thread.regs->ppr, 0, sizeof(u64));
    302}
    303
    304static int dscr_get(struct task_struct *target, const struct user_regset *regset,
    305		    struct membuf to)
    306{
    307	return membuf_write(&to, &target->thread.dscr, sizeof(u64));
    308}
    309static int dscr_set(struct task_struct *target, const struct user_regset *regset,
    310		    unsigned int pos, unsigned int count, const void *kbuf,
    311		    const void __user *ubuf)
    312{
    313	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    314				  &target->thread.dscr, 0, sizeof(u64));
    315}
    316#endif
    317#ifdef CONFIG_PPC_BOOK3S_64
    318static int tar_get(struct task_struct *target, const struct user_regset *regset,
    319		   struct membuf to)
    320{
    321	return membuf_write(&to, &target->thread.tar, sizeof(u64));
    322}
    323static int tar_set(struct task_struct *target, const struct user_regset *regset,
    324		   unsigned int pos, unsigned int count, const void *kbuf,
    325		   const void __user *ubuf)
    326{
    327	return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    328				  &target->thread.tar, 0, sizeof(u64));
    329}
    330
    331static int ebb_active(struct task_struct *target, const struct user_regset *regset)
    332{
    333	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
    334		return -ENODEV;
    335
    336	if (target->thread.used_ebb)
    337		return regset->n;
    338
    339	return 0;
    340}
    341
    342static int ebb_get(struct task_struct *target, const struct user_regset *regset,
    343		   struct membuf to)
    344{
    345	/* Build tests */
    346	BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
    347	BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
    348
    349	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
    350		return -ENODEV;
    351
    352	if (!target->thread.used_ebb)
    353		return -ENODATA;
    354
    355	return membuf_write(&to, &target->thread.ebbrr, 3 * sizeof(unsigned long));
    356}
    357
    358static int ebb_set(struct task_struct *target, const struct user_regset *regset,
    359		   unsigned int pos, unsigned int count, const void *kbuf,
    360		   const void __user *ubuf)
    361{
    362	int ret = 0;
    363
    364	/* Build tests */
    365	BUILD_BUG_ON(TSO(ebbrr) + sizeof(unsigned long) != TSO(ebbhr));
    366	BUILD_BUG_ON(TSO(ebbhr) + sizeof(unsigned long) != TSO(bescr));
    367
    368	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
    369		return -ENODEV;
    370
    371	if (target->thread.used_ebb)
    372		return -ENODATA;
    373
    374	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.ebbrr,
    375				 0, sizeof(unsigned long));
    376
    377	if (!ret)
    378		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    379					 &target->thread.ebbhr, sizeof(unsigned long),
    380					 2 * sizeof(unsigned long));
    381
    382	if (!ret)
    383		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    384					 &target->thread.bescr, 2 * sizeof(unsigned long),
    385					 3 * sizeof(unsigned long));
    386
    387	return ret;
    388}
    389static int pmu_active(struct task_struct *target, const struct user_regset *regset)
    390{
    391	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
    392		return -ENODEV;
    393
    394	return regset->n;
    395}
    396
    397static int pmu_get(struct task_struct *target, const struct user_regset *regset,
    398		   struct membuf to)
    399{
    400	/* Build tests */
    401	BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
    402	BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
    403	BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
    404	BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
    405
    406	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
    407		return -ENODEV;
    408
    409	return membuf_write(&to, &target->thread.siar, 5 * sizeof(unsigned long));
    410}
    411
    412static int pmu_set(struct task_struct *target, const struct user_regset *regset,
    413		   unsigned int pos, unsigned int count, const void *kbuf,
    414		   const void __user *ubuf)
    415{
    416	int ret = 0;
    417
    418	/* Build tests */
    419	BUILD_BUG_ON(TSO(siar) + sizeof(unsigned long) != TSO(sdar));
    420	BUILD_BUG_ON(TSO(sdar) + sizeof(unsigned long) != TSO(sier));
    421	BUILD_BUG_ON(TSO(sier) + sizeof(unsigned long) != TSO(mmcr2));
    422	BUILD_BUG_ON(TSO(mmcr2) + sizeof(unsigned long) != TSO(mmcr0));
    423
    424	if (!cpu_has_feature(CPU_FTR_ARCH_207S))
    425		return -ENODEV;
    426
    427	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.siar,
    428				 0, sizeof(unsigned long));
    429
    430	if (!ret)
    431		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    432					 &target->thread.sdar, sizeof(unsigned long),
    433					 2 * sizeof(unsigned long));
    434
    435	if (!ret)
    436		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    437					 &target->thread.sier, 2 * sizeof(unsigned long),
    438					 3 * sizeof(unsigned long));
    439
    440	if (!ret)
    441		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    442					 &target->thread.mmcr2, 3 * sizeof(unsigned long),
    443					 4 * sizeof(unsigned long));
    444
    445	if (!ret)
    446		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    447					 &target->thread.mmcr0, 4 * sizeof(unsigned long),
    448					 5 * sizeof(unsigned long));
    449	return ret;
    450}
    451#endif
    452
    453#ifdef CONFIG_PPC_MEM_KEYS
    454static int pkey_active(struct task_struct *target, const struct user_regset *regset)
    455{
    456	if (!arch_pkeys_enabled())
    457		return -ENODEV;
    458
    459	return regset->n;
    460}
    461
    462static int pkey_get(struct task_struct *target, const struct user_regset *regset,
    463		    struct membuf to)
    464{
    465
    466	if (!arch_pkeys_enabled())
    467		return -ENODEV;
    468
    469	membuf_store(&to, target->thread.regs->amr);
    470	membuf_store(&to, target->thread.regs->iamr);
    471	return membuf_store(&to, default_uamor);
    472}
    473
    474static int pkey_set(struct task_struct *target, const struct user_regset *regset,
    475		    unsigned int pos, unsigned int count, const void *kbuf,
    476		    const void __user *ubuf)
    477{
    478	u64 new_amr;
    479	int ret;
    480
    481	if (!arch_pkeys_enabled())
    482		return -ENODEV;
    483
    484	/* Only the AMR can be set from userspace */
    485	if (pos != 0 || count != sizeof(new_amr))
    486		return -EINVAL;
    487
    488	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
    489				 &new_amr, 0, sizeof(new_amr));
    490	if (ret)
    491		return ret;
    492
    493	/*
    494	 * UAMOR determines which bits of the AMR can be set from userspace.
    495	 * UAMOR value 0b11 indicates that the AMR value can be modified
    496	 * from userspace. If the kernel is using a specific key, we avoid
    497	 * userspace modifying the AMR value for that key by masking them
    498	 * via UAMOR 0b00.
    499	 *
    500	 * Pick the AMR values for the keys that kernel is using. This
    501	 * will be indicated by the ~default_uamor bits.
    502	 */
    503	target->thread.regs->amr = (new_amr & default_uamor) |
    504		(target->thread.regs->amr & ~default_uamor);
    505
    506	return 0;
    507}
    508#endif /* CONFIG_PPC_MEM_KEYS */
    509
    510static const struct user_regset native_regsets[] = {
    511	[REGSET_GPR] = {
    512		.core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
    513		.size = sizeof(long), .align = sizeof(long),
    514		.regset_get = gpr_get, .set = gpr_set
    515	},
    516	[REGSET_FPR] = {
    517		.core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
    518		.size = sizeof(double), .align = sizeof(double),
    519		.regset_get = fpr_get, .set = fpr_set
    520	},
    521#ifdef CONFIG_ALTIVEC
    522	[REGSET_VMX] = {
    523		.core_note_type = NT_PPC_VMX, .n = 34,
    524		.size = sizeof(vector128), .align = sizeof(vector128),
    525		.active = vr_active, .regset_get = vr_get, .set = vr_set
    526	},
    527#endif
    528#ifdef CONFIG_VSX
    529	[REGSET_VSX] = {
    530		.core_note_type = NT_PPC_VSX, .n = 32,
    531		.size = sizeof(double), .align = sizeof(double),
    532		.active = vsr_active, .regset_get = vsr_get, .set = vsr_set
    533	},
    534#endif
    535#ifdef CONFIG_SPE
    536	[REGSET_SPE] = {
    537		.core_note_type = NT_PPC_SPE, .n = 35,
    538		.size = sizeof(u32), .align = sizeof(u32),
    539		.active = evr_active, .regset_get = evr_get, .set = evr_set
    540	},
    541#endif
    542#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
    543	[REGSET_TM_CGPR] = {
    544		.core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
    545		.size = sizeof(long), .align = sizeof(long),
    546		.active = tm_cgpr_active, .regset_get = tm_cgpr_get, .set = tm_cgpr_set
    547	},
    548	[REGSET_TM_CFPR] = {
    549		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
    550		.size = sizeof(double), .align = sizeof(double),
    551		.active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set
    552	},
    553	[REGSET_TM_CVMX] = {
    554		.core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
    555		.size = sizeof(vector128), .align = sizeof(vector128),
    556		.active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set
    557	},
    558	[REGSET_TM_CVSX] = {
    559		.core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
    560		.size = sizeof(double), .align = sizeof(double),
    561		.active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set
    562	},
    563	[REGSET_TM_SPR] = {
    564		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
    565		.size = sizeof(u64), .align = sizeof(u64),
    566		.active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set
    567	},
    568	[REGSET_TM_CTAR] = {
    569		.core_note_type = NT_PPC_TM_CTAR, .n = 1,
    570		.size = sizeof(u64), .align = sizeof(u64),
    571		.active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set
    572	},
    573	[REGSET_TM_CPPR] = {
    574		.core_note_type = NT_PPC_TM_CPPR, .n = 1,
    575		.size = sizeof(u64), .align = sizeof(u64),
    576		.active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set
    577	},
    578	[REGSET_TM_CDSCR] = {
    579		.core_note_type = NT_PPC_TM_CDSCR, .n = 1,
    580		.size = sizeof(u64), .align = sizeof(u64),
    581		.active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set
    582	},
    583#endif
    584#ifdef CONFIG_PPC64
    585	[REGSET_PPR] = {
    586		.core_note_type = NT_PPC_PPR, .n = 1,
    587		.size = sizeof(u64), .align = sizeof(u64),
    588		.regset_get = ppr_get, .set = ppr_set
    589	},
    590	[REGSET_DSCR] = {
    591		.core_note_type = NT_PPC_DSCR, .n = 1,
    592		.size = sizeof(u64), .align = sizeof(u64),
    593		.regset_get = dscr_get, .set = dscr_set
    594	},
    595#endif
    596#ifdef CONFIG_PPC_BOOK3S_64
    597	[REGSET_TAR] = {
    598		.core_note_type = NT_PPC_TAR, .n = 1,
    599		.size = sizeof(u64), .align = sizeof(u64),
    600		.regset_get = tar_get, .set = tar_set
    601	},
    602	[REGSET_EBB] = {
    603		.core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
    604		.size = sizeof(u64), .align = sizeof(u64),
    605		.active = ebb_active, .regset_get = ebb_get, .set = ebb_set
    606	},
    607	[REGSET_PMR] = {
    608		.core_note_type = NT_PPC_PMU, .n = ELF_NPMU,
    609		.size = sizeof(u64), .align = sizeof(u64),
    610		.active = pmu_active, .regset_get = pmu_get, .set = pmu_set
    611	},
    612#endif
    613#ifdef CONFIG_PPC_MEM_KEYS
    614	[REGSET_PKEY] = {
    615		.core_note_type = NT_PPC_PKEY, .n = ELF_NPKEY,
    616		.size = sizeof(u64), .align = sizeof(u64),
    617		.active = pkey_active, .regset_get = pkey_get, .set = pkey_set
    618	},
    619#endif
    620};
    621
    622const struct user_regset_view user_ppc_native_view = {
    623	.name = UTS_MACHINE, .e_machine = ELF_ARCH, .ei_osabi = ELF_OSABI,
    624	.regsets = native_regsets, .n = ARRAY_SIZE(native_regsets)
    625};
    626
    627#include <linux/compat.h>
    628
    629int gpr32_get_common(struct task_struct *target,
    630		     const struct user_regset *regset,
    631		     struct membuf to, unsigned long *regs)
    632{
    633	int i;
    634
    635	for (i = 0; i < PT_MSR; i++)
    636		membuf_store(&to, (u32)regs[i]);
    637	membuf_store(&to, (u32)get_user_msr(target));
    638	for (i++ ; i < PT_REGS_COUNT; i++)
    639		membuf_store(&to, (u32)regs[i]);
    640	return membuf_zero(&to, (ELF_NGREG - PT_REGS_COUNT) * sizeof(u32));
    641}
    642
    643int gpr32_set_common(struct task_struct *target,
    644		     const struct user_regset *regset,
    645		     unsigned int pos, unsigned int count,
    646		     const void *kbuf, const void __user *ubuf,
    647		     unsigned long *regs)
    648{
    649	const compat_ulong_t *k = kbuf;
    650	const compat_ulong_t __user *u = ubuf;
    651	compat_ulong_t reg;
    652
    653	if (!kbuf && !user_read_access_begin(u, count))
    654		return -EFAULT;
    655
    656	pos /= sizeof(reg);
    657	count /= sizeof(reg);
    658
    659	if (kbuf)
    660		for (; count > 0 && pos < PT_MSR; --count)
    661			regs[pos++] = *k++;
    662	else
    663		for (; count > 0 && pos < PT_MSR; --count) {
    664			unsafe_get_user(reg, u++, Efault);
    665			regs[pos++] = reg;
    666		}
    667
    668
    669	if (count > 0 && pos == PT_MSR) {
    670		if (kbuf)
    671			reg = *k++;
    672		else
    673			unsafe_get_user(reg, u++, Efault);
    674		set_user_msr(target, reg);
    675		++pos;
    676		--count;
    677	}
    678
    679	if (kbuf) {
    680		for (; count > 0 && pos <= PT_MAX_PUT_REG; --count)
    681			regs[pos++] = *k++;
    682		for (; count > 0 && pos < PT_TRAP; --count, ++pos)
    683			++k;
    684	} else {
    685		for (; count > 0 && pos <= PT_MAX_PUT_REG; --count) {
    686			unsafe_get_user(reg, u++, Efault);
    687			regs[pos++] = reg;
    688		}
    689		for (; count > 0 && pos < PT_TRAP; --count, ++pos)
    690			unsafe_get_user(reg, u++, Efault);
    691	}
    692
    693	if (count > 0 && pos == PT_TRAP) {
    694		if (kbuf)
    695			reg = *k++;
    696		else
    697			unsafe_get_user(reg, u++, Efault);
    698		set_user_trap(target, reg);
    699		++pos;
    700		--count;
    701	}
    702	if (!kbuf)
    703		user_read_access_end();
    704
    705	kbuf = k;
    706	ubuf = u;
    707	pos *= sizeof(reg);
    708	count *= sizeof(reg);
    709	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
    710					 (PT_TRAP + 1) * sizeof(reg), -1);
    711
    712Efault:
    713	user_read_access_end();
    714	return -EFAULT;
    715}
    716
    717static int gpr32_get(struct task_struct *target,
    718		     const struct user_regset *regset,
    719		     struct membuf to)
    720{
    721	if (target->thread.regs == NULL)
    722		return -EIO;
    723
    724	return gpr32_get_common(target, regset, to,
    725			&target->thread.regs->gpr[0]);
    726}
    727
    728static int gpr32_set(struct task_struct *target,
    729		     const struct user_regset *regset,
    730		     unsigned int pos, unsigned int count,
    731		     const void *kbuf, const void __user *ubuf)
    732{
    733	if (target->thread.regs == NULL)
    734		return -EIO;
    735
    736	return gpr32_set_common(target, regset, pos, count, kbuf, ubuf,
    737			&target->thread.regs->gpr[0]);
    738}
    739
    740/*
    741 * These are the regset flavors matching the CONFIG_PPC32 native set.
    742 */
    743static const struct user_regset compat_regsets[] = {
    744	[REGSET_GPR] = {
    745		.core_note_type = NT_PRSTATUS, .n = ELF_NGREG,
    746		.size = sizeof(compat_long_t), .align = sizeof(compat_long_t),
    747		.regset_get = gpr32_get, .set = gpr32_set
    748	},
    749	[REGSET_FPR] = {
    750		.core_note_type = NT_PRFPREG, .n = ELF_NFPREG,
    751		.size = sizeof(double), .align = sizeof(double),
    752		.regset_get = fpr_get, .set = fpr_set
    753	},
    754#ifdef CONFIG_ALTIVEC
    755	[REGSET_VMX] = {
    756		.core_note_type = NT_PPC_VMX, .n = 34,
    757		.size = sizeof(vector128), .align = sizeof(vector128),
    758		.active = vr_active, .regset_get = vr_get, .set = vr_set
    759	},
    760#endif
    761#ifdef CONFIG_SPE
    762	[REGSET_SPE] = {
    763		.core_note_type = NT_PPC_SPE, .n = 35,
    764		.size = sizeof(u32), .align = sizeof(u32),
    765		.active = evr_active, .regset_get = evr_get, .set = evr_set
    766	},
    767#endif
    768#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
    769	[REGSET_TM_CGPR] = {
    770		.core_note_type = NT_PPC_TM_CGPR, .n = ELF_NGREG,
    771		.size = sizeof(long), .align = sizeof(long),
    772		.active = tm_cgpr_active,
    773		.regset_get = tm_cgpr32_get, .set = tm_cgpr32_set
    774	},
    775	[REGSET_TM_CFPR] = {
    776		.core_note_type = NT_PPC_TM_CFPR, .n = ELF_NFPREG,
    777		.size = sizeof(double), .align = sizeof(double),
    778		.active = tm_cfpr_active, .regset_get = tm_cfpr_get, .set = tm_cfpr_set
    779	},
    780	[REGSET_TM_CVMX] = {
    781		.core_note_type = NT_PPC_TM_CVMX, .n = ELF_NVMX,
    782		.size = sizeof(vector128), .align = sizeof(vector128),
    783		.active = tm_cvmx_active, .regset_get = tm_cvmx_get, .set = tm_cvmx_set
    784	},
    785	[REGSET_TM_CVSX] = {
    786		.core_note_type = NT_PPC_TM_CVSX, .n = ELF_NVSX,
    787		.size = sizeof(double), .align = sizeof(double),
    788		.active = tm_cvsx_active, .regset_get = tm_cvsx_get, .set = tm_cvsx_set
    789	},
    790	[REGSET_TM_SPR] = {
    791		.core_note_type = NT_PPC_TM_SPR, .n = ELF_NTMSPRREG,
    792		.size = sizeof(u64), .align = sizeof(u64),
    793		.active = tm_spr_active, .regset_get = tm_spr_get, .set = tm_spr_set
    794	},
    795	[REGSET_TM_CTAR] = {
    796		.core_note_type = NT_PPC_TM_CTAR, .n = 1,
    797		.size = sizeof(u64), .align = sizeof(u64),
    798		.active = tm_tar_active, .regset_get = tm_tar_get, .set = tm_tar_set
    799	},
    800	[REGSET_TM_CPPR] = {
    801		.core_note_type = NT_PPC_TM_CPPR, .n = 1,
    802		.size = sizeof(u64), .align = sizeof(u64),
    803		.active = tm_ppr_active, .regset_get = tm_ppr_get, .set = tm_ppr_set
    804	},
    805	[REGSET_TM_CDSCR] = {
    806		.core_note_type = NT_PPC_TM_CDSCR, .n = 1,
    807		.size = sizeof(u64), .align = sizeof(u64),
    808		.active = tm_dscr_active, .regset_get = tm_dscr_get, .set = tm_dscr_set
    809	},
    810#endif
    811#ifdef CONFIG_PPC64
    812	[REGSET_PPR] = {
    813		.core_note_type = NT_PPC_PPR, .n = 1,
    814		.size = sizeof(u64), .align = sizeof(u64),
    815		.regset_get = ppr_get, .set = ppr_set
    816	},
    817	[REGSET_DSCR] = {
    818		.core_note_type = NT_PPC_DSCR, .n = 1,
    819		.size = sizeof(u64), .align = sizeof(u64),
    820		.regset_get = dscr_get, .set = dscr_set
    821	},
    822#endif
    823#ifdef CONFIG_PPC_BOOK3S_64
    824	[REGSET_TAR] = {
    825		.core_note_type = NT_PPC_TAR, .n = 1,
    826		.size = sizeof(u64), .align = sizeof(u64),
    827		.regset_get = tar_get, .set = tar_set
    828	},
    829	[REGSET_EBB] = {
    830		.core_note_type = NT_PPC_EBB, .n = ELF_NEBB,
    831		.size = sizeof(u64), .align = sizeof(u64),
    832		.active = ebb_active, .regset_get = ebb_get, .set = ebb_set
    833	},
    834#endif
    835};
    836
    837static const struct user_regset_view user_ppc_compat_view = {
    838	.name = "ppc", .e_machine = EM_PPC, .ei_osabi = ELF_OSABI,
    839	.regsets = compat_regsets, .n = ARRAY_SIZE(compat_regsets)
    840};
    841
    842const struct user_regset_view *task_user_regset_view(struct task_struct *task)
    843{
    844	if (IS_ENABLED(CONFIG_COMPAT) && is_tsk_32bit_task(task))
    845		return &user_ppc_compat_view;
    846	return &user_ppc_native_view;
    847}