mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Marc Zyngier <marc.zyngier@arm.com>
To: Julien Thierry <julien.thierry@arm.com>,
	linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org, rostedt@goodmis.org,
	yuzenghui@huawei.com, wanghaibin.wang@huawei.com,
	james.morse@arm.com, will.deacon@arm.com,
	catalin.marinas@arm.com, mark.rutland@arm.com,
	liwei391@huawei.com, Thomas Gleixner <tglx@linutronix.de>,
	Jason Cooper <jason@lakedaemon.net>
Subject: Re: [PATCH v3 4/8] arm64: Fix interrupt tracing in the presence of NMIs
Date: Fri, 7 Jun 2019 16:42:44 +0100	[thread overview]
Message-ID: <72cc234e-1c70-9356-bf53-0e3aa4ba43c5@arm.com> (raw)
In-Reply-To: <1559813517-41540-5-git-send-email-julien.thierry@arm.com>

On 06/06/2019 10:31, Julien Thierry wrote:
> In the presence of any form of instrumentation, nmi_enter() should be
> done before calling any traceable code and any instrumentation code.
> 
> Currently, nmi_enter() is done in handle_domain_nmi(), which is much
> too late as instrumentation code might get called before. Move the
> nmi_enter/exit() calls to the arch IRQ vector handler.
> 
> On arm64, it is not possible to know if the IRQ vector handler was
> called because of an NMI before acknowledging the interrupt. However, It
> is possible to know whether normal interrupts could be taken in the
> interrupted context (i.e. if taking an NMI in that context could
> introduce a potential race condition).
> 
> When interrupting a context with IRQs disabled, call nmi_enter() as soon
> as possible. In contexts with IRQs enabled, defer this to the interrupt
> controller, which is in a better position to know if an interrupt taken
> is an NMI.
> 
> Fixes: bc3c03ccb ("arm64: Enable the support of pseudo-NMIs")
> Signed-off-by: Julien Thierry <julien.thierry@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Jason Cooper <jason@lakedaemon.net>
> Cc: Marc Zyngier <marc.zyngier@arm.com>
> Cc: Mark Rutland <mark.rutland@arm.com>
> ---
>  arch/arm64/kernel/entry.S    | 44 +++++++++++++++++++++++++++++++++-----------
>  arch/arm64/kernel/irq.c      | 17 +++++++++++++++++
>  drivers/irqchip/irq-gic-v3.c |  6 ++++++
>  kernel/irq/irqdesc.c         |  8 ++++++--
>  4 files changed, 62 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> index 89ab6bd..46358a3 100644
> --- a/arch/arm64/kernel/entry.S
> +++ b/arch/arm64/kernel/entry.S
> @@ -435,6 +435,20 @@ tsk	.req	x28		// current thread_info
>  	irq_stack_exit
>  	.endm
> 
> +#ifdef CONFIG_ARM64_PSEUDO_NMI
> +	/*
> +	 * Set res to 0 if irqs were masked in interrupted context.

Is that comment right? This macro seems to return 0 if PMR is equal to
GIC_PRIO_IRQON, meaning that irqs are unmasked...

> +	 * Otherwise set res to non-0 value.
> +	 */
> +	.macro	test_irqs_unmasked res:req, pmr:req
> +alternative_if ARM64_HAS_IRQ_PRIO_MASKING
> +	sub	\res, \pmr, #GIC_PRIO_IRQON
> +alternative_else
> +	mov	\res, xzr
> +alternative_endif
> +	.endm
> +#endif
> +
>  	.text
> 
>  /*
> @@ -631,19 +645,19 @@ ENDPROC(el1_sync)
>  el1_irq:
>  	kernel_entry 1
>  	enable_da_f
> -#ifdef CONFIG_TRACE_IRQFLAGS
> +
>  #ifdef CONFIG_ARM64_PSEUDO_NMI
>  alternative_if ARM64_HAS_IRQ_PRIO_MASKING
>  	ldr	x20, [sp, #S_PMR_SAVE]
> -alternative_else
> -	mov	x20, #GIC_PRIO_IRQON
> -alternative_endif
> -	cmp	x20, #GIC_PRIO_IRQOFF
> -	/* Irqs were disabled, don't trace */
> -	b.ls	1f
> +alternative_else_nop_endif
> +	test_irqs_unmasked	res=x0, pmr=x20
> +	cbz	x0, 1f
> +	bl	asm_nmi_enter
> +1:
>  #endif
> +
> +#ifdef CONFIG_TRACE_IRQFLAGS
>  	bl	trace_hardirqs_off
> -1:
>  #endif
> 
>  	irq_handler
> @@ -662,14 +676,22 @@ alternative_else_nop_endif
>  	bl	preempt_schedule_irq		// irq en/disable is done inside
>  1:
>  #endif
> -#ifdef CONFIG_TRACE_IRQFLAGS
> +
>  #ifdef CONFIG_ARM64_PSEUDO_NMI
>  	/*
>  	 * if IRQs were disabled when we received the interrupt, we have an NMI
>  	 * and we are not re-enabling interrupt upon eret. Skip tracing.
>  	 */
> -	cmp	x20, #GIC_PRIO_IRQOFF
> -	b.ls	1f
> +	test_irqs_unmasked	res=x0, pmr=x20
> +	cbz	x0, 1f
> +	bl	asm_nmi_exit
> +1:
> +#endif
> +
> +#ifdef CONFIG_TRACE_IRQFLAGS
> +#ifdef CONFIG_ARM64_PSEUDO_NMI
> +	test_irqs_unmasked	res=x0, pmr=x20
> +	cbnz	x0, 1f
>  #endif
>  	bl	trace_hardirqs_on
>  1:
> diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
> index 92fa817..fdd9cb2 100644
> --- a/arch/arm64/kernel/irq.c
> +++ b/arch/arm64/kernel/irq.c
> @@ -27,8 +27,10 @@
>  #include <linux/smp.h>
>  #include <linux/init.h>
>  #include <linux/irqchip.h>
> +#include <linux/kprobes.h>
>  #include <linux/seq_file.h>
>  #include <linux/vmalloc.h>
> +#include <asm/daifflags.h>
>  #include <asm/vmap_stack.h>
> 
>  unsigned long irq_err_count;
> @@ -76,3 +78,18 @@ void __init init_IRQ(void)
>  	if (!handle_arch_irq)
>  		panic("No interrupt controller found.");
>  }
> +
> +/*
> + * Stubs to make nmi_enter/exit() code callable from ASM
> + */
> +asmlinkage void notrace asm_nmi_enter(void)
> +{
> +	nmi_enter();
> +}
> +NOKPROBE_SYMBOL(asm_nmi_enter);
> +
> +asmlinkage void notrace asm_nmi_exit(void)
> +{
> +	nmi_exit();
> +}
> +NOKPROBE_SYMBOL(asm_nmi_exit);
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index f44cd89..0bf0fc4 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -495,7 +495,13 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
> 
>  	if (gic_supports_nmi() &&
>  	    unlikely(gic_read_rpr() == GICD_INT_NMI_PRI)) {
> +		if (interrupts_enabled(regs))
> +			nmi_enter();
> +
>  		gic_handle_nmi(irqnr, regs);
> +
> +		if (interrupts_enabled(regs))
> +			nmi_exit();

Just to be on the safe side, I'd rather sample interrupts_enabled(regs)
and use the same value to decide whether to do nmi_exit or not.

>  		return;
>  	}
> 
> diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
> index c52b737..a92b335 100644
> --- a/kernel/irq/irqdesc.c
> +++ b/kernel/irq/irqdesc.c
> @@ -680,6 +680,8 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
>   * @hwirq:	The HW irq number to convert to a logical one
>   * @regs:	Register file coming from the low-level handling code
>   *
> + *		This function must be called from an NMI context.
> + *
>   * Returns:	0 on success, or -EINVAL if conversion has failed
>   */
>  int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
> @@ -689,7 +691,10 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
>  	unsigned int irq;
>  	int ret = 0;
> 
> -	nmi_enter();
> +	/*
> +	 * NMI context needs to be setup earlier in order to deal with tracing.
> +	 */
> +	WARN_ON(!in_nmi());
> 
>  	irq = irq_find_mapping(domain, hwirq);
> 
> @@ -702,7 +707,6 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
>  	else
>  		ret = -EINVAL;
> 
> -	nmi_exit();
>  	set_irq_regs(old_regs);
>  	return ret;
>  }
> --
> 1.9.1
> 

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

  reply	other threads:[~2019-06-07 15:58 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-06  9:31 [PATCH v3 0/8] arm64: IRQ priority masking and Pseudo-NMI fixes Julien Thierry
2019-06-06  9:31 ` [PATCH v3 1/8] arm64: Do not enable IRQs for ct_user_exit Julien Thierry
2019-06-07  9:25   ` James Morse
2019-06-06  9:31 ` [PATCH v3 2/8] arm64: irqflags: Pass flags as readonly operand to restore instruction Julien Thierry
2019-06-06  9:31 ` [PATCH v3 3/8] arm64: irqflags: Add condition flags to inline asm clobber list Julien Thierry
2019-06-06  9:31 ` [PATCH v3 4/8] arm64: Fix interrupt tracing in the presence of NMIs Julien Thierry
2019-06-07 15:42   ` Marc Zyngier [this message]
2019-06-07 15:54     ` Julien Thierry
2019-06-06  9:31 ` [PATCH v3 5/8] arm64: Fix incorrect irqflag restore for priority masking Julien Thierry
2019-06-07 16:29   ` Marc Zyngier
2019-06-10  7:49     ` Julien Thierry
2019-06-10 11:36       ` Julien Thierry
2019-06-10 11:42         ` Marc Zyngier
2019-06-06  9:31 ` [PATCH v3 6/8] arm64: irqflags: Introduce explicit debugging for IRQ priorities Julien Thierry
2019-06-07 16:31   ` Marc Zyngier
2019-06-10  7:53     ` Julien Thierry
2019-06-06  9:31 ` [PATCH v3 7/8] arm64: fix kernel stack overflow in kdump capture kernel Julien Thierry
2019-06-06  9:31 ` [PATCH v3 8/8] arm64: Allow selecting Pseudo-NMI again Julien Thierry

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=72cc234e-1c70-9356-bf53-0e3aa4ba43c5@arm.com \
    --to=marc.zyngier@arm.com \
    --cc=catalin.marinas@arm.com \
    --cc=james.morse@arm.com \
    --cc=jason@lakedaemon.net \
    --cc=julien.thierry@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=liwei391@huawei.com \
    --cc=mark.rutland@arm.com \
    --cc=rostedt@goodmis.org \
    --cc=tglx@linutronix.de \
    --cc=wanghaibin.wang@huawei.com \
    --cc=will.deacon@arm.com \
    --cc=yuzenghui@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®