diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-08 10:09:55 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-02-08 10:09:55 -0800 |
commit | 8bd73803e18354add19b050d05770b646ecbffd0 (patch) | |
tree | c2aa0467418491890b972177dfc64f7fe8e47d9b /arch/sh/kernel/dwarf.c | |
parent | 6339204ecc2aa2067a99595522de0403f0854bb8 (diff) | |
parent | 1af0b2fc676009d9b5b71a82ea6a3c2b20b7ea56 (diff) | |
download | op-kernel-dev-8bd73803e18354add19b050d05770b646ecbffd0.zip op-kernel-dev-8bd73803e18354add19b050d05770b646ecbffd0.tar.gz |
Merge branch 'sh/for-2.6.33' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
* 'sh/for-2.6.33' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6:
sh: Remove superfluous setup_frame_reg call
sh: Don't continue unwinding across interrupts
sh: Setup frame pointer in handle_exception path
sh: Correct the offset of the return address in ret_from_exception
usb: r8a66597-hcd: Fix up spinlock recursion in root hub polling.
usb: r8a66597-hcd: Flush the D-cache for the pipe-in transfer buffers.
Diffstat (limited to 'arch/sh/kernel/dwarf.c')
-rw-r--r-- | arch/sh/kernel/dwarf.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c index 88d28ec..e511680 100644 --- a/arch/sh/kernel/dwarf.c +++ b/arch/sh/kernel/dwarf.c @@ -540,6 +540,8 @@ void dwarf_free_frame(struct dwarf_frame *frame) mempool_free(frame, dwarf_frame_pool); } +extern void ret_from_irq(void); + /** * dwarf_unwind_stack - unwind the stack * @@ -678,6 +680,24 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc, addr = frame->cfa + reg->addr; frame->return_addr = __raw_readl(addr); + /* + * Ah, the joys of unwinding through interrupts. + * + * Interrupts are tricky - the DWARF info needs to be _really_ + * accurate and unfortunately I'm seeing a lot of bogus DWARF + * info. For example, I've seen interrupts occur in epilogues + * just after the frame pointer (r14) had been restored. The + * problem was that the DWARF info claimed that the CFA could be + * reached by using the value of the frame pointer before it was + * restored. + * + * So until the compiler can be trusted to produce reliable + * DWARF info when it really matters, let's stop unwinding once + * we've calculated the function that was interrupted. + */ + if (prev && prev->pc == (unsigned long)ret_from_irq) + frame->return_addr = 0; + return frame; bail: |