Skip to contentSkip to conversation

irqchip/gic-v3-its: Limit number of per-device MSIs to the range the ITS supports

PATCH Applied Marc Zyngier 5 participants 6 messages Feb 6 – Feb 17

Subsystems (3)
lore
Share & tools
lore

Marc Zyngier

author maintainer
#0 lore raw

PATCH 1/1 irqchip/gic-v3-its: Limit number of per-device MSIs to the range the ITS supports

The ITS driver blindly assumes that EventIDs are in abundant supply, to the point where it never checks how many the HW actually supports.

It turns out that some pretty esoteric integrations make it so that only a few bits are available, all the way down to a. single. bit.

Enforce the advertised limitation at the point of allocating the device structure, and hope that the endpoint driver can deal with such limitation.

---
 drivers/irqchip/irq-gic-v3-its.c   | 4 ++++
 include/linux/irqchip/arm-gic-v3.h | 1 +
 2 files changed, 5 insertions(+)
drivers/irqchip/irq-gic-v3-its.c +4 -0
index 2988def30972b..a51e8e6a81819 100644
@@ -3475,6 +3475,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	int lpi_base;
 	int nr_lpis;
 	int nr_ites;
+	int id_bits;
 	int sz;
 
 	if (!its_alloc_device_table(its, dev_id))
@@ -3486,7 +3487,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	/*
 	 * Even if the device wants a single LPI, the ITT must be
 	 * sized as a power of two (and you need at least one bit...).
+	 * Also honor the ITS's own EID limit.
 	 */
+	id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1;
+	nvecs = min_t(unsigned int, nvecs, BIT(id_bits));
 	nr_ites = max(2, nvecs);
 	sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
 	sz = max(sz, ITS_ITT_ALIGN);
include/linux/irqchip/arm-gic-v3.h +1 -0
index 70c0948f978eb..0225121f30138 100644
@@ -394,6 +394,7 @@
 #define GITS_TYPER_VLPIS		(1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
 #define GITS_TYPER_ITT_ENTRY_SIZE	GENMASK_ULL(7, 4)
+#define GITS_TYPER_IDBITS		GENMASK_ULL(12, 8)
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS		GENMASK_ULL(17, 13)
Signature · 1 line
2.47.3
Reviewed-by on v1 1/1
#1 lore raw
Quoted 9 lines · Marc Zyngier

The ITS driver blindly assumes that EventIDs are in abundant supply, to the point where it never checks how many the HW actually supports.

It turns out that some pretty esoteric integrations make it so that only a few bits are available, all the way down to a. single. bit.

Enforce the advertised limitation at the point of allocating the device structure, and hope that the endpoint driver can deal with such limitation.

Quoted 42 lines
---
  drivers/irqchip/irq-gic-v3-its.c   | 4 ++++
  include/linux/irqchip/arm-gic-v3.h | 1 +
  2 files changed, 5 insertions(+)
drivers/irqchip/irq-gic-v3-its.c +4 -0
index 2988def30972b..a51e8e6a81819 100644
@@ -3475,6 +3475,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
  	int lpi_base;
  	int nr_lpis;
  	int nr_ites;
+	int id_bits;
  	int sz;
 
  	if (!its_alloc_device_table(its, dev_id))
@@ -3486,7 +3487,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
  	/*
  	 * Even if the device wants a single LPI, the ITT must be
  	 * sized as a power of two (and you need at least one bit...).
+	 * Also honor the ITS's own EID limit.
  	 */
+	id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1;
+	nvecs = min_t(unsigned int, nvecs, BIT(id_bits));
  	nr_ites = max(2, nvecs);
  	sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
  	sz = max(sz, ITS_ITT_ALIGN);
include/linux/irqchip/arm-gic-v3.h +1 -0
index 70c0948f978eb..0225121f30138 100644
@@ -394,6 +394,7 @@
  #define GITS_TYPER_VLPIS		(1UL << 1)
  #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
  #define GITS_TYPER_ITT_ENTRY_SIZE	GENMASK_ULL(7, 4)
+#define GITS_TYPER_IDBITS		GENMASK_ULL(12, 8)
  #define GITS_TYPER_IDBITS_SHIFT		8
  #define GITS_TYPER_DEVBITS_SHIFT	13
  #define GITS_TYPER_DEVBITS		GENMASK_ULL(17, 13)
maintainer
#2 lore raw
In reply to Marc Zyngier
Quoted 6 lines · Marc Zyngier

The ITS driver blindly assumes that EventIDs are in abundant supply, to the point where it never checks how many the HW actually supports.

It turns out that some pretty esoteric integrations make it so that only a few bits are available, all the way down to a. single. bit.

Quoted 6 lines

Enforce the advertised limitation at the point of allocating the device structure, and hope that the endpoint driver can deal with such limitation.

Can you please provide a Fixes tag?

Thanks,

tglx

author maintainer
#3 lore raw
Quoted 9 lines · Thomas Gleixner
Quoted 6 lines · Marc Zyngier

The ITS driver blindly assumes that EventIDs are in abundant supply, to the point where it never checks how many the HW actually supports.

