linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Russell King - ARM Linux admin <linux@armlinux.org.uk>
To: Marc Zyngier <maz@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Will Deacon <will@kernel.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Jason Cooper <jason@lakedaemon.net>,
	Sumit Garg <sumit.garg@linaro.org>,
	kernel-team@android.com
Subject: Re: [PATCH 04/11] ARM: Allow IPIs to be handled as normal interrupts
Date: Tue, 19 May 2020 23:24:47 +0100	[thread overview]
Message-ID: <20200519222447.GJ1551@shell.armlinux.org.uk> (raw)
In-Reply-To: <20200519161755.209565-5-maz@kernel.org>

On Tue, May 19, 2020 at 05:17:48PM +0100, Marc Zyngier wrote:
> In order to deal with IPIs as normal interrupts, let's add
> a new way to register them with the architecture code.
> 
> set_smp_ipi_range() takes a range of interrupts, and allows
> the arch code to request them as if the were normal interrupts.
> A standard handler is then called by the core IRQ code to deal
> with the IPI.
> 
> This means that we don't need to call irq_enter/irq_exit, and
> that we don't need to deal with set_irq_regs either. So let's
> move the dispatcher into its own function, and leave handle_IPI()
> as a compatibility function.
> 
> On the sending side, let's make use of ipi_send_mask, which
> already exists for this purpose.

You say nothing about the nesting of irq_enter() and irq_exit()
for scheduler_ipi().

Given that lockdep introduced the requirement that hard IRQs can't
be nested, are we sure that calling irq_exit() twice is safe?

Looking at irqtime_account_irq(), it seems that will cause double-
accounting of in-interrupt time, since we will increment
irq_start_time by just over twice the the period spent handling
the IPI.

I think the rest of irq_exit() should be safe, but still, this
behaviour should be documented at the very least, if not avoided.

> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>  arch/arm/Kconfig           |  1 +
>  arch/arm/include/asm/smp.h |  5 ++
>  arch/arm/kernel/smp.c      | 97 ++++++++++++++++++++++++++++++++------
>  3 files changed, 88 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index c77c93c485a0..0caaba9bf880 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -48,6 +48,7 @@ config ARM
>  	select GENERIC_ARCH_TOPOLOGY if ARM_CPU_TOPOLOGY
>  	select GENERIC_ATOMIC64 if CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI
>  	select GENERIC_CLOCKEVENTS_BROADCAST if SMP
> +	select GENERIC_IRQ_IPI if SMP
>  	select GENERIC_CPU_AUTOPROBE
>  	select GENERIC_EARLY_IOREMAP
>  	select GENERIC_IDLE_POLL_SETUP
> diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
> index a91f21e3c5b5..0e29730295ca 100644
> --- a/arch/arm/include/asm/smp.h
> +++ b/arch/arm/include/asm/smp.h
> @@ -45,6 +45,11 @@ extern void smp_init_cpus(void);
>   */
>  extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
>  
> +/*
> + * Register IPI interrupts with the arch SMP code
> + */
> +extern void set_smp_ipi_range(int ipi_base, int nr_ipi);
> +
>  /*
>   * Called from platform specific assembly code, this is the
>   * secondary CPU entry point.
> diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
> index 46e1be9e57a8..618641978a5b 100644
> --- a/arch/arm/kernel/smp.c
> +++ b/arch/arm/kernel/smp.c
> @@ -79,10 +79,19 @@ enum ipi_msg_type {
>  	 */
>  };
>  
> +static int ipi_irq_base;
> +static int nr_ipi = NR_IPI;
> +static struct irq_desc *ipi_desc[NR_IPI];
> +
> +static void ipi_setup(int cpu);
> +static void ipi_teardown(int cpu);
> +
>  static DECLARE_COMPLETION(cpu_running);
>  
>  static struct smp_operations smp_ops __ro_after_init;
>  
> +static void ipi_setup(int cpu);
> +
>  void __init smp_set_ops(const struct smp_operations *ops)
>  {
>  	if (ops)
> @@ -308,6 +317,8 @@ void arch_cpu_idle_dead(void)
>  
>  	local_irq_disable();
>  
> +	ipi_teardown(cpu);
> +
>  	/*
>  	 * Flush the data out of the L1 cache for this CPU.  This must be
>  	 * before the completion to ensure that data is safely written out
> @@ -424,6 +435,8 @@ asmlinkage void secondary_start_kernel(void)
>  
>  	notify_cpu_starting(cpu);
>  
> +	ipi_setup(cpu);
> +
>  	calibrate_delay();
>  
>  	smp_store_cpu_info(cpu);
> @@ -629,10 +642,9 @@ asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
>  	handle_IPI(ipinr, regs);
>  }
>  
> -void handle_IPI(int ipinr, struct pt_regs *regs)
> +static void do_handle_IPI(int ipinr)
>  {
>  	unsigned int cpu = smp_processor_id();
> -	struct pt_regs *old_regs = set_irq_regs(regs);
>  
>  	if ((unsigned)ipinr < NR_IPI) {
>  		trace_ipi_entry_rcuidle(ipi_types[ipinr]);
> @@ -645,9 +657,7 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
>  
>  #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
>  	case IPI_TIMER:
> -		irq_enter();
>  		tick_receive_broadcast();
> -		irq_exit();
>  		break;
>  #endif
>  
> @@ -656,36 +666,26 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
>  		break;
>  
>  	case IPI_CALL_FUNC:
> -		irq_enter();
>  		generic_smp_call_function_interrupt();
> -		irq_exit();
>  		break;
>  
>  	case IPI_CPU_STOP:
> -		irq_enter();
>  		ipi_cpu_stop(cpu);
> -		irq_exit();
>  		break;
>  
>  #ifdef CONFIG_IRQ_WORK
>  	case IPI_IRQ_WORK:
> -		irq_enter();
>  		irq_work_run();
> -		irq_exit();
>  		break;
>  #endif
>  
>  	case IPI_COMPLETION:
> -		irq_enter();
>  		ipi_complete(cpu);
> -		irq_exit();
>  		break;
>  
>  	case IPI_CPU_BACKTRACE:
>  		printk_nmi_enter();
> -		irq_enter();
> -		nmi_cpu_backtrace(regs);
> -		irq_exit();
> +		nmi_cpu_backtrace(get_irq_regs());
>  		printk_nmi_exit();
>  		break;
>  
> @@ -697,9 +697,76 @@ void handle_IPI(int ipinr, struct pt_regs *regs)
>  
>  	if ((unsigned)ipinr < NR_IPI)
>  		trace_ipi_exit_rcuidle(ipi_types[ipinr]);
> +}
> +
> +/* Legacy version, should go away once all irqchips have been converted */
> +void handle_IPI(int ipinr, struct pt_regs *regs)
> +{
> +	struct pt_regs *old_regs = set_irq_regs(regs);
> +
> +	irq_enter();
> +	do_handle_IPI(ipinr);
> +	irq_exit();
> +
>  	set_irq_regs(old_regs);
>  }
>  
> +static irqreturn_t ipi_handler(int irq, void *data)
> +{
> +	do_handle_IPI(irq - ipi_irq_base);
> +	return IRQ_HANDLED;
> +}
> +
> +static void ipi_send(const struct cpumask *target, unsigned int ipi)
> +{
> +	__ipi_send_mask(ipi_desc[ipi], target);
> +}
> +
> +static void ipi_setup(int cpu)
> +{
> +	if (ipi_irq_base) {
> +		int i;
> +
> +		for (i = 0; i < nr_ipi; i++)
> +			enable_percpu_irq(ipi_irq_base + i, 0);
> +	}
> +}
> +
> +static void ipi_teardown(int cpu)
> +{
> +	if (ipi_irq_base) {
> +		int i;
> +
> +		for (i = 0; i < nr_ipi; i++)
> +			disable_percpu_irq(ipi_irq_base + i);
> +	}
> +}
> +
> +void __init set_smp_ipi_range(int ipi_base, int n)
> +{
> +	int i;
> +
> +	WARN_ON(n < NR_IPI);
> +	nr_ipi = min(n, NR_IPI);
> +
> +	for (i = 0; i < nr_ipi; i++) {
> +		int err;
> +
> +		err = request_percpu_irq(ipi_base + i, ipi_handler,
> +					 "IPI", &irq_stat);
> +		WARN_ON(err);
> +
> +		ipi_desc[i] = irq_to_desc(ipi_base + i);
> +		irq_set_status_flags(ipi_base + i, IRQ_NO_ACCOUNTING);
> +	}
> +
> +	ipi_irq_base = ipi_base;
> +	set_smp_cross_call(ipi_send);
> +
> +	/* Setup the boot CPU immediately */
> +	ipi_setup(smp_processor_id());
> +}
> +
>  void smp_send_reschedule(int cpu)
>  {
>  	smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
> -- 
> 2.26.2
> 
> 

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTC for 0.8m (est. 1762m) line in suburbia: sync at 13.1Mbps down 424kbps up

  reply	other threads:[~2020-05-19 22:25 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-19 16:17 [PATCH 00/11] arm/arm64: Turning IPIs into normal interrupts Marc Zyngier
2020-05-19 16:17 ` [PATCH 01/11] genirq: Add fasteoi IPI flow Marc Zyngier
2020-05-19 19:47   ` Florian Fainelli
2020-06-12  9:54     ` Marc Zyngier
2020-05-19 22:25   ` Valentin Schneider
2020-05-19 22:29     ` Valentin Schneider
2020-06-12  9:58     ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 02/11] genirq: Allow interrupts to be excluded from /proc/interrupts Marc Zyngier
2020-05-19 16:17 ` [PATCH 03/11] arm64: Allow IPIs to be handled as normal interrupts Marc Zyngier
2020-05-21 14:03   ` Valentin Schneider
2020-05-19 16:17 ` [PATCH 04/11] ARM: " Marc Zyngier
2020-05-19 22:24   ` Russell King - ARM Linux admin [this message]
2020-05-21 14:03     ` Valentin Schneider
2020-05-21 15:12       ` Russell King - ARM Linux admin
2020-05-21 16:11         ` Valentin Schneider
2020-05-19 16:17 ` [PATCH 05/11] irqchip/gic-v3: Describe the SGI range Marc Zyngier
2020-05-19 16:17 ` [PATCH 06/11] irqchip/gic-v3: Configure SGIs as standard interrupts Marc Zyngier
2020-05-20  9:52   ` Sumit Garg
2020-05-20 10:24     ` Marc Zyngier
2020-05-21 14:04   ` Valentin Schneider
2020-06-12 10:39     ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 07/11] irqchip/gic: Refactor SMP configuration Marc Zyngier
2020-05-19 16:17 ` [PATCH 08/11] irqchip/gic: Configure SGIs as standard interrupts Marc Zyngier
2021-04-20 20:37   ` dann frazier
2021-04-20 21:25     ` dann frazier
2021-04-21 10:58       ` Marc Zyngier
2021-04-21 14:52         ` dann frazier
2021-04-21 15:49           ` Marc Zyngier
2020-05-19 16:17 ` [PATCH 09/11] irqchip/gic-common: Don't enable SGIs by default Marc Zyngier
2020-05-19 16:17 ` [PATCH 10/11] irqchip/bcm2836: Configure mailbox interrupts as standard interrupts Marc Zyngier
2020-05-19 16:17 ` [PATCH 11/11] arm64: Kill __smp_cross_call and co Marc Zyngier
2020-05-19 17:50 ` [PATCH 00/11] arm/arm64: Turning IPIs into normal interrupts Florian Fainelli
2020-05-19 19:47   ` Florian Fainelli
2020-06-12  9:49   ` Marc Zyngier
2020-06-12 16:57     ` Florian Fainelli
2020-05-19 22:25 ` Valentin Schneider

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=20200519222447.GJ1551@shell.armlinux.org.uk \
    --to=linux@armlinux.org.uk \
    --cc=catalin.marinas@arm.com \
    --cc=jason@lakedaemon.net \
    --cc=kernel-team@android.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=maz@kernel.org \
    --cc=sumit.garg@linaro.org \
    --cc=tglx@linutronix.de \
    --cc=will@kernel.org \
    /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;
as well as URLs for NNTP newsgroup(s).