mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
67 lines
1.7 KiB
67 lines
1.7 KiB
// SPDX-License-Identifier: GPL-2.0-only |
|
/* |
|
* Linux performance counter support for MIPS. |
|
* |
|
* Copyright (C) 2010 MIPS Technologies, Inc. |
|
* Author: Deng-Cheng Zhu |
|
* |
|
* This code is based on the implementation for ARM, which is in turn |
|
* based on the sparc64 perf event code and the x86 code. Performance |
|
* counter access is based on the MIPS Oprofile code. And the callchain |
|
* support references the code of MIPS stacktrace.c. |
|
*/ |
|
|
|
#include <linux/perf_event.h> |
|
#include <linux/sched/task_stack.h> |
|
|
|
#include <asm/stacktrace.h> |
|
|
|
/* Callchain handling code. */ |
|
|
|
/* |
|
* Leave userspace callchain empty for now. When we find a way to trace |
|
* the user stack callchains, we will add it here. |
|
*/ |
|
|
|
static void save_raw_perf_callchain(struct perf_callchain_entry_ctx *entry, |
|
unsigned long reg29) |
|
{ |
|
unsigned long *sp = (unsigned long *)reg29; |
|
unsigned long addr; |
|
|
|
while (!kstack_end(sp)) { |
|
addr = *sp++; |
|
if (__kernel_text_address(addr)) { |
|
perf_callchain_store(entry, addr); |
|
if (entry->nr >= entry->max_stack) |
|
break; |
|
} |
|
} |
|
} |
|
|
|
void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, |
|
struct pt_regs *regs) |
|
{ |
|
unsigned long sp = regs->regs[29]; |
|
#ifdef CONFIG_KALLSYMS |
|
unsigned long ra = regs->regs[31]; |
|
unsigned long pc = regs->cp0_epc; |
|
|
|
if (raw_show_trace || !__kernel_text_address(pc)) { |
|
unsigned long stack_page = |
|
(unsigned long)task_stack_page(current); |
|
if (stack_page && sp >= stack_page && |
|
sp <= stack_page + THREAD_SIZE - 32) |
|
save_raw_perf_callchain(entry, sp); |
|
return; |
|
} |
|
do { |
|
perf_callchain_store(entry, pc); |
|
if (entry->nr >= entry->max_stack) |
|
break; |
|
pc = unwind_stack(current, &sp, pc, &ra); |
|
} while (pc); |
|
#else |
|
save_raw_perf_callchain(entry, sp); |
|
#endif |
|
}
|
|
|