[linuxppc-dev] powerpc/64e: External Proxy interrupt support

Tudor Laurentiu Laurentiu.Tudor at freescale.com
Sat Oct 8 01:27:44 EST 2011


Sorry about this. Please disregard.

---
Best Regards, Laurentiu

On 10/7/2011 5:15 PM, Laurentiu Tudor wrote:
> From: Scott Wood<scottwood at freescale.com>
>
> Adds support for External Proxy (a.k.a. CoreInt) interrupts on 64-bit
> kernels.  External Proxy combines interrupt delivery and
> acknowledgement, so simply returning from the interrupt without EOI
> or other action will not result in the interrupt being reasserted.
>
> When an external interrupt is deferred in this manner (whether
> external proxy is used or not), we set a flag in the PACA.  When we
> re-enable interrupts, either explicitly or as part of an exception
> return, we check the flag and branch to the interrupt exception
> vector as if hardware had delivered the interrupt.
>
> Another approach I considered was to use doorbells to replay the
> interrupt.  There are some problems with this:
>   - The timing of the actual delivery of the doorbell is undefined.
>     This means we can't be sure in an architected way that the
>     doorbell will happen before interrupts are again soft-disabled, at
>     which point (barring interrupt-controller specific actions such as
>     raising CTPR) we could take a higher priority interrupt and
>     overwrite the saved EPR.
>   - Doorbells have a lower priority than true external interrupt. This
>     means you could have a lower priority interrupt appear to preempt
>     a higher prio interrupt, once the higher priority interrupt
>     enables EE and the doorbell comes in.
>
> Signed-off-by: Scott Wood<scottwood at freescale.com>
>
> ---
> We need this patch to have reliable interrupts in hypervisor
> scenarios.
>
> arch/powerpc/include/asm/irq.h         |    2 +
>   arch/powerpc/include/asm/paca.h        |    4 ++
>   arch/powerpc/kernel/asm-offsets.c      |    3 +
>   arch/powerpc/kernel/entry_64.S         |    4 ++
>   arch/powerpc/kernel/exceptions-64e.S   |   94 +++++++++++++++++++++++++++-----
>   arch/powerpc/kernel/irq.c              |   11 ++++
>   arch/powerpc/platforms/85xx/p5020_ds.c |    5 --
>   7 files changed, 103 insertions(+), 20 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
> index c57a28e..c0a45e7 100644
> --- a/arch/powerpc/include/asm/irq.h
> +++ b/arch/powerpc/include/asm/irq.h
> @@ -332,5 +332,7 @@ extern void do_IRQ(struct pt_regs *regs);
>
>   int irq_choose_cpu(const struct cpumask *mask);
>
> +void deliver_pending_irq(void);
> +
>   #endif /* _ASM_IRQ_H */
>   #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
> index c1f65f5..e5af3e3 100644
> --- a/arch/powerpc/include/asm/paca.h
> +++ b/arch/powerpc/include/asm/paca.h
> @@ -134,6 +134,10 @@ struct paca_struct {
>   	u8 hard_enabled;		/* set if irqs are enabled in MSR */
>   	u8 io_sync;			/* writel() needs spin_unlock sync */
>   	u8 irq_work_pending;		/* IRQ_WORK interrupt while soft-disable */
> +#ifdef CONFIG_PPC_BOOK3E
> +	/* an irq is pending while soft-disabled */
> +	u8 irq_pending;
> +#endif
>
>   	/* Stuff for accurate time accounting */
>   	u64 user_time;			/* accumulated usermode TB ticks */
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index c98144f..5082ee7 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -206,6 +206,9 @@ int main(void)
>   	DEFINE(SVCPU_SLB, offsetof(struct kvmppc_book3s_shadow_vcpu, slb));
>   	DEFINE(SVCPU_SLB_MAX, offsetof(struct kvmppc_book3s_shadow_vcpu, slb_max));
>   #endif
> +#ifdef CONFIG_PPC_BOOK3E
> +	DEFINE(PACA_IRQ_PENDING, offsetof(struct paca_struct, irq_pending));
> +#endif
>   #endif /* CONFIG_PPC64 */
>
>   	/* RTAS */
> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
> index d834425..c1d8eea 100644
> --- a/arch/powerpc/kernel/entry_64.S
> +++ b/arch/powerpc/kernel/entry_64.S
> @@ -596,6 +596,9 @@ _GLOBAL(ret_from_except_lite)
>   restore:
>   BEGIN_FW_FTR_SECTION
>   	ld	r5,SOFTE(r1)
> +#ifdef CONFIG_PPC_BOOK3E
> +	lbz	r6,PACA_IRQ_PENDING(r13)
> +#endif
>   FW_FTR_SECTION_ELSE
>   	b	.Liseries_check_pending_irqs
>   ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
> @@ -608,6 +611,7 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES)
>   	stb	r4,PACAHARDIRQEN(r13)
>
>   #ifdef CONFIG_PPC_BOOK3E
> +	/* consumes r3-r6 */
>   	b	.exception_return_book3e
>   #else
>   	ld	r4,_CTR(r1)
> diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
> index 429983c..9886be9 100644
> --- a/arch/powerpc/kernel/exceptions-64e.S
> +++ b/arch/powerpc/kernel/exceptions-64e.S
> @@ -2,6 +2,7 @@
>    *  Boot code and exception vectors for Book3E processors
>    *
>    *  Copyright (C) 2007 Ben. Herrenschmidt (benh at kernel.crashing.org), IBM Corp.
> + *  Copyright 2011 Freescale Semiconductor, Inc.
>    *
>    *  This program is free software; you can redistribute it and/or
>    *  modify it under the terms of the GNU General Public License
> @@ -125,6 +126,10 @@
>   	cmpwi	cr0,r11,0;		/* yes ->  go out of line */	    \
>   	beq	masked_doorbell_book3e
>
> +#define PROLOG_ADDITION_EXTIRQ_GEN					    \
> +	lbz	r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */	    \
> +	cmpwi	cr0,r11,0;		/* yes ->  go out of line */	    \
> +	beq	masked_extirq_book3e
>
>   /* Core exception code for all exceptions except TLB misses.
>    * XXX: Needs to make SPRN_SPRG_GEN depend on exception type
> @@ -325,7 +330,13 @@ interrupt_end_book3e:
>   	b	storage_fault_common
>
>   /* External Input Interrupt */
> -	MASKABLE_EXCEPTION(0x500, external_input, .do_IRQ, ACK_NONE)
> +	START_EXCEPTION(external_input)
> +	NORMAL_EXCEPTION_PROLOG(0x500, PROLOG_ADDITION_EXTIRQ)
> +	EXCEPTION_COMMON(0x500, PACA_EXGEN, INTS_DISABLE_ALL)
> +	CHECK_NAPPING()
> +	addi	r3,r1,STACK_FRAME_OVERHEAD
> +	bl	.do_IRQ
> +	b	.ret_from_except_lite
>
>   /* Alignment */
>   	START_EXCEPTION(alignment);
> @@ -557,6 +568,12 @@ kernel_dbg_exc:
>    * An interrupt came in while soft-disabled; clear EE in SRR1,
>    * clear paca->hard_enabled and return.
>    */
> +masked_extirq_book3e:
> +	mtcr	r10
> +	li	r10,1
> +	stb	r10,PACA_IRQ_PENDING(r13)
> +	b	masked_interrupt_book3e_common
> +
>   masked_doorbell_book3e:
>   	mtcr	r10
>   	/* Resend the doorbell to fire again when ints enabled */
> @@ -618,20 +635,8 @@ alignment_more:
>   	bl	.alignment_exception
>   	b	.ret_from_except
>
> -/*
> - * We branch here from entry_64.S for the last stage of the exception
> - * return code path. MSR:EE is expected to be off at that point
> - */
> -_GLOBAL(exception_return_book3e)
> -	b	1f
> -
> -/* This is the return from load_up_fpu fast path which could do with
> - * less GPR restores in fact, but for now we have a single return path
> - */
> -	.globl fast_exception_return
> -fast_exception_return:
> -	wrteei	0
> -1:	mr	r0,r13
> +.macro exception_restore
> +	mr	r0,r13
>   	ld	r10,_MSR(r1)
>   	REST_4GPRS(2, r1)
>   	andi.	r6,r10,MSR_PR
> @@ -667,8 +672,67 @@ fast_exception_return:
>   	ld	r10,PACA_EXGEN+EX_R10(r13)
>   	ld	r11,PACA_EXGEN+EX_R11(r13)
>   	mfspr	r13,SPRN_SPRG_GEN_SCRATCH
> +.endm
> +
> +/*
> + * We branch here from entry_64.S for the last stage of the exception
> + * return code path. MSR:EE is expected to be off at that point
> + * r3 = MSR for return context
> + * r4 = hard irq-enable status for return context
> + * r5 = soft irq-enable status for return context
> + * r6 = irq pending flag
> + */
> +_GLOBAL(exception_return_book3e)
> +	cmpwi	r6,0
> +	beq	common_exception_return
> +
> +/*
> + * There's an interrupt pending.  If we're returning to a context that
> + * is soft-irq-enabled, we need to deliver the interrupt now.
> + *
> + * We should never get here with soft IRQs enabled but hard IRQs disabled,
> + * but just to be sure, check that too.
> + */
> +	cmpwi	r5,0
> +	beq	common_exception_return
> +	cmpwi	r4,0
> +	beq	common_exception_return
> +
> +	lis	r5,(MSR_CE | MSR_ME | MSR_DE)@h
> +	li	r4,0
> +	ori	r5,r5,(MSR_CE | MSR_ME | MSR_DE)@l
> +	stb	r4,PACA_IRQ_PENDING(r13)
> +	and	r5,r5,r3
> +	oris	r5,r5,MSR_CM at h
> +	mtmsr	r5
> +
> +	exception_restore
> +	b	exc_external_input_book3e
> +
> +/* This is the return from load_up_fpu fast path which could do with
> + * less GPR restores in fact, but for now we have a single return path
> + */
> +	.globl fast_exception_return
> +fast_exception_return:
> +	wrteei	0
> +common_exception_return:
> +	exception_restore
>   	rfi
>
> +/* Called from arch_local_irq_restore() prior to hard-enabling interrupts */
> +_GLOBAL(deliver_pending_irq)
> +	mflr	r3
> +	mfmsr	r4
> +	lis	r5,(MSR_CM | MSR_CE | MSR_ME | MSR_DE)@h
> +	ori	r5,r5,(MSR_CM | MSR_CE | MSR_ME | MSR_DE)@l
> +	and	r5,r5,r4
> +	ori	r4,r4,MSR_EE
> +
> +	mtspr	SPRN_SRR0,r3
> +	mtspr	SPRN_SRR1,r4
> +	mtmsr	r5
> +	b	exc_external_input_book3e
> +
>   /*
>    * Trampolines used when spotting a bad kernel stack pointer in
>    * the exception entry code.
> diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
> index d281fb6..44a23d0 100644
> --- a/arch/powerpc/kernel/irq.c
> +++ b/arch/powerpc/kernel/irq.c
> @@ -184,6 +184,17 @@ notrace void arch_local_irq_restore(unsigned long en)
>   		lv1_get_version_info(&tmp);
>   	}
>
> +#ifdef CONFIG_PPC_BOOK3E
> +	/*
> +	 * If there's a pending IRQ, deliver it now.  Interrupts
> +	 * will be hard-enabled on return.
> +	 */
> +	if (get_paca()->irq_pending) {
> +		get_paca()->irq_pending = 0;
> +		deliver_pending_irq();
> +	}
> +#endif
> +
>   	__hard_irq_enable();
>   }
>   EXPORT_SYMBOL(arch_local_irq_restore);
> diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c
> index e8cba50..87e7d29 100644
> --- a/arch/powerpc/platforms/85xx/p5020_ds.c
> +++ b/arch/powerpc/platforms/85xx/p5020_ds.c
> @@ -76,12 +76,7 @@ define_machine(p5020_ds) {
>   #ifdef CONFIG_PCI
>   	.pcibios_fixup_bus	= fsl_pcibios_fixup_bus,
>   #endif
> -/* coreint doesn't play nice with lazy EE, use legacy mpic for now */
> -#ifdef CONFIG_PPC64
> -	.get_irq		= mpic_get_irq,
> -#else
>   	.get_irq		= mpic_get_coreint_irq,
> -#endif
>   	.restart		= fsl_rstcr_restart,
>   	.calibrate_decr		= generic_calibrate_decr,
>   	.progress		= udbg_progress,
> _______________________________________________
> linuxppc-dev mailing list
> linuxppc-dev at linux.freescale.net
> http://linux.freescale.net/mailman/listinfo/linuxppc-dev





More information about the Linuxppc-dev mailing list