aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/cpu
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2012-05-24 02:03:46 -0400
committerPaul Mundt <lethal@linux-sh.org>2012-05-24 02:03:46 -0400
commit49453264997f232008efae457553d82381f9614f (patch)
treeab5e697e26453774c5aece0936aaf4c59173ec1b /arch/sh/kernel/cpu
parentf9369910a6225b8d4892c3f20ae740a711cd5ace (diff)
sh64: Convert to unwinder API.
This switches over to use the sh unwinder API which brings it all in line with the general sh routines (which we shuffle around at the same time), and lets us kill off more sh64-specific cruft. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/cpu')
-rw-r--r--arch/sh/kernel/cpu/sh5/unwind.c63
1 files changed, 41 insertions, 22 deletions
diff --git a/arch/sh/kernel/cpu/sh5/unwind.c b/arch/sh/kernel/cpu/sh5/unwind.c
index b205b25eaf45..10aed41757fc 100644
--- a/arch/sh/kernel/cpu/sh5/unwind.c
+++ b/arch/sh/kernel/cpu/sh5/unwind.c
@@ -16,6 +16,8 @@
16#include <asm/ptrace.h> 16#include <asm/ptrace.h>
17#include <asm/processor.h> 17#include <asm/processor.h>
18#include <asm/io.h> 18#include <asm/io.h>
19#include <asm/unwinder.h>
20#include <asm/stacktrace.h>
19 21
20static u8 regcache[63]; 22static u8 regcache[63];
21 23
@@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
199 return 0; 201 return 0;
200} 202}
201 203
202/* Don't put this on the stack since we'll want to call sh64_unwind 204/*
203 * when we're close to underflowing the stack anyway. */ 205 * Don't put this on the stack since we'll want to call in to
206 * sh64_unwinder_dump() when we're close to underflowing the stack
207 * anyway.
208 */
204static struct pt_regs here_regs; 209static struct pt_regs here_regs;
205 210
206extern const char syscall_ret; 211extern const char syscall_ret;
@@ -208,17 +213,19 @@ extern const char ret_from_syscall;
208extern const char ret_from_exception; 213extern const char ret_from_exception;
209extern const char ret_from_irq; 214extern const char ret_from_irq;
210 215
211static void sh64_unwind_inner(struct pt_regs *regs); 216static void sh64_unwind_inner(const struct stacktrace_ops *ops,
217 void *data, struct pt_regs *regs);
212 218
213static void unwind_nested (unsigned long pc, unsigned long fp) 219static inline void unwind_nested(const struct stacktrace_ops *ops, void *data,
220 unsigned long pc, unsigned long fp)
214{ 221{
215 if ((fp >= __MEMORY_START) && 222 if ((fp >= __MEMORY_START) &&
216 ((fp & 7) == 0)) { 223 ((fp & 7) == 0))
217 sh64_unwind_inner((struct pt_regs *) fp); 224 sh64_unwind_inner(ops, data, (struct pt_regs *)fp);
218 }
219} 225}
220 226
221static void sh64_unwind_inner(struct pt_regs *regs) 227static void sh64_unwind_inner(const struct stacktrace_ops *ops,
228 void *data, struct pt_regs *regs)
222{ 229{
223 unsigned long pc, fp; 230 unsigned long pc, fp;
224 int ofs = 0; 231 int ofs = 0;
@@ -232,29 +239,29 @@ static void sh64_unwind_inner(struct pt_regs *regs)
232 int cond; 239 int cond;
233 unsigned long next_fp, next_pc; 240 unsigned long next_fp, next_pc;
234 241
235 if (pc == ((unsigned long) &syscall_ret & ~1)) { 242 if (pc == ((unsigned long)&syscall_ret & ~1)) {
236 printk("SYSCALL\n"); 243 printk("SYSCALL\n");
237 unwind_nested(pc,fp); 244 unwind_nested(ops, data, pc, fp);
238 return; 245 return;
239 } 246 }
240 247
241 if (pc == ((unsigned long) &ret_from_syscall & ~1)) { 248 if (pc == ((unsigned long)&ret_from_syscall & ~1)) {
242 printk("SYSCALL (PREEMPTED)\n"); 249 printk("SYSCALL (PREEMPTED)\n");
243 unwind_nested(pc,fp); 250 unwind_nested(ops, data, pc, fp);
244 return; 251 return;
245 } 252 }
246 253
247 /* In this case, the PC is discovered by lookup_prev_stack_frame but 254 /* In this case, the PC is discovered by lookup_prev_stack_frame but
248 it has 4 taken off it to look like the 'caller' */ 255 it has 4 taken off it to look like the 'caller' */
249 if (pc == ((unsigned long) &ret_from_exception & ~1)) { 256 if (pc == ((unsigned long)&ret_from_exception & ~1)) {
250 printk("EXCEPTION\n"); 257 printk("EXCEPTION\n");
251 unwind_nested(pc,fp); 258 unwind_nested(ops, data, pc, fp);
252 return; 259 return;
253 } 260 }
254 261
255 if (pc == ((unsigned long) &ret_from_irq & ~1)) { 262 if (pc == ((unsigned long)&ret_from_irq & ~1)) {
256 printk("IRQ\n"); 263 printk("IRQ\n");
257 unwind_nested(pc,fp); 264 unwind_nested(ops, data, pc, fp);
258 return; 265 return;
259 } 266 }
260 267
@@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs)
263 270
264 pc -= ofs; 271 pc -= ofs;
265 272
266 printk("[<%08lx>] ", pc); 273 ops->address(data, pc, 1);
267 print_symbol("%s\n", pc);
268 274
269 if (first_pass) { 275 if (first_pass) {
270 /* If the innermost frame is a leaf function, it's 276 /* If the innermost frame is a leaf function, it's
@@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)
287 } 293 }
288 294
289 printk("\n"); 295 printk("\n");
290
291} 296}
292 297
293void sh64_unwind(struct pt_regs *regs) 298static void sh64_unwinder_dump(struct task_struct *task,
299 struct pt_regs *regs,
300 unsigned long *sp,
301 const struct stacktrace_ops *ops,
302 void *data)
294{ 303{
295 if (!regs) { 304 if (!regs) {
296 /* 305 /*
@@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs)
320 ); 329 );
321 } 330 }
322 331
323 printk("\nCall Trace:\n"); 332 sh64_unwind_inner(ops, data, regs);
324 sh64_unwind_inner(regs);
325} 333}
326 334
335static struct unwinder sh64_unwinder = {
336 .name = "sh64-unwinder",
337 .dump = sh64_unwinder_dump,
338 .rating = 150,
339};
340
341static int __init sh64_unwinder_init(void)
342{
343 return unwinder_register(&sh64_unwinder);
344}
345early_initcall(sh64_unwinder_init);