Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754339AbbK0PBd (ORCPT ); Fri, 27 Nov 2015 10:01:33 -0500 Received: from mail-lf0-f44.google.com ([209.85.215.44]:35350 "EHLO mail-lf0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751595AbbK0PBa (ORCPT ); Fri, 27 Nov 2015 10:01:30 -0500 From: Max Filippov To: linux-xtensa@linux-xtensa.org Cc: Chris Zankel , Marc Gauthier , Petr Mladek , Peter Zijlstra , Steven Rostedt , LKML , Max Filippov Subject: [PATCH] xtensa: make fake NMI configurable Date: Fri, 27 Nov 2015 18:00:50 +0300 Message-Id: <1448636450-14150-1-git-send-email-jcmvbkbc@gmail.com> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4295 Lines: 125 Do not always use fake NMI when safe, provide Kconfig option instead. Print a warning if fake NMI is chosen in unsafe configuration, but allow it, because it may work if the user knows that interrupts with priorities at or above PMM IRQ are not used. Add a check to NMI handler that BUGs if any of these IRQs fire. Signed-off-by: Max Filippov --- arch/xtensa/Kconfig | 16 ++++++++++++++++ arch/xtensa/include/asm/processor.h | 12 +++++------- arch/xtensa/kernel/traps.c | 27 +++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 3bd3504..401f905 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -138,6 +138,22 @@ config XTENSA_VARIANT_HAVE_PERF_EVENTS If unsure, say N. +config XTENSA_FAKE_NMI + bool "Treat PMM IRQ as NMI" + depends on XTENSA_VARIANT_HAVE_PERF_EVENTS + default n + help + If PMM IRQ is the only IRQ at EXCM level it is safe to + treat it as NMI, which improves accuracy of profiling. + + If there are other interrupts at or above PMM IRQ priority level + but not above the EXCM level, PMM IRQ still may be treated as NMI, + but only if these IRQs are not used. There will be a build warning + saying that this is not safe, and a bugcheck if one of these IRQs + actually fire. + + If unsure, say N. + config XTENSA_UNALIGNED_USER bool "Unaligned memory access in use space" help diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 83e2e4bc..744ecf0 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h @@ -78,22 +78,20 @@ #define XTENSA_INTLEVEL_MASK(level) _XTENSA_INTLEVEL_MASK(level) #define _XTENSA_INTLEVEL_MASK(level) (XCHAL_INTLEVEL##level##_MASK) -#define IS_POW2(v) (((v) & ((v) - 1)) == 0) +#define XTENSA_INTLEVEL_ANDBELOW_MASK(l) _XTENSA_INTLEVEL_ANDBELOW_MASK(l) +#define _XTENSA_INTLEVEL_ANDBELOW_MASK(l) (XCHAL_INTLEVEL##l##_ANDBELOW_MASK) #define PROFILING_INTLEVEL XTENSA_INT_LEVEL(XCHAL_PROFILING_INTERRUPT) /* LOCKLEVEL defines the interrupt level that masks all * general-purpose interrupts. */ -#if defined(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) && \ - defined(XCHAL_PROFILING_INTERRUPT) && \ - PROFILING_INTLEVEL == XCHAL_EXCM_LEVEL && \ - XCHAL_EXCM_LEVEL > 1 && \ - IS_POW2(XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL)) -#define LOCKLEVEL (XCHAL_EXCM_LEVEL - 1) +#if defined(CONFIG_XTENSA_FAKE_NMI) && defined(XCHAL_PROFILING_INTERRUPT) +#define LOCKLEVEL (PROFILING_INTLEVEL - 1) #else #define LOCKLEVEL XCHAL_EXCM_LEVEL #endif + #define TOPLEVEL XCHAL_EXCM_LEVEL #define XTENSA_FAKE_NMI (LOCKLEVEL < TOPLEVEL) diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index 42d441f..be0cae8 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -205,6 +205,32 @@ extern void do_IRQ(int, struct pt_regs *); #if XTENSA_FAKE_NMI +#define IS_POW2(v) (((v) & ((v) - 1)) == 0) + +#if !(PROFILING_INTLEVEL == XCHAL_EXCM_LEVEL && \ + IS_POW2(XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL))) +#warning "Fake NMI is requested for PMM, but there are other IRQs at or above its level." +#warning "Fake NMI will be used, but there will be a bugcheck if one of those IRQs fire." + +static inline void check_valid_nmi(void) +{ + unsigned intread = get_sr(interrupt); + unsigned intenable = get_sr(intenable); + + BUG_ON(intread & intenable & + ~(XTENSA_INTLEVEL_ANDBELOW_MASK(PROFILING_INTLEVEL) ^ + XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL) ^ + BIT(XCHAL_PROFILING_INTERRUPT))); +} + +#else + +static inline void check_valid_nmi(void) +{ +} + +#endif + irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id); DEFINE_PER_CPU(unsigned long, nmi_count); @@ -219,6 +245,7 @@ void do_nmi(struct pt_regs *regs) old_regs = set_irq_regs(regs); nmi_enter(); ++*this_cpu_ptr(&nmi_count); + check_valid_nmi(); xtensa_pmu_irq_handler(0, NULL); nmi_exit(); set_irq_regs(old_regs); -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/