mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Amir Noohi <amirmnoohi@gmail.com>
To: Thomas Gleixner <tglx@kernel.org>, Marc Zyngier <maz@kernel.org>,
	Oliver Upton <oupton@kernel.org>
Cc: Radu Rendec <radu@rendec.net>, Igor Velkov <iav@iav.lv>,
	Fuad Tabba <fuad.tabba@linux.dev>,
	Joey Gouly <joey.gouly@arm.com>,
	Steffen Eiden <seiden@linux.ibm.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Christoffer Dall <cdall@linaro.org>,
	kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
	linux-kernel@vger.kernel.org, Amir Noohi <amirmnoohi@gmail.com>
Subject: [PATCH 1/2] genirq/manage: Provide irq_set_percpu_irqchip_state()
Date: Sat, 24 Oct 2026 02:24:49 +0000	[thread overview]
Message-ID: <20261024022450.629980-2-amirmnoohi@gmail.com> (raw)
In-Reply-To: <20261024022450.629980-1-amirmnoohi@gmail.com>

irq_set_irqchip_state() acquires the bus lock and the descriptor lock of
the interrupt. A per CPU devid interrupt has a single descriptor for all
CPUs, while its irqchip state is per CPU, e.g. each GICv3 redistributor
holds the active and pending state of the PPIs of its own CPU and GICv5
keeps that state in per CPU system registers. Callers which modify that
state have to be pinned to the CPU anyway, so the descriptor lock only
serializes CPUs which update their own private state.

KVM on arm64 sets the active state of the host timer interrupts on every
vCPU load, i.e. on every KVM_RUN ioctl and every time a vCPU thread is
scheduled in. When many CPUs load vCPUs at the same time, they all spin
on the descriptor lock of the same interrupt, even when every vCPU has
a physical CPU of its own. A global serialization point on the same path
was removed before in commit 64b6d1d7a845 ("genirq: Get rid of global
lock in irq_do_set_affinity()").

Provide irq_set_percpu_irqchip_state(), which sets the irqchip state of
a per CPU devid interrupt on the calling CPU without acquiring the
descriptor lock. The irqchip callback is still invoked with interrupts
disabled. The caller has to have preemption disabled and has to ensure
that the interrupt is neither freed nor reconfigured concurrently, which
is the case for an interrupt it has requested. Interrupt chips which
require a bus lock are rejected, as the bus lock may sleep and cannot be
taken with preemption disabled.

The function is not exported as its only user, KVM on arm64, cannot be
built as a module.

Signed-off-by: Amir Noohi <amirmnoohi@gmail.com>
---
 include/linux/interrupt.h |  2 ++
 kernel/irq/manage.c       | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 3bf969ad8fe0..ab20129615d4 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -507,6 +507,8 @@ extern int irq_get_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
 				 bool *state);
 extern int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
 				 bool state);
+int irq_set_percpu_irqchip_state(unsigned int irq, enum irqchip_irq_state which,
+				 bool state);
 
 #ifdef CONFIG_IRQ_FORCED_THREADING
 # ifdef CONFIG_PREEMPT_RT
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index bdb47837c66f..e76fe1cec9fb 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2777,6 +2777,42 @@ int irq_set_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool v
 }
 EXPORT_SYMBOL_GPL(irq_set_irqchip_state);
 
+/**
+ * irq_set_percpu_irqchip_state - Set the irqchip state of a per CPU interrupt
+ * @irq:	Linux interrupt number of a per CPU devid interrupt
+ * @which:	State to be set (one of IRQCHIP_STATE_*)
+ * @val:	Value corresponding to @which
+ *
+ * Variant of irq_set_irqchip_state() which sets the state of the calling
+ * CPU's instance of a per CPU devid interrupt without acquiring the
+ * interrupt descriptor lock. The descriptor and its lock are shared by all
+ * CPUs while the state is not, so acquiring the lock only serializes CPUs
+ * which modify their own state.
+ *
+ * Must be called with preemption disabled on an interrupt which has been
+ * requested, so that the interrupt chip hierarchy cannot change
+ * concurrently. Interrupt chips which require a bus lock are not supported.
+ *
+ * Return: 0 on success, a negative error code otherwise.
+ */
+int irq_set_percpu_irqchip_state(unsigned int irq, enum irqchip_irq_state which, bool val)
+{
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct irq_chip *chip;
+
+	lockdep_assert_preemption_disabled();
+
+	if (WARN_ON_ONCE(!desc || !irq_settings_is_per_cpu_devid(desc)))
+		return -EINVAL;
+
+	chip = irq_desc_get_chip(desc);
+	if (WARN_ON_ONCE(chip->irq_bus_lock || chip->irq_bus_sync_unlock))
+		return -EINVAL;
+
+	guard(irqsave)();
+	return __irq_set_irqchip_state(desc, which, val);
+}
+
 /**
  * irq_has_action - Check whether an interrupt is requested
  * @irq:	The linux irq number
-- 
2.53.0


  reply	other threads:[~2026-10-24  2:24 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-24  2:24 [PATCH 0/2] genirq, KVM: arm64: Avoid the irq descriptor lock on vCPU load Amir Noohi
2026-10-24  2:24 ` Amir Noohi [this message]
2026-10-24 12:21   ` [PATCH 1/2] genirq/manage: Provide irq_set_percpu_irqchip_state() Marc Zyngier
2026-10-24  2:24 ` [PATCH 2/2] KVM: arm64: timer: Avoid the irq descriptor lock on vCPU load Amir Noohi
2026-10-24 11:52 ` [PATCH 0/2] genirq, KVM: arm64: " Marc Zyngier

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=20261024022450.629980-2-amirmnoohi@gmail.com \
    --to=amirmnoohi@gmail.com \
    --cc=catalin.marinas@arm.com \
    --cc=cdall@linaro.org \
    --cc=fuad.tabba@linux.dev \
    --cc=iav@iav.lv \
    --cc=joey.gouly@arm.com \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=maz@kernel.org \
    --cc=oupton@kernel.org \
    --cc=radu@rendec.net \
    --cc=seiden@linux.ibm.com \
    --cc=suzuki.poulose@arm.com \
    --cc=tglx@kernel.org \
    --cc=will@kernel.org \
    --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®