]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - arch/parisc/kernel/unwind.c
Replace <asm/uaccess.h> with <linux/uaccess.h> globally
[mirror_ubuntu-bionic-kernel.git] / arch / parisc / kernel / unwind.c
CommitLineData
1da177e4
LT
1/*
2 * Kernel unwinding support
3 *
4 * (c) 2002-2004 Randolph Chung <tausq@debian.org>
5 *
6 * Derived partially from the IA64 implementation. The PA-RISC
7 * Runtime Architecture Document is also a useful reference to
8 * understand what is happening here
9 */
10
1da177e4
LT
11#include <linux/kernel.h>
12#include <linux/init.h>
e6fc0449 13#include <linux/sched.h>
1da177e4
LT
14#include <linux/slab.h>
15#include <linux/kallsyms.h>
8f78df87 16#include <linux/sort.h>
1da177e4 17
7c0f6ba6 18#include <linux/uaccess.h>
1da177e4 19#include <asm/assembly.h>
05dc16d6
RC
20#include <asm/asm-offsets.h>
21#include <asm/ptrace.h>
1da177e4
LT
22
23#include <asm/unwind.h>
24
25/* #define DEBUG 1 */
26#ifdef DEBUG
27#define dbg(x...) printk(x)
28#else
29#define dbg(x...)
30#endif
31
33a932d1 32#define KERNEL_START (KERNEL_BINARY_TEXT_START)
e036306a 33
1da177e4
LT
34extern struct unwind_table_entry __start___unwind[];
35extern struct unwind_table_entry __stop___unwind[];
36
37static spinlock_t unwind_lock;
38/*
39 * the kernel unwind block is not dynamically allocated so that
40 * we can call unwind_init as early in the bootup process as
41 * possible (before the slab allocator is initialized)
42 */
8039de10 43static struct unwind_table kernel_unwind_table __read_mostly;
1da177e4
LT
44static LIST_HEAD(unwind_tables);
45
46static inline const struct unwind_table_entry *
47find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
48{
49 const struct unwind_table_entry *e = NULL;
50 unsigned long lo, hi, mid;
51
52 lo = 0;
53 hi = table->length - 1;
54
55 while (lo <= hi) {
56 mid = (hi - lo) / 2 + lo;
57 e = &table->table[mid];
58 if (addr < e->region_start)
59 hi = mid - 1;
60 else if (addr > e->region_end)
61 lo = mid + 1;
62 else
63 return e;
64 }
65
66 return NULL;
67}
68
69static const struct unwind_table_entry *
70find_unwind_entry(unsigned long addr)
71{
72 struct unwind_table *table;
73 const struct unwind_table_entry *e = NULL;
74
75 if (addr >= kernel_unwind_table.start &&
76 addr <= kernel_unwind_table.end)
77 e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
be24a897
MP
78 else {
79 unsigned long flags;
80
81 spin_lock_irqsave(&unwind_lock, flags);
1da177e4
LT
82 list_for_each_entry(table, &unwind_tables, list) {
83 if (addr >= table->start &&
84 addr <= table->end)
85 e = find_unwind_entry_in_table(table, addr);
b1b1d4a6
PC
86 if (e) {
87 /* Move-to-front to exploit common traces */
88 list_move(&table->list, &unwind_tables);
1da177e4 89 break;
b1b1d4a6 90 }
1da177e4 91 }
be24a897
MP
92 spin_unlock_irqrestore(&unwind_lock, flags);
93 }
1da177e4
LT
94
95 return e;
96}
97
98static void
99unwind_table_init(struct unwind_table *table, const char *name,
100 unsigned long base_addr, unsigned long gp,
101 void *table_start, void *table_end)
102{
103 struct unwind_table_entry *start = table_start;
104 struct unwind_table_entry *end =
105 (struct unwind_table_entry *)table_end - 1;
106
107 table->name = name;
108 table->base_addr = base_addr;
109 table->gp = gp;
110 table->start = base_addr + start->region_start;
111 table->end = base_addr + end->region_end;
112 table->table = (struct unwind_table_entry *)table_start;
113 table->length = end - start + 1;
114 INIT_LIST_HEAD(&table->list);
115
116 for (; start <= end; start++) {
117 if (start < end &&
118 start->region_end > (start+1)->region_start) {
119 printk("WARNING: Out of order unwind entry! %p and %p\n", start, start+1);
120 }
121
122 start->region_start += base_addr;
123 start->region_end += base_addr;
124 }
125}
126
8f78df87
HD
127static int cmp_unwind_table_entry(const void *a, const void *b)
128{
129 return ((const struct unwind_table_entry *)a)->region_start
130 - ((const struct unwind_table_entry *)b)->region_start;
131}
132
1da177e4
LT
133static void
134unwind_table_sort(struct unwind_table_entry *start,
135 struct unwind_table_entry *finish)
136{
8f78df87
HD
137 sort(start, finish - start, sizeof(struct unwind_table_entry),
138 cmp_unwind_table_entry, NULL);
1da177e4
LT
139}
140
141struct unwind_table *
142unwind_table_add(const char *name, unsigned long base_addr,
143 unsigned long gp,
144 void *start, void *end)
145{
146 struct unwind_table *table;
147 unsigned long flags;
148 struct unwind_table_entry *s = (struct unwind_table_entry *)start;
149 struct unwind_table_entry *e = (struct unwind_table_entry *)end;
150
151 unwind_table_sort(s, e);
152
153 table = kmalloc(sizeof(struct unwind_table), GFP_USER);
154 if (table == NULL)
155 return NULL;
156 unwind_table_init(table, name, base_addr, gp, start, end);
157 spin_lock_irqsave(&unwind_lock, flags);
158 list_add_tail(&table->list, &unwind_tables);
159 spin_unlock_irqrestore(&unwind_lock, flags);
160
161 return table;
162}
163
164void unwind_table_remove(struct unwind_table *table)
165{
166 unsigned long flags;
167
168 spin_lock_irqsave(&unwind_lock, flags);
169 list_del(&table->list);
170 spin_unlock_irqrestore(&unwind_lock, flags);
171
172 kfree(table);
173}
174
175/* Called from setup_arch to import the kernel unwind info */
c790b41b 176int __init unwind_init(void)
1da177e4
LT
177{
178 long start, stop;
179 register unsigned long gp __asm__ ("r27");
180
181 start = (long)&__start___unwind[0];
182 stop = (long)&__stop___unwind[0];
183
184 spin_lock_init(&unwind_lock);
185
186 printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
187 start, stop,
188 (stop - start) / sizeof(struct unwind_table_entry));
189
190 unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
191 gp,
192 &__start___unwind[0], &__stop___unwind[0]);
193#if 0
194 {
195 int i;
196 for (i = 0; i < 10; i++)
197 {
198 printk("region 0x%x-0x%x\n",
199 __start___unwind[i].region_start,
200 __start___unwind[i].region_end);
201 }
202 }
203#endif
204 return 0;
205}
206
05dc16d6
RC
207#ifdef CONFIG_64BIT
208#define get_func_addr(fptr) fptr[2]
209#else
210#define get_func_addr(fptr) fptr[0]
211#endif
212
213static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
214{
78199943
KM
215 extern void handle_interruption(int, struct pt_regs *);
216 static unsigned long *hi = (unsigned long *)&handle_interruption;
05dc16d6
RC
217
218 if (pc == get_func_addr(hi)) {
219 struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
220 dbg("Unwinding through handle_interruption()\n");
221 info->prev_sp = regs->gr[30];
222 info->prev_ip = regs->iaoq[0];
223
224 return 1;
225 }
226
227 return 0;
228}
229
1da177e4
LT
230static void unwind_frame_regs(struct unwind_frame_info *info)
231{
232 const struct unwind_table_entry *e;
233 unsigned long npc;
234 unsigned int insn;
235 long frame_size = 0;
236 int looking_for_rp, rpoffset = 0;
237
238 e = find_unwind_entry(info->ip);
239 if (e == NULL) {
240 unsigned long sp;
1da177e4
LT
241
242 dbg("Cannot find unwind entry for 0x%lx; forced unwinding\n", info->ip);
243
244#ifdef CONFIG_KALLSYMS
245 /* Handle some frequent special cases.... */
246 {
9281acea 247 char symname[KSYM_NAME_LEN];
cb957795 248 char *modname;
1da177e4 249
cb957795
KM
250 kallsyms_lookup(info->ip, NULL, NULL, &modname,
251 symname);
1da177e4
LT
252
253 dbg("info->ip = 0x%lx, name = %s\n", info->ip, symname);
254
255 if (strcmp(symname, "_switch_to_ret") == 0) {
256 info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
257 info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
258 dbg("_switch_to_ret @ %lx - setting "
259 "prev_sp=%lx prev_ip=%lx\n",
260 info->ip, info->prev_sp,
261 info->prev_ip);
262 return;
263 } else if (strcmp(symname, "ret_from_kernel_thread") == 0 ||
264 strcmp(symname, "syscall_exit") == 0) {
265 info->prev_ip = info->prev_sp = 0;
266 return;
267 }
268 }
269#endif
270
271 /* Since we are doing the unwinding blind, we don't know if
272 we are adjusting the stack correctly or extracting the rp
273 correctly. The rp is checked to see if it belongs to the
274 kernel text section, if not we assume we don't have a
275 correct stack frame and we continue to unwind the stack.
276 This is not quite correct, and will fail for loadable
277 modules. */
278 sp = info->sp & ~63;
279 do {
280 unsigned long tmp;
281
282 info->prev_sp = sp - 64;
283 info->prev_ip = 0;
284 if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
285 break;
286 info->prev_ip = tmp;
287 sp = info->prev_sp;
c790b41b 288 } while (!kernel_text_address(info->prev_ip));
1da177e4
LT
289
290 info->rp = 0;
291
292 dbg("analyzing func @ %lx with no unwind info, setting "
293 "prev_sp=%lx prev_ip=%lx\n", info->ip,
294 info->prev_sp, info->prev_ip);
295 } else {
296 dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
297 "Save_RP = %d, Millicode = %d size = %u\n",
298 e->region_start, e->region_end, e->Save_SP, e->Save_RP,
299 e->Millicode, e->Total_frame_size);
300
301 looking_for_rp = e->Save_RP;
302
303 for (npc = e->region_start;
304 (frame_size < (e->Total_frame_size << 3) ||
305 looking_for_rp) &&
306 npc < info->ip;
307 npc += 4) {
308
309 insn = *(unsigned int *)npc;
310
be24a897
MP
311 if ((insn & 0xffffc001) == 0x37de0000 ||
312 (insn & 0xffe00001) == 0x6fc00000) {
1da177e4 313 /* ldo X(sp), sp, or stwm X,D(sp) */
be24a897 314 frame_size += (insn & 0x3fff) >> 1;
1da177e4
LT
315 dbg("analyzing func @ %lx, insn=%08x @ "
316 "%lx, frame_size = %ld\n", info->ip,
317 insn, npc, frame_size);
be24a897 318 } else if ((insn & 0xffe00009) == 0x73c00008) {
1da177e4 319 /* std,ma X,D(sp) */
be24a897 320 frame_size += ((insn >> 4) & 0x3ff) << 3;
1da177e4
LT
321 dbg("analyzing func @ %lx, insn=%08x @ "
322 "%lx, frame_size = %ld\n", info->ip,
323 insn, npc, frame_size);
324 } else if (insn == 0x6bc23fd9) {
325 /* stw rp,-20(sp) */
326 rpoffset = 20;
327 looking_for_rp = 0;
328 dbg("analyzing func @ %lx, insn=stw rp,"
329 "-20(sp) @ %lx\n", info->ip, npc);
330 } else if (insn == 0x0fc212c1) {
331 /* std rp,-16(sr0,sp) */
332 rpoffset = 16;
333 looking_for_rp = 0;
334 dbg("analyzing func @ %lx, insn=std rp,"
335 "-16(sp) @ %lx\n", info->ip, npc);
336 }
337 }
338
be24a897
MP
339 if (frame_size > e->Total_frame_size << 3)
340 frame_size = e->Total_frame_size << 3;
341
05dc16d6
RC
342 if (!unwind_special(info, e->region_start, frame_size)) {
343 info->prev_sp = info->sp - frame_size;
344 if (e->Millicode)
345 info->rp = info->r31;
346 else if (rpoffset)
347 info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
348 info->prev_ip = info->rp;
349 info->rp = 0;
350 }
1da177e4
LT
351
352 dbg("analyzing func @ %lx, setting prev_sp=%lx "
353 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
354 info->prev_ip, npc);
355 }
356}
357
358void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
359 struct pt_regs *regs)
360{
361 memset(info, 0, sizeof(struct unwind_frame_info));
362 info->t = t;
363 info->sp = regs->gr[30];
364 info->ip = regs->iaoq[0];
365 info->rp = regs->gr[2];
366 info->r31 = regs->gr[31];
367
368 dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
369 t ? (int)t->pid : -1, info->sp, info->ip);
370}
371
372void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
373{
374 struct pt_regs *r = &t->thread.regs;
375 struct pt_regs *r2;
376
e0e7ed48 377 r2 = kmalloc(sizeof(struct pt_regs), GFP_ATOMIC);
1da177e4
LT
378 if (!r2)
379 return;
380 *r2 = *r;
381 r2->gr[30] = r->ksp;
382 r2->iaoq[0] = r->kpc;
383 unwind_frame_init(info, t, r2);
384 kfree(r2);
385}
386
387void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
388{
389 unwind_frame_init(info, current, regs);
390}
391
392int unwind_once(struct unwind_frame_info *next_frame)
393{
394 unwind_frame_regs(next_frame);
395
396 if (next_frame->prev_sp == 0 ||
397 next_frame->prev_ip == 0)
398 return -1;
399
400 next_frame->sp = next_frame->prev_sp;
401 next_frame->ip = next_frame->prev_ip;
402 next_frame->prev_sp = 0;
403 next_frame->prev_ip = 0;
404
405 dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
406 next_frame->t ? (int)next_frame->t->pid : -1,
407 next_frame->sp, next_frame->ip);
408
409 return 0;
410}
411
412int unwind_to_user(struct unwind_frame_info *info)
413{
414 int ret;
415
416 do {
417 ret = unwind_once(info);
418 } while (!ret && !(info->ip & 3));
419
420 return ret;
421}
11e17809
HD
422
423unsigned long return_address(unsigned int level)
424{
425 struct unwind_frame_info info;
426 struct pt_regs r;
427 unsigned long sp;
428
429 /* initialize unwind info */
430 asm volatile ("copy %%r30, %0" : "=r"(sp));
431 memset(&r, 0, sizeof(struct pt_regs));
432 r.iaoq[0] = (unsigned long) current_text_addr();
433 r.gr[2] = (unsigned long) __builtin_return_address(0);
434 r.gr[30] = sp;
435 unwind_frame_init(&info, current, &r);
436
437 /* unwind stack */
438 ++level;
439 do {
440 if (unwind_once(&info) < 0 || info.ip == 0)
441 return 0;
c790b41b 442 if (!kernel_text_address(info.ip))
11e17809 443 return 0;
11e17809
HD
444 } while (info.ip && level--);
445
446 return info.ip;
447}