diff options
Diffstat (limited to 'arch/um/kernel/sysrq.c')
-rw-r--r-- | arch/um/kernel/sysrq.c | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c new file mode 100644 index 000000000000..e630438f9e73 --- /dev/null +++ b/arch/um/kernel/sysrq.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2001 Jeff Dike (jdike@karaya.com) | ||
3 | * Licensed under the GPL | ||
4 | */ | ||
5 | |||
6 | #include "linux/sched.h" | ||
7 | #include "linux/kernel.h" | ||
8 | #include "linux/module.h" | ||
9 | #include "linux/kallsyms.h" | ||
10 | #include "asm/page.h" | ||
11 | #include "asm/processor.h" | ||
12 | #include "sysrq.h" | ||
13 | #include "user_util.h" | ||
14 | |||
15 | void show_trace(unsigned long * stack) | ||
16 | { | ||
17 | /* XXX: Copy the CONFIG_FRAME_POINTER stack-walking backtrace from | ||
18 | * arch/i386/kernel/traps.c, and then move this to sys-i386/sysrq.c.*/ | ||
19 | unsigned long addr; | ||
20 | |||
21 | if (!stack) { | ||
22 | stack = (unsigned long*) &stack; | ||
23 | WARN_ON(1); | ||
24 | } | ||
25 | |||
26 | printk("Call Trace: \n"); | ||
27 | while (((long) stack & (THREAD_SIZE-1)) != 0) { | ||
28 | addr = *stack; | ||
29 | if (__kernel_text_address(addr)) { | ||
30 | printk("%08lx: [<%08lx>]", (unsigned long) stack, addr); | ||
31 | print_symbol(" %s", addr); | ||
32 | printk("\n"); | ||
33 | } | ||
34 | stack++; | ||
35 | } | ||
36 | printk("\n"); | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * stack dumps generator - this is used by arch-independent code. | ||
41 | * And this is identical to i386 currently. | ||
42 | */ | ||
43 | void dump_stack(void) | ||
44 | { | ||
45 | unsigned long stack; | ||
46 | |||
47 | show_trace(&stack); | ||
48 | } | ||
49 | EXPORT_SYMBOL(dump_stack); | ||
50 | |||
51 | /*Stolen from arch/i386/kernel/traps.c */ | ||
52 | static int kstack_depth_to_print = 24; | ||
53 | |||
54 | /* This recently started being used in arch-independent code too, as in | ||
55 | * kernel/sched.c.*/ | ||
56 | void show_stack(struct task_struct *task, unsigned long *esp) | ||
57 | { | ||
58 | unsigned long *stack; | ||
59 | int i; | ||
60 | |||
61 | if (esp == NULL) { | ||
62 | if (task != current) { | ||
63 | esp = (unsigned long *) KSTK_ESP(task); | ||
64 | /* Which one? No actual difference - just coding style.*/ | ||
65 | //esp = (unsigned long *) PT_REGS_IP(&task->thread.regs); | ||
66 | } else { | ||
67 | esp = (unsigned long *) &esp; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | stack = esp; | ||
72 | for(i = 0; i < kstack_depth_to_print; i++) { | ||
73 | if (kstack_end(stack)) | ||
74 | break; | ||
75 | if (i && ((i % 8) == 0)) | ||
76 | printk("\n "); | ||
77 | printk("%08lx ", *stack++); | ||
78 | } | ||
79 | |||
80 | show_trace(esp); | ||
81 | } | ||