[PATCH] powerpc/64s: fix may_hard_irq_enable for PMI soft masking
Madhavan Srinivasan
maddy at linux.vnet.ibm.com
Tue Feb 6 21:00:43 AEDT 2018
On Saturday 03 February 2018 12:47 PM, Nicholas Piggin wrote:
> vThe soft IRQ masking code has to hard-disable interrupts in cases
> where the exception is not cleared by the masked handler. External
> interrupts used this approach for soft masking. Now recently PMU
> interrupts do the same thing.
>
> The soft IRQ masking code additionally allowed for interrupt handlers
> to hard-enable interrupts after soft-disabling them. The idea is to
> allow PMU interrupts through to profile interrupt handlers.
>
> So when interrupts are being replayed when there is a pending
> interrupt that requires hard-disabling, there is a test to prevent
> those handlers from hard-enabling them if there is a pending external
> interrupt. may_hard_irq_enable() handles this.
>
> After f442d00480 ("powerpc/64s: Add support to mask perf interrupts
> and replay them"), may_hard_irq_enable() could prematurely enable
> MSR[EE] when a PMU exception exists, which would result in the
> interrupt firing again while masked, and MSR[EE] being disabled again.
>
> I haven't seen that this could cause a serious problem, but it's
> more consistent to handle these soft-masked interrupts in the same
> way. So introduce a define for all types of interrupts that require
> MSR[EE] masking in their soft-disable handlers, and use that in
> may_hard_irq_enable().
>
> Cc: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
> Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
Yes nice catch. We could get into a messy state.
May be if I run my perf+kernbench longer, could get lucky.
Reviewed-by: Madhavan Srinivasan <maddy at linux.vnet.ibm.com>
> ---
> Hi,
>
> A review of this would be helpful. I think it probably might as well
> go into 4.16 unless I misunderstood the code. My changelog got a bit
> long-winded in the end, I could try improve it if it's hard to
> understand.
>
> Thanks,
> Nick
>
> arch/powerpc/include/asm/hw_irq.h | 12 +++++++++++-
> arch/powerpc/kernel/exceptions-64e.S | 2 ++
> arch/powerpc/kernel/exceptions-64s.S | 6 +++---
> 3 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
> index 88e5e8f17e98..855e17d158b1 100644
> --- a/arch/powerpc/include/asm/hw_irq.h
> +++ b/arch/powerpc/include/asm/hw_irq.h
> @@ -29,6 +29,16 @@
> #define PACA_IRQ_HMI 0x20
> #define PACA_IRQ_PMI 0x40
>
> +/*
> + * Some soft-masked interrupts must be hard masked until they are replayed
> + * (e.g., because the soft-masked handler does not clear the exception).
> + */
> +#ifdef CONFIG_PPC_BOOK3S
> +#define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE|PACA_IRQ_PMI)
> +#else
> +#define PACA_IRQ_MUST_HARD_MASK (PACA_IRQ_EE)
> +#endif
> +
> /*
> * flags for paca->irq_soft_mask
> */
> @@ -244,7 +254,7 @@ static inline bool lazy_irq_pending(void)
> static inline void may_hard_irq_enable(void)
> {
> get_paca()->irq_happened &= ~PACA_IRQ_HARD_DIS;
> - if (!(get_paca()->irq_happened & PACA_IRQ_EE))
> + if (!(get_paca()->irq_happened & PACA_IRQ_MUST_HARD_MASK))
> __hard_irq_enable();
> }
>
> diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
> index ee832d344a5a..9b6e653e501a 100644
> --- a/arch/powerpc/kernel/exceptions-64e.S
> +++ b/arch/powerpc/kernel/exceptions-64e.S
> @@ -943,6 +943,8 @@ kernel_dbg_exc:
> /*
> * An interrupt came in while soft-disabled; We mark paca->irq_happened
> * accordingly and if the interrupt is level sensitive, we hard disable
> + * hard disable (full_mask) corresponds to PACA_IRQ_MUST_HARD_MASK, so
> + * keep these in synch.
> */
>
> .macro masked_interrupt_book3e paca_irq full_mask
> diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
> index 243d072a225a..3ac87e53b3da 100644
> --- a/arch/powerpc/kernel/exceptions-64s.S
> +++ b/arch/powerpc/kernel/exceptions-64s.S
> @@ -1426,7 +1426,7 @@ EXC_COMMON_BEGIN(soft_nmi_common)
> * triggered and won't automatically refire.
> * - If it was a HMI we return immediately since we handled it in realmode
> * and it won't refire.
> - * - else we hard disable and return.
> + * - Else it is one of PACA_IRQ_MUST_HARD_MASK, so hard disable and return.
> * This is called with r10 containing the value to OR to the paca field.
> */
> #define MASKED_INTERRUPT(_H) \
> @@ -1441,8 +1441,8 @@ masked_##_H##interrupt: \
> ori r10,r10,0xffff; \
> mtspr SPRN_DEC,r10; \
> b MASKED_DEC_HANDLER_LABEL; \
> -1: andi. r10,r10,(PACA_IRQ_DBELL|PACA_IRQ_HMI); \
> - bne 2f; \
> +1: andi. r10,r10,PACA_IRQ_MUST_HARD_MASK; \
> + beq 2f; \
> mfspr r10,SPRN_##_H##SRR1; \
> xori r10,r10,MSR_EE; /* clear MSR_EE */ \
> mtspr SPRN_##_H##SRR1,r10; \
More information about the Linuxppc-dev
mailing list