• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * stack_profile.c
3  *
4  * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  *  * Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *  * Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *  * Neither the name Texas Instruments nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * src/stack_profile.c
36  *
37  */
38 
39 #include <linux/stddef.h>
40 #include <linux/kernel.h>
41 #include <linux/sched.h>
42 
43 #define STACK_MASK		(THREAD_SIZE-1)
44 #define MAX_STACK_FRAME		2
45 
46 typedef struct STACK_FRAME {
47 	unsigned long stack_buf[THREAD_SIZE/sizeof(unsigned long)];
48 	unsigned long *stack_start;
49 	unsigned long stack_size;
50 } stack_frame_t;
51 
52 static stack_frame_t sf_array[MAX_STACK_FRAME];
53 
check_stack(unsigned long * base)54 static unsigned long check_stack(unsigned long *base)
55 {
56 	register unsigned long sp asm ("sp");
57 	unsigned long retval = sp;
58 
59 	*base = ((sp & ~STACK_MASK) + sizeof(struct task_struct) + 4);
60 	return retval;
61 }
62 
check_stack_start(unsigned long * base,unsigned long real_sp,int id)63 unsigned long check_stack_start(unsigned long *base, unsigned long real_sp,
64 				int id)
65 {
66 	unsigned long i;
67 	unsigned long from, to;
68 
69 	to = check_stack(&from);
70 	*base = from;
71 
72 	/* save used stack context */
73 	if (id < MAX_STACK_FRAME) {
74 		stack_frame_t *sfp = &sf_array[id];
75 
76 		if (!real_sp)
77 			real_sp = to;
78 		sfp->stack_size = THREAD_SIZE - (real_sp & STACK_MASK);
79 		sfp->stack_start = (unsigned long *)real_sp;
80 		memcpy(sfp->stack_buf, sfp->stack_start, sfp->stack_size);
81 	}
82 	/* run from the stack pointer down to the base */
83 	for(i=from;(i < to);i+=4) {
84 		/* fill up the pattern */
85 		*(unsigned long *)i = 0xdeadbeef;
86 	}
87 	/*printk("check_stack_start: from=%x to=%x data=%x\n",from,to,*(long *)(from+4));*/
88 	return to;
89 }
90 
check_stack_stop(unsigned long * base,int id)91 unsigned long check_stack_stop(unsigned long *base, int id)
92 {
93 	unsigned long i;
94 	unsigned long from, to;
95 
96 	to = check_stack(&from);
97 	*base = from;
98 
99 	/* check used stack context */
100 	if (id < MAX_STACK_FRAME) {
101 		stack_frame_t *sfp = &sf_array[id];
102 
103 		if (memcmp(sfp->stack_buf, sfp->stack_start, sfp->stack_size)) {
104 			printk("%s: %p - Error\n", __func__, sfp->stack_start);
105 			for(i=0;(i < sfp->stack_size/sizeof(unsigned long));i++) {
106 				if (sfp->stack_start[i] != sfp->stack_buf[i])
107 					printk("%p: 0x%08lx != 0x%08lx\n", &sfp->stack_start[i], sfp->stack_start[i], sfp->stack_buf[i]);
108 			}
109 		}
110 	}
111 
112 	/* run from the stack pointer down to the base */
113 	for(i=from;(i < to);i+=4) {
114 		/* check up the pattern */
115 		if ((*(unsigned long *)i) != 0xdeadbeef)
116 			break;
117 	}
118 
119 	/*printk("check_stack_stop: from=%x to=%x data=%x data=%x i=0x%x\n",from,to,*(long *)from,*(long *)(from+4),i);*/
120 	/* return the first time when the pattern doesn't match */
121 	return i;
122 }
123 
print_stack(int id)124 void print_stack(int id)
125 {
126 	stack_frame_t *sfp = &sf_array[id];
127 	unsigned long i;
128 
129 	printk("%s: %d\n", __func__, id);
130 	for(i=0;(i < sfp->stack_size/sizeof(unsigned long));i++) {
131 		printk("%p: 0x%08lx\n", &sfp->stack_start[i], sfp->stack_start[i]);
132 	}
133 }
134 
get_task_struct_ptr_by_name(char * name)135 struct task_struct *get_task_struct_ptr_by_name(char *name)
136 {
137 	struct task_struct *g, *p;
138 
139 	read_lock(&tasklist_lock);
140 	do_each_thread(g, p) {
141 		/*
142 		 * reset the NMI-timeout, listing all files on a slow
143 		 * console might take alot of time:
144 		 */
145 		/* touch_nmi_watchdog(); */
146 		if (!strcmp(name, p->comm)) {
147 			read_unlock(&tasklist_lock);
148 			return p;
149 		}
150 	} while_each_thread(g, p);
151 	read_unlock(&tasklist_lock);
152 	return NULL;
153 }
154 
save_stack_context(char * name,int id)155 unsigned long save_stack_context(char *name, int id)
156 {
157 /*	register unsigned long sp asm ("sp");
158 	unsigned long sp_local = sp;
159 */
160 	struct task_struct *p;
161 	stack_frame_t *sfp;
162 
163 	if (id >= MAX_STACK_FRAME)
164 		return 0L;
165 	sfp = &sf_array[id];
166 	p = get_task_struct_ptr_by_name(name);
167 	if (p) {
168 		printk("%s: %s found\n", __func__, p->comm); /* sched_show_task(t);*/
169 		sfp->stack_start = (unsigned long *)((unsigned long)end_of_stack(p) & ~STACK_MASK);
170 		sfp->stack_size = THREAD_SIZE;
171 		memcpy(sfp->stack_buf, sfp->stack_start, sfp->stack_size);
172 	}
173 	return sfp->stack_size;
174 }
175