cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

stacktrace.c (2175B)


      1/*
      2 * Stack trace utility for OpenRISC
      3 *
      4 * Copyright (C) 2017 Stafford Horne <shorne@gmail.com>
      5 *
      6 * This file is licensed under the terms of the GNU General Public License
      7 * version 2.  This program is licensed "as is" without any warranty of any
      8 * kind, whether express or implied.
      9 *
     10 * Losely based on work from sh and powerpc.
     11 */
     12
     13#include <linux/export.h>
     14#include <linux/sched.h>
     15#include <linux/sched/debug.h>
     16#include <linux/sched/task_stack.h>
     17#include <linux/stacktrace.h>
     18
     19#include <asm/processor.h>
     20#include <asm/unwinder.h>
     21
     22/*
     23 * Save stack-backtrace addresses into a stack_trace buffer.
     24 */
     25static void
     26save_stack_address(void *data, unsigned long addr, int reliable)
     27{
     28	struct stack_trace *trace = data;
     29
     30	if (!reliable)
     31		return;
     32
     33	if (trace->skip > 0) {
     34		trace->skip--;
     35		return;
     36	}
     37
     38	if (trace->nr_entries < trace->max_entries)
     39		trace->entries[trace->nr_entries++] = addr;
     40}
     41
     42void save_stack_trace(struct stack_trace *trace)
     43{
     44	unwind_stack(trace, (unsigned long *) &trace, save_stack_address);
     45}
     46EXPORT_SYMBOL_GPL(save_stack_trace);
     47
     48static void
     49save_stack_address_nosched(void *data, unsigned long addr, int reliable)
     50{
     51	struct stack_trace *trace = (struct stack_trace *)data;
     52
     53	if (!reliable)
     54		return;
     55
     56	if (in_sched_functions(addr))
     57		return;
     58
     59	if (trace->skip > 0) {
     60		trace->skip--;
     61		return;
     62	}
     63
     64	if (trace->nr_entries < trace->max_entries)
     65		trace->entries[trace->nr_entries++] = addr;
     66}
     67
     68void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
     69{
     70	unsigned long *sp = NULL;
     71
     72	if (!try_get_task_stack(tsk))
     73		return;
     74
     75	if (tsk == current)
     76		sp = (unsigned long *) &sp;
     77	else {
     78		unsigned long ksp;
     79
     80		/* Locate stack from kernel context */
     81		ksp = task_thread_info(tsk)->ksp;
     82		ksp += STACK_FRAME_OVERHEAD;	/* redzone */
     83		ksp += sizeof(struct pt_regs);
     84
     85		sp = (unsigned long *) ksp;
     86	}
     87
     88	unwind_stack(trace, sp, save_stack_address_nosched);
     89
     90	put_task_stack(tsk);
     91}
     92EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
     93
     94void
     95save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
     96{
     97	unwind_stack(trace, (unsigned long *) regs->sp,
     98		     save_stack_address_nosched);
     99}
    100EXPORT_SYMBOL_GPL(save_stack_trace_regs);