It turns out that some pretty esoteric integrations make it so that only a few bits are available, all the way down to a. single. bit.

Quoted 8 lines
Quoted 6 lines

Enforce the advertised limitation at the point of allocating the device structure, and hope that the endpoint driver can deal with such limitation.

Can you please provide a Fixes tag?

That'd be

Fixes 84a6a2e7fc18d ("irqchip: GICv3: ITS: device allocation and configuration")

Thanks,

	M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Reviewed-by on v1 1/1
#4 lore raw
In reply to Marc Zyngier
Quoted 45 lines · Marc Zyngier

The ITS driver blindly assumes that EventIDs are in abundant supply, to the point where it never checks how many the HW actually supports.

It turns out that some pretty esoteric integrations make it so that only a few bits are available, all the way down to a. single. bit.

Enforce the advertised limitation at the point of allocating the device structure, and hope that the endpoint driver can deal with such limitation.

---
 drivers/irqchip/irq-gic-v3-its.c   | 4 ++++
 include/linux/irqchip/arm-gic-v3.h | 1 +
 2 files changed, 5 insertions(+)
drivers/irqchip/irq-gic-v3-its.c +4 -0
index 2988def30972b..a51e8e6a81819 100644
@@ -3475,6 +3475,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	int lpi_base;
 	int nr_lpis;
 	int nr_ites;
+	int id_bits;
 	int sz;
 
 	if (!its_alloc_device_table(its, dev_id))
@@ -3486,7 +3487,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	/*
 	 * Even if the device wants a single LPI, the ITT must be
 	 * sized as a power of two (and you need at least one bit...).
+	 * Also honor the ITS's own EID limit.
 	 */
+	id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1;
+	nvecs = min_t(unsigned int, nvecs, BIT(id_bits));
 	nr_ites = max(2, nvecs);
 	sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
 	sz = max(sz, ITS_ITT_ALIGN);
include/linux/irqchip/arm-gic-v3.h +0 -0
index 70c0948f978eb..0225121f30138 100644

include/linux/irqchip/arm-gic-v3.h line 400

Quoted 7 lines
include/linux/irqchip/arm-gic-v3.h +1 -0
@@ -394,6 +394,7 @@
 #define GITS_TYPER_VLPIS		(1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
 #define GITS_TYPER_ITT_ENTRY_SIZE	GENMASK_ULL(7, 4)
+#define GITS_TYPER_IDBITS		GENMASK_ULL(12, 8)
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS		GENMASK_ULL(17, 13)

Thanks,
Zenghui

merge bot Applied
#5 lore raw
In reply to Marc Zyngier
The following commit has been merged into the irq/urgent branch of tip:

The following commit has been merged into the irq/urgent branch of tip:

Commit-ID:     ce9e40a9a5e5cff0b1b0d2fa582b3d71a8ce68e8
Gitweb:        https://git.kernel.org/tip/ce9e40a9a5e5cff0b1b0d2fa582b3d71a8ce68e8
Author:        Marc Zyngier <[email protected]>
AuthorDate:    Fri, 06 Feb 2026 15:48:16 
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Tue, 17 Feb 2026 11:00:43 +01:00

irqchip/gic-v3-its: Limit number of per-device MSIs to the range the ITS supports

The ITS driver blindly assumes that EventIDs are in abundant supply, to the point where it never checks how many the hardware actually supports.

It turns out that some pretty esoteric integrations make it so that only a few bits are available, all the way down to a single bit.

Enforce the advertised limitation at the point of allocating the device structure, and hope that the endpoint driver can deal with such limitation.

Fixes 84a6a2e7fc18d ("irqchip: GICv3: ITS: device allocation and configuration")
---
 drivers/irqchip/irq-gic-v3-its.c   | 4 ++++
 include/linux/irqchip/arm-gic-v3.h | 1 +
 2 files changed, 5 insertions(+)
drivers/irqchip/irq-gic-v3-its.c +4 -0
index 2988def..a51e8e6 100644
@@ -3475,6 +3475,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	int lpi_base;
 	int nr_lpis;
 	int nr_ites;
+	int id_bits;
 	int sz;
 
 	if (!its_alloc_device_table(its, dev_id))
@@ -3486,7 +3487,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	/*
 	 * Even if the device wants a single LPI, the ITT must be
 	 * sized as a power of two (and you need at least one bit...).
+	 * Also honor the ITS's own EID limit.
 	 */
+	id_bits = FIELD_GET(GITS_TYPER_IDBITS, its->typer) + 1;
+	nvecs = min_t(unsigned int, nvecs, BIT(id_bits));
 	nr_ites = max(2, nvecs);
 	sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
 	sz = max(sz, ITS_ITT_ALIGN);
include/linux/irqchip/arm-gic-v3.h +1 -0
index 70c0948..0225121 100644
@@ -394,6 +394,7 @@
 #define GITS_TYPER_VLPIS		(1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
 #define GITS_TYPER_ITT_ENTRY_SIZE	GENMASK_ULL(7, 4)
+#define GITS_TYPER_IDBITS		GENMASK_ULL(12, 8)
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS		GENMASK_ULL(17, 13)