123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- From: Matt Redfearn <matt.redfearn@imgtec.com>
- Date: Mon, 19 Dec 2016 14:20:59 +0000
- Subject: [PATCH] MIPS: Switch to the irq_stack in interrupts
- 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>
- ---
- --- a/arch/mips/kernel/genex.S
- +++ b/arch/mips/kernel/genex.S
- @@ -188,9 +188,44 @@ NESTED(handle_int, PT_SIZE, sp)
-
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
- - PTR_LA ra, ret_from_irq
- - PTR_LA v0, plat_irq_dispatch
- - jr v0
- +
- + /*
- + * SAVE_ALL ensures we are using a valid kernel stack for the thread.
- + * Check if we are already using the IRQ stack.
- + */
- + move s1, sp # Preserve the sp
- +
- + /* Get IRQ stack for this CPU */
- + ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
- +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
- + lui k1, %hi(irq_stack)
- +#else
- + lui k1, %highest(irq_stack)
- + daddiu k1, %higher(irq_stack)
- + dsll k1, 16
- + daddiu k1, %hi(irq_stack)
- + dsll k1, 16
- +#endif
- + LONG_SRL k0, SMP_CPUID_PTRSHIFT
- + LONG_ADDU k1, k0
- + LONG_L t0, %lo(irq_stack)(k1)
- +
- + # Check if already on IRQ stack
- + PTR_LI t1, ~(_THREAD_SIZE-1)
- + and t1, t1, sp
- + beq t0, t1, 2f
- +
- + /* Switch to IRQ stack */
- + li t1, _IRQ_STACK_SIZE
- + PTR_ADD sp, t0, t1
- +
- +2:
- + jal plat_irq_dispatch
- +
- + /* Restore sp */
- + move sp, s1
- +
- + j ret_from_irq
- #ifdef CONFIG_CPU_MICROMIPS
- nop
- #endif
- @@ -263,8 +298,44 @@ NESTED(except_vec_vi_handler, 0, sp)
-
- LONG_L s0, TI_REGS($28)
- LONG_S sp, TI_REGS($28)
- - PTR_LA ra, ret_from_irq
- - jr v0
- +
- + /*
- + * SAVE_ALL ensures we are using a valid kernel stack for the thread.
- + * Check if we are already using the IRQ stack.
- + */
- + move s1, sp # Preserve the sp
- +
- + /* Get IRQ stack for this CPU */
- + ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG
- +#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
- + lui k1, %hi(irq_stack)
- +#else
- + lui k1, %highest(irq_stack)
- + daddiu k1, %higher(irq_stack)
- + dsll k1, 16
- + daddiu k1, %hi(irq_stack)
- + dsll k1, 16
- +#endif
- + LONG_SRL k0, SMP_CPUID_PTRSHIFT
- + LONG_ADDU k1, k0
- + LONG_L t0, %lo(irq_stack)(k1)
- +
- + # Check if already on IRQ stack
- + PTR_LI t1, ~(_THREAD_SIZE-1)
- + and t1, t1, sp
- + beq t0, t1, 2f
- +
- + /* Switch to IRQ stack */
- + li t1, _IRQ_STACK_SIZE
- + PTR_ADD sp, t0, t1
- +
- +2:
- + jal plat_irq_dispatch
- +
- + /* Restore sp */
- + move sp, s1
- +
- + j ret_from_irq
- END(except_vec_vi_handler)
-
- /*
|