aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Redfearn <matt.redfearn@imgtec.com>2016-12-19 09:20:59 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-04-18 01:11:48 -0400
commite8fa51d31aee1714a02b1f5de72b0d624fd6b5cd (patch)
tree6c8308b017df73680b00de17254f71c6d2d74871
parentaa6b1dac465e7e5b1591482bbb51d332bfe13cc7 (diff)
MIPS: Switch to the irq_stack in interrupts
commit dda45f701c9d7ad4ac0bb446e3a96f6df9a468d9 upstream. When enterring interrupt context via handle_int or except_vec_vi, switch to the irq_stack of the current CPU if it is not already in use. The current stack pointer is masked with the thread size and compared to the base or the irq stack. If it does not match then the stack pointer is set to the top of that stack, otherwise this is a nested irq being handled on the irq stack so the stack pointer should be left as it was. The in-use stack pointer is placed in the callee saved register s1. It will be saved to the stack when plat_irq_dispatch is invoked and can be restored once control returns here. 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/14743/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Signed-off-by: Amit Pundir <amit.pundir@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/mips/kernel/genex.S81
1 files changed, 76 insertions, 5 deletions
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index 52a4fdfc8513..3a98ef64fdf0 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -187,9 +187,44 @@ NESTED(handle_int, PT_SIZE, sp)
187 187
188 LONG_L s0, TI_REGS($28) 188 LONG_L s0, TI_REGS($28)
189 LONG_S sp, TI_REGS($28) 189 LONG_S sp, TI_REGS($28)
190 PTR_LA ra, ret_from_irq 190
191 PTR_LA v0, plat_irq_dispatch 191 /*
192 jr v0 192 * SAVE_ALL ensures we are using a valid kernel stack for the thread.
193 * Check if we are already using the IRQ stack.
194 */
195 move s1, sp # Preserve the sp
196
197 /* Get IRQ stack for this CPU */
198 ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
199#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
200 lui k1, %hi(irq_stack)
201#else
202 lui k1, %highest(irq_stack)
203 daddiu k1, %higher(irq_stack)
204 dsll k1, 16
205 daddiu k1, %hi(irq_stack)
206 dsll k1, 16
207#endif
208 LONG_SRL k0, SMP_CPUID_PTRSHIFT
209 LONG_ADDU k1, k0
210 LONG_L t0, %lo(irq_stack)(k1)
211
212 # Check if already on IRQ stack
213 PTR_LI t1, ~(_THREAD_SIZE-1)
214 and t1, t1, sp
215 beq t0, t1, 2f
216
217 /* Switch to IRQ stack */
218 li t1, _IRQ_STACK_SIZE
219 PTR_ADD sp, t0, t1
220
2212:
222 jal plat_irq_dispatch
223
224 /* Restore sp */
225 move sp, s1
226
227 j ret_from_irq
193#ifdef CONFIG_CPU_MICROMIPS 228#ifdef CONFIG_CPU_MICROMIPS
194 nop 229 nop
195#endif 230#endif
@@ -262,8 +297,44 @@ NESTED(except_vec_vi_handler, 0, sp)
262 297
263 LONG_L s0, TI_REGS($28) 298 LONG_L s0, TI_REGS($28)
264 LONG_S sp, TI_REGS($28) 299 LONG_S sp, TI_REGS($28)
265 PTR_LA ra, ret_from_irq 300
266 jr v0 301 /*
302 * SAVE_ALL ensures we are using a valid kernel stack for the thread.
303 * Check if we are already using the IRQ stack.
304 */
305 move s1, sp # Preserve the sp
306
307 /* Get IRQ stack for this CPU */
308 ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
309#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
310 lui k1, %hi(irq_stack)
311#else
312 lui k1, %highest(irq_stack)
313 daddiu k1, %higher(irq_stack)
314 dsll k1, 16
315 daddiu k1, %hi(irq_stack)
316 dsll k1, 16
317#endif
318 LONG_SRL k0, SMP_CPUID_PTRSHIFT
319 LONG_ADDU k1, k0
320 LONG_L t0, %lo(irq_stack)(k1)
321
322 # Check if already on IRQ stack
323 PTR_LI t1, ~(_THREAD_SIZE-1)
324 and t1, t1, sp
325 beq t0, t1, 2f
326
327 /* Switch to IRQ stack */
328 li t1, _IRQ_STACK_SIZE
329 PTR_ADD sp, t0, t1
330
3312:
332 jal plat_irq_dispatch
333
334 /* Restore sp */
335 move sp, s1
336
337 j ret_from_irq
267 END(except_vec_vi_handler) 338 END(except_vec_vi_handler)
268 339
269/* 340/*