12ee0d7fdSJean Pihet #include <linux/errno.h> 22ee0d7fdSJean Pihet #include <linux/kernel.h> 32ee0d7fdSJean Pihet #include <linux/perf_event.h> 42ee0d7fdSJean Pihet #include <linux/bug.h> 5*68db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 6ff268ff7SMark Salter 7ff268ff7SMark Salter #include <asm/compat.h> 82ee0d7fdSJean Pihet #include <asm/perf_regs.h> 92ee0d7fdSJean Pihet #include <asm/ptrace.h> 102ee0d7fdSJean Pihet 112ee0d7fdSJean Pihet u64 perf_reg_value(struct pt_regs *regs, int idx) 122ee0d7fdSJean Pihet { 132ee0d7fdSJean Pihet if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX)) 142ee0d7fdSJean Pihet return 0; 152ee0d7fdSJean Pihet 162ee0d7fdSJean Pihet /* 172ee0d7fdSJean Pihet * Compat (i.e. 32 bit) mode: 182ee0d7fdSJean Pihet * - PC has been set in the pt_regs struct in kernel_entry, 192ee0d7fdSJean Pihet * - Handle SP and LR here. 202ee0d7fdSJean Pihet */ 212ee0d7fdSJean Pihet if (compat_user_mode(regs)) { 222ee0d7fdSJean Pihet if ((u32)idx == PERF_REG_ARM64_SP) 232ee0d7fdSJean Pihet return regs->compat_sp; 242ee0d7fdSJean Pihet if ((u32)idx == PERF_REG_ARM64_LR) 252ee0d7fdSJean Pihet return regs->compat_lr; 262ee0d7fdSJean Pihet } 272ee0d7fdSJean Pihet 285b75a6afSWill Deacon if ((u32)idx == PERF_REG_ARM64_SP) 295b75a6afSWill Deacon return regs->sp; 305b75a6afSWill Deacon 315b75a6afSWill Deacon if ((u32)idx == PERF_REG_ARM64_PC) 325b75a6afSWill Deacon return regs->pc; 335b75a6afSWill Deacon 342ee0d7fdSJean Pihet return regs->regs[idx]; 352ee0d7fdSJean Pihet } 362ee0d7fdSJean Pihet 372ee0d7fdSJean Pihet #define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1)) 382ee0d7fdSJean Pihet 392ee0d7fdSJean Pihet int perf_reg_validate(u64 mask) 402ee0d7fdSJean Pihet { 412ee0d7fdSJean Pihet if (!mask || mask & REG_RESERVED) 422ee0d7fdSJean Pihet return -EINVAL; 432ee0d7fdSJean Pihet 442ee0d7fdSJean Pihet return 0; 452ee0d7fdSJean Pihet } 462ee0d7fdSJean Pihet 472ee0d7fdSJean Pihet u64 perf_reg_abi(struct task_struct *task) 482ee0d7fdSJean Pihet { 492ee0d7fdSJean Pihet if (is_compat_thread(task_thread_info(task))) 502ee0d7fdSJean Pihet return PERF_SAMPLE_REGS_ABI_32; 512ee0d7fdSJean Pihet else 522ee0d7fdSJean Pihet return PERF_SAMPLE_REGS_ABI_64; 532ee0d7fdSJean Pihet } 5488a7c26aSAndy Lutomirski 5588a7c26aSAndy Lutomirski void perf_get_regs_user(struct perf_regs *regs_user, 5688a7c26aSAndy Lutomirski struct pt_regs *regs, 5788a7c26aSAndy Lutomirski struct pt_regs *regs_user_copy) 5888a7c26aSAndy Lutomirski { 5988a7c26aSAndy Lutomirski regs_user->regs = task_pt_regs(current); 6088a7c26aSAndy Lutomirski regs_user->abi = perf_reg_abi(current); 6188a7c26aSAndy Lutomirski } 62