~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/powerpc/oprofile/backtrace.c

Version: ~ [ linux-5.9.1 ] ~ [ linux-5.8.16 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.72 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.152 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.202 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.240 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.240 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /**
  2  * Copyright (C) 2005 Brian Rogan <bcr6@cornell.edu>, IBM
  3  *
  4  * This program is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU General Public License
  6  * as published by the Free Software Foundation; either version
  7  * 2 of the License, or (at your option) any later version.
  8 **/
  9 
 10 #include <linux/oprofile.h>
 11 #include <linux/sched.h>
 12 #include <asm/processor.h>
 13 #include <linux/uaccess.h>
 14 #include <asm/compat.h>
 15 #include <asm/oprofile_impl.h>
 16 
 17 #define STACK_SP(STACK)         *(STACK)
 18 
 19 #define STACK_LR64(STACK)       *((unsigned long *)(STACK) + 2)
 20 #define STACK_LR32(STACK)       *((unsigned int *)(STACK) + 1)
 21 
 22 #ifdef CONFIG_PPC64
 23 #define STACK_LR(STACK)         STACK_LR64(STACK)
 24 #else
 25 #define STACK_LR(STACK)         STACK_LR32(STACK)
 26 #endif
 27 
 28 static unsigned int user_getsp32(unsigned int sp, int is_first)
 29 {
 30         unsigned int stack_frame[2];
 31         void __user *p = compat_ptr(sp);
 32 
 33         if (!access_ok(VERIFY_READ, p, sizeof(stack_frame)))
 34                 return 0;
 35 
 36         /*
 37          * The most likely reason for this is that we returned -EFAULT,
 38          * which means that we've done all that we can do from
 39          * interrupt context.
 40          */
 41         if (__copy_from_user_inatomic(stack_frame, p, sizeof(stack_frame)))
 42                 return 0;
 43 
 44         if (!is_first)
 45                 oprofile_add_trace(STACK_LR32(stack_frame));
 46 
 47         /*
 48          * We do not enforce increasing stack addresses here because
 49          * we may transition to a different stack, eg a signal handler.
 50          */
 51         return STACK_SP(stack_frame);
 52 }
 53 
 54 #ifdef CONFIG_PPC64
 55 static unsigned long user_getsp64(unsigned long sp, int is_first)
 56 {
 57         unsigned long stack_frame[3];
 58 
 59         if (!access_ok(VERIFY_READ, (void __user *)sp, sizeof(stack_frame)))
 60                 return 0;
 61 
 62         if (__copy_from_user_inatomic(stack_frame, (void __user *)sp,
 63                                         sizeof(stack_frame)))
 64                 return 0;
 65 
 66         if (!is_first)
 67                 oprofile_add_trace(STACK_LR64(stack_frame));
 68 
 69         return STACK_SP(stack_frame);
 70 }
 71 #endif
 72 
 73 static unsigned long kernel_getsp(unsigned long sp, int is_first)
 74 {
 75         unsigned long *stack_frame = (unsigned long *)sp;
 76 
 77         if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
 78                 return 0;
 79 
 80         if (!is_first)
 81                 oprofile_add_trace(STACK_LR(stack_frame));
 82 
 83         /*
 84          * We do not enforce increasing stack addresses here because
 85          * we might be transitioning from an interrupt stack to a kernel
 86          * stack. validate_sp() is designed to understand this, so just
 87          * use it.
 88          */
 89         return STACK_SP(stack_frame);
 90 }
 91 
 92 void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth)
 93 {
 94         unsigned long sp = regs->gpr[1];
 95         int first_frame = 1;
 96 
 97         /* We ditch the top stackframe so need to loop through an extra time */
 98         depth += 1;
 99 
100         if (!user_mode(regs)) {
101                 while (depth--) {
102                         sp = kernel_getsp(sp, first_frame);
103                         if (!sp)
104                                 break;
105                         first_frame = 0;
106                 }
107         } else {
108                 pagefault_disable();
109 #ifdef CONFIG_PPC64
110                 if (!is_32bit_task()) {
111                         while (depth--) {
112                                 sp = user_getsp64(sp, first_frame);
113                                 if (!sp)
114                                         break;
115                                 first_frame = 0;
116                         }
117                         pagefault_enable();
118                         return;
119                 }
120 #endif
121 
122                 while (depth--) {
123                         sp = user_getsp32(sp, first_frame);
124                         if (!sp)
125                                 break;
126                         first_frame = 0;
127                 }
128                 pagefault_enable();
129         }
130 }
131 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp