* [PATCH v2 03/10] irqchip/gic-v5: Serialise IRS synchronisation requests
2026-11-04 17:47 [PATCH v2 00/10] irqchip/gic-v5: Fix misc IRS and ITS host driver issues Sascha Bischoff
@ 2026-11-04 17:47 ` Sascha Bischoff
2026-11-05 7:48 ` Lorenzo Pieralisi
2026-11-04 17:47 ` [PATCH v2 04/10] irqchip/gic-v5: Serialise ITS invalidation commands Sascha Bischoff
` (2 subsequent siblings)
3 siblings, 1 reply; 7+ messages in thread
From: Sascha Bischoff @ 2026-11-04 17:47 UTC (permalink / raw)
To: Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner, Radu Rendec,
Timothy Hayes, Catalin Marinas, Jonathan Cameron,
Rafael J. Wysocki
Cc: linux-arm-kernel, linux-kernel, Sascha Bischoff, stable
IRS_SYNCR writes are ignored while IRS_SYNC_STATUSR.IDLE is clear.
Calls to gicv5_irs_syncr() for different IRQs can overlap, allowing
the second request to be dropped. Its caller can then observe the
first request completing and assume that its own events have been
processed.
With GICv5 ITS KVM support, gicv5_irs_syncr() is also called while
restoring the host ITTE in gicv5_its_set_vcpu_affinity(). The callback
runs under the IRQ descriptor lock via irq_set_vcpu_affinity(), so it
cannot sleep.
Serialise the request and completion poll with a raw spinlock, and use
atomic polling because the synchronisation runs while holding the IRQ
descriptor lock.
Fixes: 57d72196dfc8 ("irqchip/gic-v5: Add GICv5 ITS support")
Cc: stable@vger.kernel.org
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
drivers/irqchip/irq-gic-v5-irs.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c
index 4edf787f3f97f..ead76560ea08f 100644
--- a/drivers/irqchip/irq-gic-v5-irs.c
+++ b/drivers/irqchip/irq-gic-v5-irs.c
@@ -10,6 +10,7 @@
#include <linux/log2.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/spinlock.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic-v5.h>
@@ -22,6 +23,8 @@
#define LPI_ID_BITS_LINEAR 12
static DEFINE_PER_CPU_READ_MOSTLY(struct gicv5_irs_chip_data *, per_cpu_irs_data);
+/* Synchronization requests must not overlap in an IRS Domain. */
+static DEFINE_RAW_SPINLOCK(irs_sync_lock);
static LIST_HEAD(irs_nodes);
static u32 irs_readl_relaxed(struct gicv5_irs_chip_data *irs_data,
@@ -507,10 +510,11 @@ void gicv5_irs_syncr(void)
return;
syncr = FIELD_PREP(GICV5_IRS_SYNCR_SYNC, 1);
+ guard(raw_spinlock_irqsave)(&irs_sync_lock);
irs_writel_relaxed(irs_data, syncr, GICV5_IRS_SYNCR);
- gicv5_wait_for_op(irs_data->irs_base, GICV5_IRS_SYNC_STATUSR,
- GICV5_IRS_SYNC_STATUSR_IDLE);
+ gicv5_wait_for_op_atomic(irs_data->irs_base, GICV5_IRS_SYNC_STATUSR,
+ GICV5_IRS_SYNC_STATUSR_IDLE, NULL);
}
int gicv5_irs_register_cpu(int cpuid)
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 03/10] irqchip/gic-v5: Serialise IRS synchronisation requests
2026-11-04 17:47 ` [PATCH v2 03/10] irqchip/gic-v5: Serialise IRS synchronisation requests Sascha Bischoff
@ 2026-11-05 7:48 ` Lorenzo Pieralisi
0 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Pieralisi @ 2026-11-05 7:48 UTC (permalink / raw)
To: Sascha Bischoff
Cc: Marc Zyngier, Thomas Gleixner, Radu Rendec, Timothy Hayes,
Catalin Marinas, Jonathan Cameron, Rafael J. Wysocki,
linux-arm-kernel, linux-kernel, stable
[Remove stable from the CC email recipient list, leave it only in the log]
On Wed, Nov 04, 2026 at 05:47:57PM +0000, Sascha Bischoff wrote:
> IRS_SYNCR writes are ignored while IRS_SYNC_STATUSR.IDLE is clear.
> Calls to gicv5_irs_syncr() for different IRQs can overlap, allowing
Nit: gicv5_irs_syncr() has no notion of specific IRQs, this is
misleading.
> the second request to be dropped. Its caller can then observe the
> first request completing and assume that its own events have been
> processed.
>
> With GICv5 ITS KVM support, gicv5_irs_syncr() is also called while
> restoring the host ITTE in gicv5_its_set_vcpu_affinity(). The callback
> runs under the IRQ descriptor lock via irq_set_vcpu_affinity(), so it
> cannot sleep.
Technically we are talking about a use case that does not exist yet.
I understand it is churn to fix it first and change it again later,
I would just say that gicv5_irs_syncr() might need to be called in atomic
context.
> Serialise the request and completion poll with a raw spinlock, and use
> atomic polling because the synchronisation runs while holding the IRQ
> descriptor lock.
>
> Fixes: 57d72196dfc8 ("irqchip/gic-v5: Add GICv5 ITS support")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> ---
> drivers/irqchip/irq-gic-v5-irs.c | 8 ++++++--
> 1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c
> index 4edf787f3f97f..ead76560ea08f 100644
> --- a/drivers/irqchip/irq-gic-v5-irs.c
> +++ b/drivers/irqchip/irq-gic-v5-irs.c
> @@ -10,6 +10,7 @@
> #include <linux/log2.h>
> #include <linux/of.h>
> #include <linux/of_address.h>
> +#include <linux/spinlock.h>
>
> #include <linux/irqchip.h>
> #include <linux/irqchip/arm-gic-v5.h>
> @@ -22,6 +23,8 @@
> #define LPI_ID_BITS_LINEAR 12
>
> static DEFINE_PER_CPU_READ_MOSTLY(struct gicv5_irs_chip_data *, per_cpu_irs_data);
> +/* Synchronization requests must not overlap in an IRS Domain. */
> +static DEFINE_RAW_SPINLOCK(irs_sync_lock);
> static LIST_HEAD(irs_nodes);
>
> static u32 irs_readl_relaxed(struct gicv5_irs_chip_data *irs_data,
> @@ -507,10 +510,11 @@ void gicv5_irs_syncr(void)
> return;
>
> syncr = FIELD_PREP(GICV5_IRS_SYNCR_SYNC, 1);
> + guard(raw_spinlock_irqsave)(&irs_sync_lock);
> irs_writel_relaxed(irs_data, syncr, GICV5_IRS_SYNCR);
>
> - gicv5_wait_for_op(irs_data->irs_base, GICV5_IRS_SYNC_STATUSR,
> - GICV5_IRS_SYNC_STATUSR_IDLE);
> + gicv5_wait_for_op_atomic(irs_data->irs_base, GICV5_IRS_SYNC_STATUSR,
> + GICV5_IRS_SYNC_STATUSR_IDLE, NULL);
> }
Acked-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
>
> int gicv5_irs_register_cpu(int cpuid)
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 04/10] irqchip/gic-v5: Serialise ITS invalidation commands
2026-11-04 17:47 [PATCH v2 00/10] irqchip/gic-v5: Fix misc IRS and ITS host driver issues Sascha Bischoff
2026-11-04 17:47 ` [PATCH v2 03/10] irqchip/gic-v5: Serialise IRS synchronisation requests Sascha Bischoff
@ 2026-11-04 17:47 ` Sascha Bischoff
2026-11-05 8:31 ` Lorenzo Pieralisi
2026-11-04 17:47 ` [PATCH v2 05/10] irqchip/gic-v5: Use linear DT and ITT when L2 covers all IDs Sascha Bischoff
2026-11-04 17:48 ` [PATCH v2 06/10] irqchip/gic-v5: Honour ACPI ITS noncoherent flag Sascha Bischoff
3 siblings, 1 reply; 7+ messages in thread
From: Sascha Bischoff @ 2026-11-04 17:47 UTC (permalink / raw)
To: Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner, Radu Rendec,
Timothy Hayes, Catalin Marinas, Jonathan Cameron,
Rafael J. Wysocki
Cc: linux-arm-kernel, linux-kernel, Sascha Bischoff, Sashiko AI,
stable
The ITS uses the shared DIDR and EIDR registers to select the DeviceID
and EventID whose translation is to be invalidated. Event
invalidations for different IRQs can overlap, as can an event
invalidation and a device invalidation. The per-IRQ descriptor lock
does not serialise these commands, so writes can interleave and cause
an invalidation to use the DeviceID or EventID of another IRQ being
invalidated concurrently on a different CPU.
Serialise the command register writes and STATUSR.IDLE polls for both
invalidation paths with a per-ITS raw spinlock. The KVM
gicv5_its_set_vcpu_affinity() callback calls the event invalidation
helper via irq_set_vcpu_affinity(), which holds the IRQ descriptor
lock. This path cannot sleep, so use atomic polling.
Fixes: 57d72196dfc8 ("irqchip/gic-v5: Add GICv5 ITS support")
Reported-by: Sashiko AI <sashiko-bot@kernel.org>
Link: https://sashiko.dev/#/patchset/20261016155741.979985-1-sascha.bischoff@arm.com?part=11
Cc: stable@vger.kernel.org
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
drivers/irqchip/irq-gic-v5-its.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c
index 28e39b065de0e..6d98f3dbe34b6 100644
--- a/drivers/irqchip/irq-gic-v5-its.c
+++ b/drivers/irqchip/irq-gic-v5-its.c
@@ -16,6 +16,7 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
+#include <linux/spinlock.h>
#include <linux/irqchip.h>
#include <linux/irqchip/arm-gic-v5.h>
@@ -28,6 +29,8 @@
struct gicv5_its_chip_data {
struct xarray its_devices;
struct mutex dev_alloc_lock;
+ /* Event and device invalidation commands share DIDR. */
+ raw_spinlock_t inv_lock;
struct fwnode_handle *fwnode;
struct gicv5_its_devtab_cfg devtab_cfgr;
void __iomem *its_base;
@@ -129,6 +132,8 @@ static int gicv5_its_itt_cache_inv(struct gicv5_its_chip_data *its, u32 device_i
eidr = FIELD_PREP(GICV5_ITS_EIDR_EVENTID, event_id);
eventr = FIELD_PREP(GICV5_ITS_INV_EVENTR_I, 0x1);
+ guard(raw_spinlock_irqsave)(&its->inv_lock);
+
its_writeq_relaxed(its, didr, GICV5_ITS_DIDR);
its_writel_relaxed(its, eidr, GICV5_ITS_EIDR);
its_writel_relaxed(its, eventr, GICV5_ITS_INV_EVENTR);
@@ -371,6 +376,9 @@ static int gicv5_its_device_cache_inv(struct gicv5_its_chip_data *its,
FIELD_PREP(GICV5_ITS_INV_DEVICER_EVENTID_BITS,
its_dev->itt_cfg.event_id_bits) |
FIELD_PREP(GICV5_ITS_INV_DEVICER_L1, 0x0);
+
+ guard(raw_spinlock_irqsave)(&its->inv_lock);
+
its_writeq_relaxed(its, didr, GICV5_ITS_DIDR);
its_writel_relaxed(its, devicer, GICV5_ITS_INV_DEVICER);
@@ -1112,6 +1120,7 @@ static int __init gicv5_its_init_bases(void __iomem *its_base, struct fwnode_han
return -ENOMEM;
mutex_init(&its_node->dev_alloc_lock);
+ raw_spin_lock_init(&its_node->inv_lock);
xa_init(&its_node->its_devices);
its_node->fwnode = handle;
its_node->its_base = its_base;
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH v2 04/10] irqchip/gic-v5: Serialise ITS invalidation commands
2026-11-04 17:47 ` [PATCH v2 04/10] irqchip/gic-v5: Serialise ITS invalidation commands Sascha Bischoff
@ 2026-11-05 8:31 ` Lorenzo Pieralisi
0 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Pieralisi @ 2026-11-05 8:31 UTC (permalink / raw)
To: Sascha Bischoff
Cc: Marc Zyngier, Thomas Gleixner, Radu Rendec, Timothy Hayes,
Catalin Marinas, Jonathan Cameron, Rafael J. Wysocki,
linux-arm-kernel, linux-kernel, Sashiko AI, stable
On Wed, Nov 04, 2026 at 05:47:58PM +0000, Sascha Bischoff wrote:
> The ITS uses the shared DIDR and EIDR registers to select the DeviceID
> and EventID whose translation is to be invalidated. Event
> invalidations for different IRQs can overlap, as can an event
> invalidation and a device invalidation. The per-IRQ descriptor lock
> does not serialise these commands, so writes can interleave and cause
> an invalidation to use the DeviceID or EventID of another IRQ being
> invalidated concurrently on a different CPU.
>
> Serialise the command register writes and STATUSR.IDLE polls for both
> invalidation paths with a per-ITS raw spinlock. The KVM
> gicv5_its_set_vcpu_affinity() callback calls the event invalidation
> helper via irq_set_vcpu_affinity(), which holds the IRQ descriptor
> lock. This path cannot sleep, so use atomic polling.
Same comment here as IRS sync. This one though looks like a host
driver bug that can happen regardless of KVM, so I'd just fix it
and remove/rephrase this paragraph.
> Fixes: 57d72196dfc8 ("irqchip/gic-v5: Add GICv5 ITS support")
> Reported-by: Sashiko AI <sashiko-bot@kernel.org>
> Link: https://sashiko.dev/#/patchset/20261016155741.979985-1-sascha.bischoff@arm.com?part=11
Again, this is linking to a report on a series that wasn't merged
yet but probably it makes sense to leave it there for context.
> Cc: stable@vger.kernel.org
> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> ---
> drivers/irqchip/irq-gic-v5-its.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
Acked-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> diff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c
> index 28e39b065de0e..6d98f3dbe34b6 100644
> --- a/drivers/irqchip/irq-gic-v5-its.c
> +++ b/drivers/irqchip/irq-gic-v5-its.c
> @@ -16,6 +16,7 @@
> #include <linux/of_address.h>
> #include <linux/of_irq.h>
> #include <linux/slab.h>
> +#include <linux/spinlock.h>
>
> #include <linux/irqchip.h>
> #include <linux/irqchip/arm-gic-v5.h>
> @@ -28,6 +29,8 @@
> struct gicv5_its_chip_data {
> struct xarray its_devices;
> struct mutex dev_alloc_lock;
> + /* Event and device invalidation commands share DIDR. */
> + raw_spinlock_t inv_lock;
> struct fwnode_handle *fwnode;
> struct gicv5_its_devtab_cfg devtab_cfgr;
> void __iomem *its_base;
> @@ -129,6 +132,8 @@ static int gicv5_its_itt_cache_inv(struct gicv5_its_chip_data *its, u32 device_i
> eidr = FIELD_PREP(GICV5_ITS_EIDR_EVENTID, event_id);
> eventr = FIELD_PREP(GICV5_ITS_INV_EVENTR_I, 0x1);
>
> + guard(raw_spinlock_irqsave)(&its->inv_lock);
> +
> its_writeq_relaxed(its, didr, GICV5_ITS_DIDR);
> its_writel_relaxed(its, eidr, GICV5_ITS_EIDR);
> its_writel_relaxed(its, eventr, GICV5_ITS_INV_EVENTR);
> @@ -371,6 +376,9 @@ static int gicv5_its_device_cache_inv(struct gicv5_its_chip_data *its,
> FIELD_PREP(GICV5_ITS_INV_DEVICER_EVENTID_BITS,
> its_dev->itt_cfg.event_id_bits) |
> FIELD_PREP(GICV5_ITS_INV_DEVICER_L1, 0x0);
> +
> + guard(raw_spinlock_irqsave)(&its->inv_lock);
> +
> its_writeq_relaxed(its, didr, GICV5_ITS_DIDR);
> its_writel_relaxed(its, devicer, GICV5_ITS_INV_DEVICER);
>
> @@ -1112,6 +1120,7 @@ static int __init gicv5_its_init_bases(void __iomem *its_base, struct fwnode_han
> return -ENOMEM;
>
> mutex_init(&its_node->dev_alloc_lock);
> + raw_spin_lock_init(&its_node->inv_lock);
> xa_init(&its_node->its_devices);
> its_node->fwnode = handle;
> its_node->its_base = its_base;
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 05/10] irqchip/gic-v5: Use linear DT and ITT when L2 covers all IDs
2026-11-04 17:47 [PATCH v2 00/10] irqchip/gic-v5: Fix misc IRS and ITS host driver issues Sascha Bischoff
2026-11-04 17:47 ` [PATCH v2 03/10] irqchip/gic-v5: Serialise IRS synchronisation requests Sascha Bischoff
2026-11-04 17:47 ` [PATCH v2 04/10] irqchip/gic-v5: Serialise ITS invalidation commands Sascha Bischoff
@ 2026-11-04 17:47 ` Sascha Bischoff
2026-11-04 17:48 ` [PATCH v2 06/10] irqchip/gic-v5: Honour ACPI ITS noncoherent flag Sascha Bischoff
3 siblings, 0 replies; 7+ messages in thread
From: Sascha Bischoff @ 2026-11-04 17:47 UTC (permalink / raw)
To: Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner, Radu Rendec,
Timothy Hayes, Catalin Marinas, Jonathan Cameron,
Rafael J. Wysocki
Cc: linux-arm-kernel, linux-kernel, Sascha Bischoff, stable
The DT and ITT level selector incorrectly chooses a two-level table
when the selected L2 table has exactly enough entries to cover the
full ID space. There are no L1 index bits in this case. ITT allocation
correctly rejects the layout and device registration fails; the DT
path instead allocates an unnecessary one-entry L1 table.
Select a linear DT or ITT when the L2 width equals the ID width.
Fixes: 57d72196dfc85 ("irqchip/gic-v5: Add GICv5 ITS support")
Cc: stable@vger.kernel.org
Acked-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
drivers/irqchip/irq-gic-v5-its.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c
index 6d98f3dbe34b6..866c238f08dfe 100644
--- a/drivers/irqchip/irq-gic-v5-its.c
+++ b/drivers/irqchip/irq-gic-v5-its.c
@@ -337,7 +337,7 @@ static bool gicv5_its_l2sz_two_level(bool devtab, u32 its_idr1, u8 id_bits, u8 *
l2_bits = gicv5_its_l2sz_to_l2_bits(l2_sz);
- if (l2_bits > id_bits)
+ if (l2_bits >= id_bits)
return false;
*sz = l2_sz;
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread* [PATCH v2 06/10] irqchip/gic-v5: Honour ACPI ITS noncoherent flag
2026-11-04 17:47 [PATCH v2 00/10] irqchip/gic-v5: Fix misc IRS and ITS host driver issues Sascha Bischoff
` (2 preceding siblings ...)
2026-11-04 17:47 ` [PATCH v2 05/10] irqchip/gic-v5: Use linear DT and ITT when L2 covers all IDs Sascha Bischoff
@ 2026-11-04 17:48 ` Sascha Bischoff
3 siblings, 0 replies; 7+ messages in thread
From: Sascha Bischoff @ 2026-11-04 17:48 UTC (permalink / raw)
To: Marc Zyngier, Lorenzo Pieralisi, Thomas Gleixner, Radu Rendec,
Timothy Hayes, Catalin Marinas, Jonathan Cameron,
Rafael J. Wysocki
Cc: linux-arm-kernel, linux-kernel, Sascha Bischoff, stable
The ACPI ITS probe passes its noncoherent flag to
gicv5_its_init_bases(), but the common initializer checks a DT
property instead. For an ACPI ITS, this always selects coherent cache
settings and skips the cache maintenance required for its tables.
Use the noncoherent argument, which both firmware paths already
supply.
Fixes: a97efa5ba5946 ("irqchip/gic-v5: Add ACPI ITS probing")
Cc: stable@vger.kernel.org
Acked-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
drivers/irqchip/irq-gic-v5-its.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-gic-v5-its.c b/drivers/irqchip/irq-gic-v5-its.c
index 866c238f08dfe..c5d057f713134 100644
--- a/drivers/irqchip/irq-gic-v5-its.c
+++ b/drivers/irqchip/irq-gic-v5-its.c
@@ -1135,7 +1135,7 @@ static int __init gicv5_its_init_bases(void __iomem *its_base, struct fwnode_han
goto out_free_node;
}
- if (of_property_read_bool(np, "dma-noncoherent")) {
+ if (noncoherent) {
/*
* A non-coherent ITS implies that some cache levels cannot be
* used coherently by the cores and GIC. Our only option is to mark
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread