aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/dumpstack.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/dumpstack.c')
-rw-r--r--arch/s390/kernel/dumpstack.c63
1 files changed, 22 insertions, 41 deletions
diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c
index 6693383bc01b..55d4fe174fd9 100644
--- a/arch/s390/kernel/dumpstack.c
+++ b/arch/s390/kernel/dumpstack.c
@@ -38,10 +38,10 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
38 if (sp < low || sp > high - sizeof(*sf)) 38 if (sp < low || sp > high - sizeof(*sf))
39 return sp; 39 return sp;
40 sf = (struct stack_frame *) sp; 40 sf = (struct stack_frame *) sp;
41 if (func(data, sf->gprs[8], 0))
42 return sp;
41 /* Follow the backchain. */ 43 /* Follow the backchain. */
42 while (1) { 44 while (1) {
43 if (func(data, sf->gprs[8]))
44 return sp;
45 low = sp; 45 low = sp;
46 sp = sf->back_chain; 46 sp = sf->back_chain;
47 if (!sp) 47 if (!sp)
@@ -49,6 +49,8 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
49 if (sp <= low || sp > high - sizeof(*sf)) 49 if (sp <= low || sp > high - sizeof(*sf))
50 return sp; 50 return sp;
51 sf = (struct stack_frame *) sp; 51 sf = (struct stack_frame *) sp;
52 if (func(data, sf->gprs[8], 1))
53 return sp;
52 } 54 }
53 /* Zero backchain detected, check for interrupt frame. */ 55 /* Zero backchain detected, check for interrupt frame. */
54 sp = (unsigned long) (sf + 1); 56 sp = (unsigned long) (sf + 1);
@@ -56,7 +58,7 @@ __dump_trace(dump_trace_func_t func, void *data, unsigned long sp,
56 return sp; 58 return sp;
57 regs = (struct pt_regs *) sp; 59 regs = (struct pt_regs *) sp;
58 if (!user_mode(regs)) { 60 if (!user_mode(regs)) {
59 if (func(data, regs->psw.addr)) 61 if (func(data, regs->psw.addr, 1))
60 return sp; 62 return sp;
61 } 63 }
62 low = sp; 64 low = sp;
@@ -85,33 +87,12 @@ void dump_trace(dump_trace_func_t func, void *data, struct task_struct *task,
85} 87}
86EXPORT_SYMBOL_GPL(dump_trace); 88EXPORT_SYMBOL_GPL(dump_trace);
87 89
88struct return_address_data { 90static int show_address(void *data, unsigned long address, int reliable)
89 unsigned long address;
90 int depth;
91};
92
93static int __return_address(void *data, unsigned long address)
94{
95 struct return_address_data *rd = data;
96
97 if (rd->depth--)
98 return 0;
99 rd->address = address;
100 return 1;
101}
102
103unsigned long return_address(int depth)
104{
105 struct return_address_data rd = { .depth = depth + 2 };
106
107 dump_trace(__return_address, &rd, NULL, current_stack_pointer());
108 return rd.address;
109}
110EXPORT_SYMBOL_GPL(return_address);
111
112static int show_address(void *data, unsigned long address)
113{ 91{
114 printk("([<%016lx>] %pSR)\n", address, (void *)address); 92 if (reliable)
93 printk(" [<%016lx>] %pSR \n", address, (void *)address);
94 else
95 printk("([<%016lx>] %pSR)\n", address, (void *)address);
115 return 0; 96 return 0;
116} 97}
117 98
@@ -138,14 +119,14 @@ void show_stack(struct task_struct *task, unsigned long *sp)
138 else 119 else
139 stack = (unsigned long *)task->thread.ksp; 120 stack = (unsigned long *)task->thread.ksp;
140 } 121 }
122 printk(KERN_DEFAULT "Stack:\n");
141 for (i = 0; i < 20; i++) { 123 for (i = 0; i < 20; i++) {
142 if (((addr_t) stack & (THREAD_SIZE-1)) == 0) 124 if (((addr_t) stack & (THREAD_SIZE-1)) == 0)
143 break; 125 break;
144 if ((i * sizeof(long) % 32) == 0) 126 if (i % 4 == 0)
145 printk("%s ", i == 0 ? "" : "\n"); 127 printk(KERN_DEFAULT " ");
146 printk("%016lx ", *stack++); 128 pr_cont("%016lx%c", *stack++, i % 4 == 3 ? '\n' : ' ');
147 } 129 }
148 printk("\n");
149 show_trace(task, (unsigned long)sp); 130 show_trace(task, (unsigned long)sp);
150} 131}
151 132
@@ -163,13 +144,13 @@ void show_registers(struct pt_regs *regs)
163 mode = user_mode(regs) ? "User" : "Krnl"; 144 mode = user_mode(regs) ? "User" : "Krnl";
164 printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr); 145 printk("%s PSW : %p %p", mode, (void *)regs->psw.mask, (void *)regs->psw.addr);
165 if (!user_mode(regs)) 146 if (!user_mode(regs))
166 printk(" (%pSR)", (void *)regs->psw.addr); 147 pr_cont(" (%pSR)", (void *)regs->psw.addr);
167 printk("\n"); 148 pr_cont("\n");
168 printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x " 149 printk(" R:%x T:%x IO:%x EX:%x Key:%x M:%x W:%x "
169 "P:%x AS:%x CC:%x PM:%x", psw->r, psw->t, psw->i, psw->e, 150 "P:%x AS:%x CC:%x PM:%x", psw->r, psw->t, psw->i, psw->e,
170 psw->key, psw->m, psw->w, psw->p, psw->as, psw->cc, psw->pm); 151 psw->key, psw->m, psw->w, psw->p, psw->as, psw->cc, psw->pm);
171 printk(" RI:%x EA:%x", psw->ri, psw->eaba); 152 pr_cont(" RI:%x EA:%x\n", psw->ri, psw->eaba);
172 printk("\n%s GPRS: %016lx %016lx %016lx %016lx\n", mode, 153 printk("%s GPRS: %016lx %016lx %016lx %016lx\n", mode,
173 regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]); 154 regs->gprs[0], regs->gprs[1], regs->gprs[2], regs->gprs[3]);
174 printk(" %016lx %016lx %016lx %016lx\n", 155 printk(" %016lx %016lx %016lx %016lx\n",
175 regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]); 156 regs->gprs[4], regs->gprs[5], regs->gprs[6], regs->gprs[7]);
@@ -205,14 +186,14 @@ void die(struct pt_regs *regs, const char *str)
205 printk("%s: %04x ilc:%d [#%d] ", str, regs->int_code & 0xffff, 186 printk("%s: %04x ilc:%d [#%d] ", str, regs->int_code & 0xffff,
206 regs->int_code >> 17, ++die_counter); 187 regs->int_code >> 17, ++die_counter);
207#ifdef CONFIG_PREEMPT 188#ifdef CONFIG_PREEMPT
208 printk("PREEMPT "); 189 pr_cont("PREEMPT ");
209#endif 190#endif
210#ifdef CONFIG_SMP 191#ifdef CONFIG_SMP
211 printk("SMP "); 192 pr_cont("SMP ");
212#endif 193#endif
213 if (debug_pagealloc_enabled()) 194 if (debug_pagealloc_enabled())
214 printk("DEBUG_PAGEALLOC"); 195 pr_cont("DEBUG_PAGEALLOC");
215 printk("\n"); 196 pr_cont("\n");
216 notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV); 197 notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV);
217 print_modules(); 198 print_modules();
218 show_regs(regs); 199 show_regs(regs);