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