| From 808be31426af57af22268ef0fcb42617beb3d15b Mon Sep 17 00:00:00 2001 |
| From: Anton Blanchard <anton@samba.org> |
| Date: Fri, 31 Oct 2014 16:50:57 +1100 |
| Subject: powerpc: do_notify_resume can be called with bad thread_info flags argument |
| |
| From: Anton Blanchard <anton@samba.org> |
| |
| commit 808be31426af57af22268ef0fcb42617beb3d15b upstream. |
| |
| Back in 7230c5644188 ("powerpc: Rework lazy-interrupt handling") we |
| added a call out to restore_interrupts() (written in c) before calling |
| do_notify_resume: |
| |
| bl restore_interrupts |
| addi r3,r1,STACK_FRAME_OVERHEAD |
| bl do_notify_resume |
| |
| Unfortunately do_notify_resume takes two arguments, the second one |
| being the thread_info flags: |
| |
| void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |
| |
| We do populate r4 (the second argument) earlier, but |
| restore_interrupts() is free to muck it up all it wants. My guess is |
| the gcc compiler gods shone down on us and its register allocator |
| never used r4. Sometimes, rarely, luck is on our side. |
| |
| LLVM on the other hand did trample r4. |
| |
| Signed-off-by: Anton Blanchard <anton@samba.org> |
| Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/powerpc/kernel/entry_64.S | 6 ++++++ |
| 1 file changed, 6 insertions(+) |
| |
| --- a/arch/powerpc/kernel/entry_64.S |
| +++ b/arch/powerpc/kernel/entry_64.S |
| @@ -659,7 +659,13 @@ _GLOBAL(ret_from_except_lite) |
| 3: |
| #endif |
| bl save_nvgprs |
| + /* |
| + * Use a non volatile GPR to save and restore our thread_info flags |
| + * across the call to restore_interrupts. |
| + */ |
| + mr r30,r4 |
| bl restore_interrupts |
| + mr r4,r30 |
| addi r3,r1,STACK_FRAME_OVERHEAD |
| bl do_notify_resume |
| b ret_from_except |