xref: /openbmc/linux/arch/arm64/kernel/perf_regs.c (revision 2ee0d7fd36a3f87bc5b29b1ec54ad6728deedb41)
1*2ee0d7fdSJean Pihet #include <linux/errno.h>
2*2ee0d7fdSJean Pihet #include <linux/kernel.h>
3*2ee0d7fdSJean Pihet #include <linux/perf_event.h>
4*2ee0d7fdSJean Pihet #include <linux/bug.h>
5*2ee0d7fdSJean Pihet #include <asm/perf_regs.h>
6*2ee0d7fdSJean Pihet #include <asm/ptrace.h>
7*2ee0d7fdSJean Pihet 
8*2ee0d7fdSJean Pihet u64 perf_reg_value(struct pt_regs *regs, int idx)
9*2ee0d7fdSJean Pihet {
10*2ee0d7fdSJean Pihet 	if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX))
11*2ee0d7fdSJean Pihet 		return 0;
12*2ee0d7fdSJean Pihet 
13*2ee0d7fdSJean Pihet 	/*
14*2ee0d7fdSJean Pihet 	 * Compat (i.e. 32 bit) mode:
15*2ee0d7fdSJean Pihet 	 * - PC has been set in the pt_regs struct in kernel_entry,
16*2ee0d7fdSJean Pihet 	 * - Handle SP and LR here.
17*2ee0d7fdSJean Pihet 	 */
18*2ee0d7fdSJean Pihet 	if (compat_user_mode(regs)) {
19*2ee0d7fdSJean Pihet 		if ((u32)idx == PERF_REG_ARM64_SP)
20*2ee0d7fdSJean Pihet 			return regs->compat_sp;
21*2ee0d7fdSJean Pihet 		if ((u32)idx == PERF_REG_ARM64_LR)
22*2ee0d7fdSJean Pihet 			return regs->compat_lr;
23*2ee0d7fdSJean Pihet 	}
24*2ee0d7fdSJean Pihet 
25*2ee0d7fdSJean Pihet 	return regs->regs[idx];
26*2ee0d7fdSJean Pihet }
27*2ee0d7fdSJean Pihet 
28*2ee0d7fdSJean Pihet #define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1))
29*2ee0d7fdSJean Pihet 
30*2ee0d7fdSJean Pihet int perf_reg_validate(u64 mask)
31*2ee0d7fdSJean Pihet {
32*2ee0d7fdSJean Pihet 	if (!mask || mask & REG_RESERVED)
33*2ee0d7fdSJean Pihet 		return -EINVAL;
34*2ee0d7fdSJean Pihet 
35*2ee0d7fdSJean Pihet 	return 0;
36*2ee0d7fdSJean Pihet }
37*2ee0d7fdSJean Pihet 
38*2ee0d7fdSJean Pihet u64 perf_reg_abi(struct task_struct *task)
39*2ee0d7fdSJean Pihet {
40*2ee0d7fdSJean Pihet 	if (is_compat_thread(task_thread_info(task)))
41*2ee0d7fdSJean Pihet 		return PERF_SAMPLE_REGS_ABI_32;
42*2ee0d7fdSJean Pihet 	else
43*2ee0d7fdSJean Pihet 		return PERF_SAMPLE_REGS_ABI_64;
44*2ee0d7fdSJean Pihet }
45