1 #include <linux/errno.h> 2 #include <linux/kernel.h> 3 #include <linux/perf_event.h> 4 #include <linux/bug.h> 5 #include <linux/sched/task_stack.h> 6 7 #include <asm/compat.h> 8 #include <asm/perf_regs.h> 9 #include <asm/ptrace.h> 10 11 u64 perf_reg_value(struct pt_regs *regs, int idx) 12 { 13 if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX)) 14 return 0; 15 16 /* 17 * Compat (i.e. 32 bit) mode: 18 * - PC has been set in the pt_regs struct in kernel_entry, 19 * - Handle SP and LR here. 20 */ 21 if (compat_user_mode(regs)) { 22 if ((u32)idx == PERF_REG_ARM64_SP) 23 return regs->compat_sp; 24 if ((u32)idx == PERF_REG_ARM64_LR) 25 return regs->compat_lr; 26 } 27 28 if ((u32)idx == PERF_REG_ARM64_SP) 29 return regs->sp; 30 31 if ((u32)idx == PERF_REG_ARM64_PC) 32 return regs->pc; 33 34 return regs->regs[idx]; 35 } 36 37 #define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1)) 38 39 int perf_reg_validate(u64 mask) 40 { 41 if (!mask || mask & REG_RESERVED) 42 return -EINVAL; 43 44 return 0; 45 } 46 47 u64 perf_reg_abi(struct task_struct *task) 48 { 49 if (is_compat_thread(task_thread_info(task))) 50 return PERF_SAMPLE_REGS_ABI_32; 51 else 52 return PERF_SAMPLE_REGS_ABI_64; 53 } 54 55 void perf_get_regs_user(struct perf_regs *regs_user, 56 struct pt_regs *regs, 57 struct pt_regs *regs_user_copy) 58 { 59 regs_user->regs = task_pt_regs(current); 60 regs_user->abi = perf_reg_abi(current); 61 } 62