Skip to content

Commit b39b263

Browse files
mpredfearngregkh
authored andcommitted
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>
1 parent 93a82f8 commit b39b263

1 file changed

Lines changed: 76 additions & 5 deletions

File tree

arch/mips/kernel/genex.S

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,44 @@ NESTED(handle_int, PT_SIZE, sp)
188188

189189
LONG_L s0, TI_REGS($28)
190190
LONG_S sp, TI_REGS($28)
191-
PTR_LA ra, ret_from_irq
192-
PTR_LA v0, plat_irq_dispatch
193-
jr v0
191+
192+
/*
193+
* SAVE_ALL ensures we are using a valid kernel stack for the thread.
194+
* Check if we are already using the IRQ stack.
195+
*/
196+
move s1, sp # Preserve the sp
197+
198+
/* Get IRQ stack for this CPU */
199+
ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
200+
#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
201+
lui k1, %hi(irq_stack)
202+
#else
203+
lui k1, %highest(irq_stack)
204+
daddiu k1, %higher(irq_stack)
205+
dsll k1, 16
206+
daddiu k1, %hi(irq_stack)
207+
dsll k1, 16
208+
#endif
209+
LONG_SRL k0, SMP_CPUID_PTRSHIFT
210+
LONG_ADDU k1, k0
211+
LONG_L t0, %lo(irq_stack)(k1)
212+
213+
# Check if already on IRQ stack
214+
PTR_LI t1, ~(_THREAD_SIZE-1)
215+
and t1, t1, sp
216+
beq t0, t1, 2f
217+
218+
/* Switch to IRQ stack */
219+
li t1, _IRQ_STACK_SIZE
220+
PTR_ADD sp, t0, t1
221+
222+
2:
223+
jal plat_irq_dispatch
224+
225+
/* Restore sp */
226+
move sp, s1
227+
228+
j ret_from_irq
194229
#ifdef CONFIG_CPU_MICROMIPS
195230
nop
196231
#endif
@@ -263,8 +298,44 @@ NESTED(except_vec_vi_handler, 0, sp)
263298

264299
LONG_L s0, TI_REGS($28)
265300
LONG_S sp, TI_REGS($28)
266-
PTR_LA ra, ret_from_irq
267-
jr v0
301+
302+
/*
303+
* SAVE_ALL ensures we are using a valid kernel stack for the thread.
304+
* Check if we are already using the IRQ stack.
305+
*/
306+
move s1, sp # Preserve the sp
307+
308+
/* Get IRQ stack for this CPU */
309+
ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
310+
#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
311+
lui k1, %hi(irq_stack)
312+
#else
313+
lui k1, %highest(irq_stack)
314+
daddiu k1, %higher(irq_stack)
315+
dsll k1, 16
316+
daddiu k1, %hi(irq_stack)
317+
dsll k1, 16
318+
#endif
319+
LONG_SRL k0, SMP_CPUID_PTRSHIFT
320+
LONG_ADDU k1, k0
321+
LONG_L t0, %lo(irq_stack)(k1)
322+
323+
# Check if already on IRQ stack
324+
PTR_LI t1, ~(_THREAD_SIZE-1)
325+
and t1, t1, sp
326+
beq t0, t1, 2f
327+
328+
/* Switch to IRQ stack */
329+
li t1, _IRQ_STACK_SIZE
330+
PTR_ADD sp, t0, t1
331+
332+
2:
333+
jal plat_irq_dispatch
334+
335+
/* Restore sp */
336+
move sp, s1
337+
338+
j ret_from_irq
268339
END(except_vec_vi_handler)
269340

270341
/*

0 commit comments

Comments
 (0)