| From 9352aeada4d8d8753fc0e414fbfe8fdfcb68a12c Mon Sep 17 00:00:00 2001 |
| From: John David Anglin <dave.anglin@bell.net> |
| Date: Mon, 13 Nov 2017 19:35:33 -0500 |
| Subject: Revert "parisc: Re-enable interrupts early" |
| |
| From: John David Anglin <dave.anglin@bell.net> |
| |
| commit 9352aeada4d8d8753fc0e414fbfe8fdfcb68a12c upstream. |
| |
| This reverts commit 5c38602d83e584047906b41b162ababd4db4106d. |
| |
| Interrupts can't be enabled early because the register saves are done on |
| the thread stack prior to switching to the IRQ stack. This caused stack |
| overflows and the thread stack needed increasing to 32k. Even then, |
| stack overflows still occasionally occurred. |
| |
| Background: |
| Even with a 32 kB thread stack, I have seen instances where the thread |
| stack overflowed on the mx3210 buildd. Detection of stack overflow only |
| occurs when we have an external interrupt. When an external interrupt |
| occurs, we switch to the thread stack if we are not already on a kernel |
| stack. Then, registers and specials are saved to the kernel stack. |
| |
| The bug occurs in intr_return where interrupts are reenabled prior to |
| returning from the interrupt. This was done incase we need to schedule |
| or deliver signals. However, it introduces the possibility that |
| multiple external interrupts may occur on the thread stack and cause a |
| stack overflow. These might not be detected and cause the kernel to |
| misbehave in random ways. |
| |
| This patch changes the code back to only reenable interrupts when we are |
| going to schedule or deliver signals. As a result, we generally return |
| from an interrupt before reenabling interrupts. This minimizes the |
| growth of the thread stack. |
| |
| Fixes: 5c38602d83e5 ("parisc: Re-enable interrupts early") |
| Signed-off-by: John David Anglin <dave.anglin@bell.net> |
| Signed-off-by: Helge Deller <deller@gmx.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/parisc/kernel/entry.S | 12 +++++++++--- |
| 1 file changed, 9 insertions(+), 3 deletions(-) |
| |
| --- a/arch/parisc/kernel/entry.S |
| +++ b/arch/parisc/kernel/entry.S |
| @@ -878,9 +878,6 @@ ENTRY_CFI(syscall_exit_rfi) |
| STREG %r19,PT_SR7(%r16) |
| |
| intr_return: |
| - /* NOTE: Need to enable interrupts incase we schedule. */ |
| - ssm PSW_SM_I, %r0 |
| - |
| /* check for reschedule */ |
| mfctl %cr30,%r1 |
| LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ |
| @@ -907,6 +904,11 @@ intr_check_sig: |
| LDREG PT_IASQ1(%r16), %r20 |
| cmpib,COND(=),n 0,%r20,intr_restore /* backward */ |
| |
| + /* NOTE: We need to enable interrupts if we have to deliver |
| + * signals. We used to do this earlier but it caused kernel |
| + * stack overflows. */ |
| + ssm PSW_SM_I, %r0 |
| + |
| copy %r0, %r25 /* long in_syscall = 0 */ |
| #ifdef CONFIG_64BIT |
| ldo -16(%r30),%r29 /* Reference param save area */ |
| @@ -958,6 +960,10 @@ intr_do_resched: |
| cmpib,COND(=) 0, %r20, intr_do_preempt |
| nop |
| |
| + /* NOTE: We need to enable interrupts if we schedule. We used |
| + * to do this earlier but it caused kernel stack overflows. */ |
| + ssm PSW_SM_I, %r0 |
| + |
| #ifdef CONFIG_64BIT |
| ldo -16(%r30),%r29 /* Reference param save area */ |
| #endif |