cregit-Linux how code gets into the kernel

Release 4.11 arch/arm/kernel/perf_callchain.c

Directory: arch/arm/kernel
/*
 * ARM callchain support
 *
 * Copyright (C) 2009 picoChip Designs, Ltd., Jamie Iles
 * Copyright (C) 2010 ARM Ltd., Will Deacon <will.deacon@arm.com>
 *
 * This code is based on the ARM OProfile backtrace code.
 */
#include <linux/perf_event.h>
#include <linux/uaccess.h>

#include <asm/stacktrace.h>

/*
 * The registers we're interested in are at the end of the variable
 * length saved register structure. The fp points at the end of this
 * structure so the address of this struct is:
 * (struct frame_tail *)(xxx->fp)-1
 *
 * This code has been adapted from the ARM OProfile support.
 */

struct frame_tail {
	
struct frame_tail __user *fp;
	
unsigned long sp;
	
unsigned long lr;
} __attribute__((packed));

/*
 * Get the return address for a single stackframe and return a pointer to the
 * next frame tail.
 */

static struct frame_tail __user * user_backtrace(struct frame_tail __user *tail, struct perf_callchain_entry_ctx *entry) { struct frame_tail buftail; unsigned long err; if (!access_ok(VERIFY_READ, tail, sizeof(buftail))) return NULL; pagefault_disable(); err = __copy_from_user_inatomic(&buftail, tail, sizeof(buftail)); pagefault_enable(); if (err) return NULL; perf_callchain_store(entry, buftail.lr); /* * Frame pointers should strictly progress back up the stack * (towards higher addresses). */ if (tail + 1 >= buftail.fp) return NULL; return buftail.fp - 1; }

Contributors

PersonTokensPropCommitsCommitProp
Mark Rutland10399.04%150.00%
Arnaldo Carvalho de Melo10.96%150.00%
Total104100.00%2100.00%


void perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs) { struct frame_tail __user *tail; if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { /* We don't support guest os callchain now */ return; } perf_callchain_store(entry, regs->ARM_pc); if (!current->mm) return; tail = (struct frame_tail __user *)regs->ARM_fp - 1; while ((entry->nr < entry->max_stack) && tail && !((unsigned long)tail & 0x3)) tail = user_backtrace(tail, entry); }

Contributors

PersonTokensPropCommitsCommitProp
Mark Rutland9595.96%150.00%
Arnaldo Carvalho de Melo44.04%150.00%
Total99100.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
Mark Rutland3397.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; if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { /* We don't support guest os callchain now */ return; } arm_get_current_stackframe(regs, &fr); walk_stackframe(&fr, callchain_trace, entry); }

Contributors

PersonTokensPropCommitsCommitProp
Mark Rutland4998.00%150.00%
Arnaldo Carvalho de Melo12.00%150.00%
Total50100.00%2100.00%


unsigned long perf_instruction_pointer(struct pt_regs *regs) { if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) return perf_guest_cbs->get_guest_ip(); return instruction_pointer(regs); }

Contributors

PersonTokensPropCommitsCommitProp
Mark Rutland32100.00%1100.00%
Total32100.00%1100.00%


unsigned long perf_misc_flags(struct pt_regs *regs) { int misc = 0; if (perf_guest_cbs && perf_guest_cbs->is_in_guest()) { if (perf_guest_cbs->is_user_mode()) misc |= PERF_RECORD_MISC_GUEST_USER; else misc |= PERF_RECORD_MISC_GUEST_KERNEL; } else { if (user_mode(regs)) misc |= PERF_RECORD_MISC_USER; else misc |= PERF_RECORD_MISC_KERNEL; } return misc; }

Contributors

PersonTokensPropCommitsCommitProp
Mark Rutland65100.00%1100.00%
Total65100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Mark Rutland41598.34%150.00%
Arnaldo Carvalho de Melo71.66%150.00%
Total422100.00%2100.00%
Directory: arch/arm/kernel
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.