mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Add perf_event_mips_regs/perf_reg_value/perf_reg_validate to support features HAVE_PERF_REGS/HAVE_PERF_USER_STACK_DUMP in kernel. [ayan@wavecomp.com: Repick this patch for unwinding userstack backtrace by perf and libunwind on MIPS based CPU.] [ralf@linux-mips.org: Add perf_get_regs_user() which is required after 'commit88a7c26af8("perf: Move task_pt_regs sampling into arch code")'.] [yangtiezhu@loongson.cn: Fix build error about perf_get_regs_user() after commit76a4efa809("perf/arch: Remove perf_sample_data::regs_user_copy"), and also separate the original patches into two parts (MIPS kernel and perf tools) to merge easily.] The original patches: https://lore.kernel.org/patchwork/patch/1126521/ https://lore.kernel.org/patchwork/patch/1126520/ Signed-off-by: David Daney <david.daney@cavium.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Archer Yan <ayan@wavecomp.com> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
		
			
				
	
	
		
			68 lines
		
	
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			68 lines
		
	
	
	
		
			1.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
/*
 | 
						|
 * This file is subject to the terms and conditions of the GNU General Public
 | 
						|
 * License.  See the file "COPYING" in the main directory of this archive
 | 
						|
 * for more details.
 | 
						|
 *
 | 
						|
 * Some parts derived from x86 version of this file.
 | 
						|
 *
 | 
						|
 * Copyright (C) 2013 Cavium, Inc.
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/perf_event.h>
 | 
						|
 | 
						|
#include <asm/ptrace.h>
 | 
						|
 | 
						|
#ifdef CONFIG_32BIT
 | 
						|
u64 perf_reg_abi(struct task_struct *tsk)
 | 
						|
{
 | 
						|
	return PERF_SAMPLE_REGS_ABI_32;
 | 
						|
}
 | 
						|
#else /* Must be CONFIG_64BIT */
 | 
						|
u64 perf_reg_abi(struct task_struct *tsk)
 | 
						|
{
 | 
						|
	if (test_tsk_thread_flag(tsk, TIF_32BIT_REGS))
 | 
						|
		return PERF_SAMPLE_REGS_ABI_32;
 | 
						|
	else
 | 
						|
		return PERF_SAMPLE_REGS_ABI_64;
 | 
						|
}
 | 
						|
#endif /* CONFIG_32BIT */
 | 
						|
 | 
						|
int perf_reg_validate(u64 mask)
 | 
						|
{
 | 
						|
	if (!mask)
 | 
						|
		return -EINVAL;
 | 
						|
	if (mask & ~((1ull << PERF_REG_MIPS_MAX) - 1))
 | 
						|
		return -EINVAL;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
u64 perf_reg_value(struct pt_regs *regs, int idx)
 | 
						|
{
 | 
						|
	long v;
 | 
						|
 | 
						|
	switch (idx) {
 | 
						|
	case PERF_REG_MIPS_PC:
 | 
						|
		v = regs->cp0_epc;
 | 
						|
		break;
 | 
						|
	case PERF_REG_MIPS_R1 ... PERF_REG_MIPS_R25:
 | 
						|
		v = regs->regs[idx - PERF_REG_MIPS_R1 + 1];
 | 
						|
		break;
 | 
						|
	case PERF_REG_MIPS_R28 ... PERF_REG_MIPS_R31:
 | 
						|
		v = regs->regs[idx - PERF_REG_MIPS_R28 + 28];
 | 
						|
		break;
 | 
						|
 | 
						|
	default:
 | 
						|
		WARN_ON_ONCE(1);
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	return (s64)v; /* Sign extend if 32-bit. */
 | 
						|
}
 | 
						|
 | 
						|
void perf_get_regs_user(struct perf_regs *regs_user,
 | 
						|
			struct pt_regs *regs)
 | 
						|
{
 | 
						|
	regs_user->regs = task_pt_regs(current);
 | 
						|
	regs_user->abi = perf_reg_abi(current);
 | 
						|
}
 |