xref: /openbmc/linux/arch/mips/kernel/perf_regs.c (revision 1ddc96bd)
1*1ddc96bdSTiezhu Yang // SPDX-License-Identifier: GPL-2.0
2*1ddc96bdSTiezhu Yang /*
3*1ddc96bdSTiezhu Yang  * This file is subject to the terms and conditions of the GNU General Public
4*1ddc96bdSTiezhu Yang  * License.  See the file "COPYING" in the main directory of this archive
5*1ddc96bdSTiezhu Yang  * for more details.
6*1ddc96bdSTiezhu Yang  *
7*1ddc96bdSTiezhu Yang  * Some parts derived from x86 version of this file.
8*1ddc96bdSTiezhu Yang  *
9*1ddc96bdSTiezhu Yang  * Copyright (C) 2013 Cavium, Inc.
10*1ddc96bdSTiezhu Yang  */
11*1ddc96bdSTiezhu Yang 
12*1ddc96bdSTiezhu Yang #include <linux/perf_event.h>
13*1ddc96bdSTiezhu Yang 
14*1ddc96bdSTiezhu Yang #include <asm/ptrace.h>
15*1ddc96bdSTiezhu Yang 
16*1ddc96bdSTiezhu Yang #ifdef CONFIG_32BIT
perf_reg_abi(struct task_struct * tsk)17*1ddc96bdSTiezhu Yang u64 perf_reg_abi(struct task_struct *tsk)
18*1ddc96bdSTiezhu Yang {
19*1ddc96bdSTiezhu Yang 	return PERF_SAMPLE_REGS_ABI_32;
20*1ddc96bdSTiezhu Yang }
21*1ddc96bdSTiezhu Yang #else /* Must be CONFIG_64BIT */
perf_reg_abi(struct task_struct * tsk)22*1ddc96bdSTiezhu Yang u64 perf_reg_abi(struct task_struct *tsk)
23*1ddc96bdSTiezhu Yang {
24*1ddc96bdSTiezhu Yang 	if (test_tsk_thread_flag(tsk, TIF_32BIT_REGS))
25*1ddc96bdSTiezhu Yang 		return PERF_SAMPLE_REGS_ABI_32;
26*1ddc96bdSTiezhu Yang 	else
27*1ddc96bdSTiezhu Yang 		return PERF_SAMPLE_REGS_ABI_64;
28*1ddc96bdSTiezhu Yang }
29*1ddc96bdSTiezhu Yang #endif /* CONFIG_32BIT */
30*1ddc96bdSTiezhu Yang 
perf_reg_validate(u64 mask)31*1ddc96bdSTiezhu Yang int perf_reg_validate(u64 mask)
32*1ddc96bdSTiezhu Yang {
33*1ddc96bdSTiezhu Yang 	if (!mask)
34*1ddc96bdSTiezhu Yang 		return -EINVAL;
35*1ddc96bdSTiezhu Yang 	if (mask & ~((1ull << PERF_REG_MIPS_MAX) - 1))
36*1ddc96bdSTiezhu Yang 		return -EINVAL;
37*1ddc96bdSTiezhu Yang 	return 0;
38*1ddc96bdSTiezhu Yang }
39*1ddc96bdSTiezhu Yang 
perf_reg_value(struct pt_regs * regs,int idx)40*1ddc96bdSTiezhu Yang u64 perf_reg_value(struct pt_regs *regs, int idx)
41*1ddc96bdSTiezhu Yang {
42*1ddc96bdSTiezhu Yang 	long v;
43*1ddc96bdSTiezhu Yang 
44*1ddc96bdSTiezhu Yang 	switch (idx) {
45*1ddc96bdSTiezhu Yang 	case PERF_REG_MIPS_PC:
46*1ddc96bdSTiezhu Yang 		v = regs->cp0_epc;
47*1ddc96bdSTiezhu Yang 		break;
48*1ddc96bdSTiezhu Yang 	case PERF_REG_MIPS_R1 ... PERF_REG_MIPS_R25:
49*1ddc96bdSTiezhu Yang 		v = regs->regs[idx - PERF_REG_MIPS_R1 + 1];
50*1ddc96bdSTiezhu Yang 		break;
51*1ddc96bdSTiezhu Yang 	case PERF_REG_MIPS_R28 ... PERF_REG_MIPS_R31:
52*1ddc96bdSTiezhu Yang 		v = regs->regs[idx - PERF_REG_MIPS_R28 + 28];
53*1ddc96bdSTiezhu Yang 		break;
54*1ddc96bdSTiezhu Yang 
55*1ddc96bdSTiezhu Yang 	default:
56*1ddc96bdSTiezhu Yang 		WARN_ON_ONCE(1);
57*1ddc96bdSTiezhu Yang 		return 0;
58*1ddc96bdSTiezhu Yang 	}
59*1ddc96bdSTiezhu Yang 
60*1ddc96bdSTiezhu Yang 	return (s64)v; /* Sign extend if 32-bit. */
61*1ddc96bdSTiezhu Yang }
62*1ddc96bdSTiezhu Yang 
perf_get_regs_user(struct perf_regs * regs_user,struct pt_regs * regs)63*1ddc96bdSTiezhu Yang void perf_get_regs_user(struct perf_regs *regs_user,
64*1ddc96bdSTiezhu Yang 			struct pt_regs *regs)
65*1ddc96bdSTiezhu Yang {
66*1ddc96bdSTiezhu Yang 	regs_user->regs = task_pt_regs(current);
67*1ddc96bdSTiezhu Yang 	regs_user->abi = perf_reg_abi(current);
68*1ddc96bdSTiezhu Yang }
69