Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b39b2638 authored by Matt Redfearn's avatar Matt Redfearn Committed by Greg Kroah-Hartman
Browse files

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: default avatarMatt Redfearn <matt.redfearn@imgtec.com>
Acked-by: default avatarJason 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: default avatarRalf Baechle <ralf@linux-mips.org>
Signed-off-by: default avatarAmit Pundir <amit.pundir@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 93a82f8d
Loading
Loading
Loading
Loading
+76 −5
Original line number Diff line number Diff line
@@ -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)

/*