Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * Arm specific backtracing code for oprofile
  3  *
  4  * Copyright 2005 Openedhand Ltd.
  5  *
  6  * Author: Richard Purdie <rpurdie@openedhand.com>
  7  *
  8  * Based on i386 oprofile backtrace code by John Levon, David Smith
  9  *
 10  * This program is free software; you can redistribute it and/or modify
 11  * it under the terms of the GNU General Public License version 2 as
 12  * published by the Free Software Foundation.
 13  *
 14  */
 15 
 16 #include <linux/oprofile.h>
 17 #include <linux/sched.h>
 18 #include <linux/mm.h>
 19 #include <linux/uaccess.h>
 20 #include <asm/ptrace.h>
 21 #include <asm/stacktrace.h>
 22 
 23 static int report_trace(struct stackframe *frame, void *d)
 24 {
 25         unsigned int *depth = d;
 26 
 27         if (*depth) {
 28                 oprofile_add_trace(frame->pc);
 29                 (*depth)--;
 30         }
 31 
 32         return *depth == 0;
 33 }
 34 
 35 /*
 36  * The registers we're interested in are at the end of the variable
 37  * length saved register structure. The fp points at the end of this
 38  * structure so the address of this struct is:
 39  * (struct frame_tail *)(xxx->fp)-1
 40  */
 41 struct frame_tail {
 42         struct frame_tail *fp;
 43         unsigned long sp;
 44         unsigned long lr;
 45 } __attribute__((packed));
 46 
 47 static struct frame_tail* user_backtrace(struct frame_tail *tail)
 48 {
 49         struct frame_tail buftail[2];
 50 
 51         /* Also check accessibility of one struct frame_tail beyond */
 52         if (!access_ok(VERIFY_READ, tail, sizeof(buftail)))
 53                 return NULL;
 54         if (__copy_from_user_inatomic(buftail, tail, sizeof(buftail)))
 55                 return NULL;
 56 
 57         oprofile_add_trace(buftail[0].lr);
 58 
 59         /* frame pointers should strictly progress back up the stack
 60          * (towards higher addresses) */
 61         if (tail >= buftail[0].fp)
 62                 return NULL;
 63 
 64         return buftail[0].fp-1;
 65 }
 66 
 67 void arm_backtrace(struct pt_regs * const regs, unsigned int depth)
 68 {
 69         struct frame_tail *tail = ((struct frame_tail *) regs->ARM_fp) - 1;
 70 
 71         if (!user_mode(regs)) {
 72                 struct stackframe frame;
 73                 frame.fp = regs->ARM_fp;
 74                 frame.sp = regs->ARM_sp;
 75                 frame.lr = regs->ARM_lr;
 76                 frame.pc = regs->ARM_pc;
 77                 walk_stackframe(&frame, report_trace, &depth);
 78                 return;
 79         }
 80 
 81         while (depth-- && tail && !((unsigned long) tail & 3))
 82                 tail = user_backtrace(tail);
 83 }
 84 
  This page was automatically generated by the LXR engine.