cregit-Linux how code gets into the kernel

Release 4.14 arch/metag/kernel/perf_callchain.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Perf callchain handling code.
 *
 *   Based on the ARM perf implementation.
 */

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/perf_event.h>
#include <linux/uaccess.h>
#include <asm/ptrace.h>
#include <asm/stacktrace.h>


static bool is_valid_call(unsigned long calladdr) { unsigned int callinsn; /* Check the possible return address is aligned. */ if (!(calladdr & 0x3)) { if (!get_user(callinsn, (unsigned int *)calladdr)) { /* Check for CALLR or SWAP PC,D1RtP. */ if ((callinsn & 0xff000000) == 0xab000000 || callinsn == 0xa3200aa0) return true; } } return false; }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan64100.00%1100.00%
Total64100.00%1100.00%


static struct metag_frame __user * user_backtrace(struct metag_frame __user *user_frame, struct perf_callchain_entry_ctx *entry) { struct metag_frame frame; unsigned long calladdr; /* We cannot rely on having frame pointers in user code. */ while (1) { /* Also check accessibility of one struct frame beyond */ if (!access_ok(VERIFY_READ, user_frame, sizeof(frame))) return 0; if (__copy_from_user_inatomic(&frame, user_frame, sizeof(frame))) return 0; --user_frame; calladdr = frame.lr - 4; if (is_valid_call(calladdr)) { perf_callchain_store(entry, calladdr); return user_frame; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan10499.05%150.00%
Arnaldo Carvalho de Melo10.95%150.00%
Total105100.00%2100.00%


void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { unsigned long sp = regs->ctx.AX[0].U0; struct metag_frame __user *frame; frame = (struct metag_frame __user *)sp; --frame; while ((entry->nr < entry->max_stack) && frame) frame = user_backtrace(frame, entry); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan6894.44%150.00%
Arnaldo Carvalho de Melo45.56%150.00%
Total72100.00%2100.00%

/* * Gets called by walk_stackframe() for every stackframe. This will be called * whist unwinding the stackframe and is like a subroutine return so we use * the PC. */
static int callchain_trace(struct stackframe *fr, void *data) { struct perf_callchain_entry_ctx *entry = data; perf_callchain_store(entry, fr->pc); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan3397.06%150.00%
Arnaldo Carvalho de Melo12.94%150.00%
Total34100.00%2100.00%


void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { struct stackframe fr; fr.fp = regs->ctx.AX[1].U0; fr.sp = regs->ctx.AX[0].U0; fr.lr = regs->ctx.DX[4].U1; fr.pc = regs->ctx.CurrPC; walk_stackframe(&fr, callchain_trace, entry); }

Contributors

PersonTokensPropCommitsCommitProp
James Hogan8398.81%150.00%
Arnaldo Carvalho de Melo11.19%150.00%
Total84100.00%2100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
James Hogan37297.89%133.33%
Arnaldo Carvalho de Melo71.84%133.33%
Greg Kroah-Hartman10.26%133.33%
Total380100.00%3100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.