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

Commit 85218827 authored by Kumar Gala's avatar Kumar Gala Committed by Paul Mackerras
Browse files

[POWERPC] Add IRQSTACKS support on ppc32



This makes it possible to use separate stacks for hard and soft IRQs
on 32-bit powerpc as well as on 64-bit.  The code for 32-bit is just
the 32-bit analog of the 64-bit code.

* Added allocation and initialization of the irq stacks.  We limit the
  stacks to be in lowmem for ppc32.
* Implemented ppc32 versions of call_do_softirq() and call_handle_irq()
  to switch the stack pointers
* Reworked how we do stack overflow detection.  We now keep around the
  limit of the stack in the thread_struct and compare against the limit
  to see if we've overflowed.  We can now use this on ppc64 if desired.

[ paulus@samba.org: Fixed bug on 6xx where we need to reload r9 with the
  thread_info pointer. ]

Signed-off-by: default avatarKumar Gala <galak@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent dd18434f
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -118,7 +118,6 @@ config XMON_DISASSEMBLY

config IRQSTACKS
	bool "Use separate kernel stacks when processing interrupts"
	depends on PPC64
	help
	  If you say Y here the kernel will use separate kernel stacks
	  for handling hard and soft interrupts.  This can help avoid
+1 −0
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ int main(void)
#endif /* CONFIG_PPC64 */

	DEFINE(KSP, offsetof(struct thread_struct, ksp));
	DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit));
	DEFINE(PT_REGS, offsetof(struct thread_struct, regs));
	DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode));
	DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0]));
+3 −2
Original line number Diff line number Diff line
@@ -137,11 +137,12 @@ transfer_to_handler:
2:	/* if from kernel, check interrupted DOZE/NAP mode and
         * check for stack overflow
         */
	lwz	r9,THREAD_INFO-THREAD(r12)
	cmplw	r1,r9			/* if r1 <= current->thread_info */
	lwz	r9,KSP_LIMIT(r12)
	cmplw	r1,r9			/* if r1 <= ksp_limit */
	ble-	stack_ovf		/* then the kernel stack overflowed */
5:
#ifdef CONFIG_6xx
	rlwinm	r9,r1,0,0,31-THREAD_SHIFT
	tophys(r9,r9)			/* check local flags */
	lwz	r12,TI_LOCAL_FLAGS(r9)
	mtcrf	0x01,r12
+8 −2
Original line number Diff line number Diff line
@@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs)
		if (curtp != irqtp) {
			struct irq_desc *desc = irq_desc + irq;
			void *handler = desc->handle_irq;
			unsigned long saved_sp_limit = current->thread.ksp_limit;
			if (handler == NULL)
				handler = &__do_IRQ;
			irqtp->task = curtp->task;
@@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs)
				(irqtp->preempt_count & ~SOFTIRQ_MASK) |
				(curtp->preempt_count & SOFTIRQ_MASK);

			current->thread.ksp_limit = (unsigned long)irqtp +
				_ALIGN_UP(sizeof(struct thread_info), 16);
			call_handle_irq(irq, desc, irqtp, handler);
			current->thread.ksp_limit = saved_sp_limit;
			irqtp->task = NULL;


@@ -352,9 +356,7 @@ void __init init_IRQ(void)
{
	if (ppc_md.init_IRQ)
		ppc_md.init_IRQ();
#ifdef CONFIG_PPC64
	irq_ctx_init();
#endif
}


@@ -383,11 +385,15 @@ void irq_ctx_init(void)
static inline void do_softirq_onstack(void)
{
	struct thread_info *curtp, *irqtp;
	unsigned long saved_sp_limit = current->thread.ksp_limit;

	curtp = current_thread_info();
	irqtp = softirq_ctx[smp_processor_id()];
	irqtp->task = curtp->task;
	current->thread.ksp_limit = (unsigned long)irqtp +
				    _ALIGN_UP(sizeof(struct thread_info), 16);
	call_do_softirq(irqtp);
	current->thread.ksp_limit = saved_sp_limit;
	irqtp->task = NULL;
}

+25 −0
Original line number Diff line number Diff line
@@ -32,6 +32,31 @@

	.text

#ifdef CONFIG_IRQSTACKS
_GLOBAL(call_do_softirq)
	mflr	r0
	stw	r0,4(r1)
	stwu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3)
	mr	r1,r3
	bl	__do_softirq
	lwz	r1,0(r1)
	lwz	r0,4(r1)
	mtlr	r0
	blr

_GLOBAL(call_handle_irq)
	mflr	r0
	stw	r0,4(r1)
	mtctr	r6
	stwu	r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5)
	mr	r1,r5
	bctrl
	lwz	r1,0(r1)
	lwz	r0,4(r1)
	mtlr	r0
	blr
#endif /* CONFIG_IRQSTACKS */

/*
 * This returns the high 64 bits of the product of two 64-bit numbers.
 */
Loading