| From 62418a5b5ca62429b4984bb9b7d6e865a676d4ae Mon Sep 17 00:00:00 2001 |
| From: Matt Redfearn <matt.redfearn@imgtec.com> |
| Date: Mon, 19 Dec 2016 14:20:58 +0000 |
| Subject: [PATCH] MIPS: Only change $28 to thread_info if coming from user mode |
| |
| commit 510d86362a27577f5ee23f46cfb354ad49731e61 upstream. |
| |
| The SAVE_SOME macro is used to save the execution context on all |
| exceptions. |
| If an exception occurs while executing user code, the stack is switched |
| to the kernel's stack for the current task, and register $28 is switched |
| to point to the current_thread_info, which is at the bottom of the stack |
| region. |
| If the exception occurs while executing kernel code, the stack is left, |
| and this change ensures that register $28 is not updated. This is the |
| correct behaviour when the kernel can be executing on the separate irq |
| stack, because the thread_info will not be at the base of it. |
| |
| With this change, register $28 is only switched to it's kernel |
| conventional usage of the currrent thread info pointer at the point at |
| which execution enters kernel space. Doing it on every exception was |
| redundant, but OK without an IRQ stack, but will be erroneous once that |
| is introduced. |
| |
| Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com> |
| Acked-by: Jason A. Donenfeld <jason@zx2c4.com> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: James Hogan <james.hogan@imgtec.com> |
| Cc: Paul Burton <paul.burton@imgtec.com> |
| Cc: linux-mips@linux-mips.org |
| Cc: linux-kernel@vger.kernel.org |
| Patchwork: https://patchwork.linux-mips.org/patch/14742/ |
| Signed-off-by: Ralf Baechle <ralf@linux-mips.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h |
| index eebf39549606..2f182bdf024f 100644 |
| --- a/arch/mips/include/asm/stackframe.h |
| +++ b/arch/mips/include/asm/stackframe.h |
| @@ -216,12 +216,19 @@ |
| LONG_S $25, PT_R25(sp) |
| LONG_S $28, PT_R28(sp) |
| LONG_S $31, PT_R31(sp) |
| + |
| + /* Set thread_info if we're coming from user mode */ |
| + mfc0 k0, CP0_STATUS |
| + sll k0, 3 /* extract cu0 bit */ |
| + bltz k0, 9f |
| + |
| ori $28, sp, _THREAD_MASK |
| xori $28, _THREAD_MASK |
| #ifdef CONFIG_CPU_CAVIUM_OCTEON |
| .set mips64 |
| pref 0, 0($28) /* Prefetch the current pointer */ |
| #endif |
| +9: |
| .set pop |
| .endm |
| |
| -- |
| 2.12.0 |
| |