49 lines
1.6 KiB
Diff
49 lines
1.6 KiB
Diff
|
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
|
||
|
|
||
|
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>
|
||
|
Reviewed-by: Maciej W. Rozycki <macro@imgtec.com>
|
||
|
---
|
||
|
|
||
|
--- 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
|
||
|
|