* [PATCH 0/5] arm64: gic-v5: Fixes from GICv5 KVM IRS review
@ 2026-08-10 10:27 Sascha Bischoff
2026-08-10 10:27 ` [PATCH 1/5] KVM: arm64: vgic: Free gic_kvm_info on initialization failure Sascha Bischoff
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Sascha Bischoff @ 2026-08-10 10:27 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org
Cc: nd, maz@kernel.org, oupton@kernel.org, Joey Gouly, Suzuki Poulose,
yuzenghui@huawei.com, lpieralisi@kernel.org
Hi all,
While reviewing v4 of the KVM GICv5 IRS series [1], Sashiko [2]
identified a number of issues in GICv5 and vGIC code that has already
been merged. This series contains the fixes for these issues.
The fixes are:
* Free gic_kvm_info when vGIC initialisation fails because the
maintenance interrupt is not provided but is required. This routes
the failure through the existing cleanup path to free gic_kvm_info
again.
* Clear the per-CPU IRS pointer and IAFFID state when host IRS
initialisation fails or an IRS is removed. This prevents the per-CPU
state from retaining a pointer to freed IRS data, thereby avoiding a
potential deference of a stale pointer later on.
* Add an isb() after disabling the GICv5 CPU interface. This ensures
that interrupts are disabled before the helper returns.
* Fix speculative accesses in the common vGIC SPI lookup which could
previously underflow. The SPI index is now made relative to the SPI
array before array_index_nospec() constrains it rather than
afterwards.
* Reject GICv5 PPIs outside KVM's supported private IRQ range. These
were previously clamped to zero, and hence would alias private IRQ 0
for an out-of-range PPI ID.
These changes are based on v7.2-rc7.
Thanks,
Sascha
[1] https://lore.kernel.org/all/20260724104819.1296803-1-sascha.bischoff@arm.com/
[2] https://sashiko.dev/#/patchset/20260724104819.1296803-1-sascha.bischoff%40arm.com
Sascha Bischoff (5):
KVM: arm64: vgic: Free gic_kvm_info on initialization failure
irqchip/gic-v5: Clear per-CPU IRS data on teardown
irqchip/gic-v5: Synchronize CPU interface disable
KVM: arm64: vgic: Prevent speculative SPI array underflow
KVM: arm64: vgic: Reject out-of-range GICv5 PPI IDs
arch/arm64/kvm/vgic/vgic-init.c | 4 +++-
arch/arm64/kvm/vgic/vgic.c | 7 +++++--
drivers/irqchip/irq-gic-v5-irs.c | 16 ++++++++++++++++
drivers/irqchip/irq-gic-v5.c | 1 +
4 files changed, 25 insertions(+), 3 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/5] KVM: arm64: vgic: Free gic_kvm_info on initialization failure
2026-08-10 10:27 [PATCH 0/5] arm64: gic-v5: Fixes from GICv5 KVM IRS review Sascha Bischoff
@ 2026-08-10 10:27 ` Sascha Bischoff
2026-08-10 10:28 ` [PATCH 2/5] irqchip/gic-v5: Clear per-CPU IRS data on teardown Sascha Bischoff
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sascha Bischoff @ 2026-08-10 10:27 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org
Cc: nd, maz@kernel.org, oupton@kernel.org, Joey Gouly, Suzuki Poulose,
yuzenghui@huawei.com, lpieralisi@kernel.org
vgic_set_kvm_info() allocates gic_kvm_info for use by
kvm_vgic_hyp_init(). When a maintenance interrupt is mandatory but not
provided, kvm_vgic_hyp_init() returns -ENXIO before reaching the
common cleanup path, leaking said allocation.
Route this error through that cleanup path so that gic_kvm_info is
freed and the global pointer is cleared.
Fixes: 0e5cb7770684 ("irqchip/gic: Split vGIC probing information from the GIC code")
Link: https://sashiko.dev/#/patchset/20260724104819.1296803-1-sascha.bischoff@arm.com?part=1
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
arch/arm64/kvm/vgic/vgic-init.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index 907057881b26a..65e203d6a2cf4 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -787,7 +787,8 @@ int kvm_vgic_hyp_init(void)
if (has_mask && !gic_kvm_info->maint_irq) {
kvm_err("No vgic maintenance irq\n");
- return -ENXIO;
+ ret = -ENXIO;
+ goto out_free;
}
/*
@@ -820,6 +821,7 @@ int kvm_vgic_hyp_init(void)
kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
+out_free:
kfree(gic_kvm_info);
gic_kvm_info = NULL;
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/5] irqchip/gic-v5: Clear per-CPU IRS data on teardown
2026-08-10 10:27 [PATCH 0/5] arm64: gic-v5: Fixes from GICv5 KVM IRS review Sascha Bischoff
2026-08-10 10:27 ` [PATCH 1/5] KVM: arm64: vgic: Free gic_kvm_info on initialization failure Sascha Bischoff
@ 2026-08-10 10:28 ` Sascha Bischoff
2026-08-10 11:36 ` Lorenzo Pieralisi
2026-08-10 10:28 ` [PATCH 3/5] irqchip/gic-v5: Synchronize CPU interface disable Sascha Bischoff
` (2 subsequent siblings)
4 siblings, 1 reply; 7+ messages in thread
From: Sascha Bischoff @ 2026-08-10 10:28 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org
Cc: nd, maz@kernel.org, oupton@kernel.org, Joey Gouly, Suzuki Poulose,
yuzenghui@huawei.com, lpieralisi@kernel.org
IRS affinity setup publishes an IRS pointer and IAFFID state in the
per-CPU data before the remaining IRS initialization can fail. The
error path then frees the IRS data without clearing that published
state, leaving CPUs associated with freed memory.
On initialization failure and normal IRS teardown, clear the per-CPU
IRS association by removing the stale pointer to irs_data. Also clear
the per-CPU IAFFID state for any CPUs that were tied to the IRS before
it was freed.
Fixes: 5cb1b6dab2de ("irqchip/gic-v5: Add GICv5 IRS/SPI support")
Fixes: 35866efa52fe ("irqchip/gic-v5: Add ACPI IRS probing")
Link: https://sashiko.dev/#/patchset/20260724104819.1296803-1-sascha.bischoff@arm.com?part=2
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
drivers/irqchip/irq-gic-v5-irs.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c
index f3fce0b1e25d9..67940ea9e39b7 100644
--- a/drivers/irqchip/irq-gic-v5-irs.c
+++ b/drivers/irqchip/irq-gic-v5-irs.c
@@ -651,6 +651,19 @@ static int __init gicv5_irs_of_init_affinity(struct device_node *node,
return ret;
}
+static void __init gicv5_irs_clear_affinity(struct gicv5_irs_chip_data *irs_data)
+{
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ if (per_cpu(per_cpu_irs_data, cpu) == irs_data) {
+ per_cpu(cpu_iaffid, cpu).iaffid = 0;
+ per_cpu(cpu_iaffid, cpu).valid = false;
+ per_cpu(per_cpu_irs_data, cpu) = NULL;
+ }
+ }
+}
+
static void irs_setup_pri_bits(u32 idr1)
{
switch (FIELD_GET(GICV5_IRS_IDR1_PRIORITY_BITS, idr1)) {
@@ -773,6 +786,7 @@ static int __init gicv5_irs_of_init(struct device_node *node)
return ret;
out_iomem:
+ gicv5_irs_clear_affinity(irs_data);
iounmap(irs_base);
out_err:
kfree(irs_data);
@@ -787,6 +801,7 @@ void __init gicv5_irs_remove(void)
gicv5_deinit_lpis();
list_for_each_entry_safe(irs_data, tmp_data, &irs_nodes, entry) {
+ gicv5_irs_clear_affinity(irs_data);
iounmap(irs_data->irs_base);
list_del(&irs_data->entry);
kfree(irs_data);
@@ -951,6 +966,7 @@ static int __init gic_acpi_parse_madt_irs(union acpi_subtable_headers *header,
return 0;
out_map:
+ gicv5_irs_clear_affinity(irs_data);
iounmap(irs_base);
out_release:
release_mem_region(r->start, resource_size(r));
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 3/5] irqchip/gic-v5: Synchronize CPU interface disable
2026-08-10 10:27 [PATCH 0/5] arm64: gic-v5: Fixes from GICv5 KVM IRS review Sascha Bischoff
2026-08-10 10:27 ` [PATCH 1/5] KVM: arm64: vgic: Free gic_kvm_info on initialization failure Sascha Bischoff
2026-08-10 10:28 ` [PATCH 2/5] irqchip/gic-v5: Clear per-CPU IRS data on teardown Sascha Bischoff
@ 2026-08-10 10:28 ` Sascha Bischoff
2026-08-10 10:29 ` [PATCH 4/5] KVM: arm64: vgic: Prevent speculative SPI array underflow Sascha Bischoff
2026-08-10 10:29 ` [PATCH 5/5] KVM: arm64: vgic: Reject out-of-range GICv5 PPI IDs Sascha Bischoff
4 siblings, 0 replies; 7+ messages in thread
From: Sascha Bischoff @ 2026-08-10 10:28 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org
Cc: nd, maz@kernel.org, oupton@kernel.org, Joey Gouly, Suzuki Poulose,
yuzenghui@huawei.com, lpieralisi@kernel.org
The write disabling the GICv5 CPU interface is only guaranteed to take
effect after a context synchronization event. Without one, execution can
return from gicv5_cpu_disable_interrupts() while an interrupt is still
able to be taken.
Add an ISB after the ICC_CR0_EL1 write to ensure interrupts are
disabled before the function returns. No corresponding ISB is added
when enabling the interface, as interrupt delivery is asynchronous and
there is no obvious benefit to waiting for it.
Fixes: 7ec80fb3f025 ("irqchip/gic-v5: Add GICv5 PPI support")
Link: https://sashiko.dev/#/patchset/20260724104819.1296803-1-sascha.bischoff@arm.com?part=6
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
drivers/irqchip/irq-gic-v5.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
index e9d1795235a66..6a99c541b559b 100644
--- a/drivers/irqchip/irq-gic-v5.c
+++ b/drivers/irqchip/irq-gic-v5.c
@@ -983,6 +983,7 @@ static void gicv5_cpu_disable_interrupts(void)
cr0 = FIELD_PREP(ICC_CR0_EL1_EN, 0);
write_sysreg_s(cr0, SYS_ICC_CR0_EL1);
+ isb();
}
static void gicv5_cpu_enable_interrupts(void)
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 4/5] KVM: arm64: vgic: Prevent speculative SPI array underflow
2026-08-10 10:27 [PATCH 0/5] arm64: gic-v5: Fixes from GICv5 KVM IRS review Sascha Bischoff
` (2 preceding siblings ...)
2026-08-10 10:28 ` [PATCH 3/5] irqchip/gic-v5: Synchronize CPU interface disable Sascha Bischoff
@ 2026-08-10 10:29 ` Sascha Bischoff
2026-08-10 10:29 ` [PATCH 5/5] KVM: arm64: vgic: Reject out-of-range GICv5 PPI IDs Sascha Bischoff
4 siblings, 0 replies; 7+ messages in thread
From: Sascha Bischoff @ 2026-08-10 10:29 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org
Cc: nd, maz@kernel.org, oupton@kernel.org, Joey Gouly, Suzuki Poulose,
yuzenghui@huawei.com, lpieralisi@kernel.org
For a non-GICv5 VM, SPI interrupt IDs include the private-interrupt
offset, while KVM's SPI array is indexed from zero. The lookup applies
array_index_nospec() to the absolute interrupt ID and subtracts the
private-interrupt offset afterwards.
On a speculative bypass of the range check for an interrupt ID below
the private range, the clamp preserves the small absolute value and
the subtraction underflows to an out-of-bounds SPI array index.
Convert the interrupt ID to a zero-based index into the SPI array
before applying array_index_nospec(). This way, we ensure that we
clamp to a reachable SPI ID, rather than an out-of-range SPI index.
Fixes: 41b87599c743 ("KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_get_irq()")
Link: https://sashiko.dev/#/patchset/20260724104819.1296803-1-sascha.bischoff@arm.com?part=27
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
arch/arm64/kvm/vgic/vgic.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 74bace10a22ed..352d52bd6315c 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -93,8 +93,9 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, u32 intid)
/* SPIs */
if (intid >= VGIC_NR_PRIVATE_IRQS &&
intid < (kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) {
- intid = array_index_nospec(intid, kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS);
- return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
+ intid -= VGIC_NR_PRIVATE_IRQS;
+ intid = array_index_nospec(intid, kvm->arch.vgic.nr_spis);
+ return &kvm->arch.vgic.spis[intid];
}
/* LPIs */
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 5/5] KVM: arm64: vgic: Reject out-of-range GICv5 PPI IDs
2026-08-10 10:27 [PATCH 0/5] arm64: gic-v5: Fixes from GICv5 KVM IRS review Sascha Bischoff
` (3 preceding siblings ...)
2026-08-10 10:29 ` [PATCH 4/5] KVM: arm64: vgic: Prevent speculative SPI array underflow Sascha Bischoff
@ 2026-08-10 10:29 ` Sascha Bischoff
4 siblings, 0 replies; 7+ messages in thread
From: Sascha Bischoff @ 2026-08-10 10:29 UTC (permalink / raw)
To: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org
Cc: nd, maz@kernel.org, oupton@kernel.org, Joey Gouly, Suzuki Poulose,
yuzenghui@huawei.com, lpieralisi@kernel.org
GICv5 supports up to 128 PPIs. In KVM, we have chosen to only support
the first 64 which correspond to the architected set of PPIs.
The GICv5 PPI helper checks only the encoded interrupt type (the top
bits of the interrupt ID). An encoded PPI with an ID outside KVM's
supported private-interrupt range therefore reaches the lookup, where
array_index_nospec() clamps it to zero and aliases private IRQ 0.
Reject out-of-range GICv5 PPI IDs before looking up the private IRQ.
Fixes: 4d591252bacb ("KVM: arm64: gic-v5: Implement PPI interrupt injection")
Link: https://sashiko.dev/#/patchset/20260724104819.1296803-1-sascha.bischoff@arm.com?part=27
Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
---
arch/arm64/kvm/vgic/vgic.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index 352d52bd6315c..b25303d9919fd 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -118,6 +118,8 @@ struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
switch (type) {
case KVM_DEV_TYPE_ARM_VGIC_V5:
intid = vgic_v5_get_hwirq_id(intid);
+ if (intid >= VGIC_V5_NR_PRIVATE_IRQS)
+ return NULL;
intid = array_index_nospec(intid, VGIC_V5_NR_PRIVATE_IRQS);
break;
default:
--
2.34.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 2/5] irqchip/gic-v5: Clear per-CPU IRS data on teardown
2026-08-10 10:28 ` [PATCH 2/5] irqchip/gic-v5: Clear per-CPU IRS data on teardown Sascha Bischoff
@ 2026-08-10 11:36 ` Lorenzo Pieralisi
0 siblings, 0 replies; 7+ messages in thread
From: Lorenzo Pieralisi @ 2026-08-10 11:36 UTC (permalink / raw)
To: Sascha Bischoff
Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev,
kvm@vger.kernel.org, nd, maz@kernel.org, oupton@kernel.org,
Joey Gouly, Suzuki Poulose, yuzenghui@huawei.com
On Mon, Aug 10, 2026 at 10:28:07AM +0000, Sascha Bischoff wrote:
> IRS affinity setup publishes an IRS pointer and IAFFID state in the
> per-CPU data before the remaining IRS initialization can fail. The
> error path then frees the IRS data without clearing that published
> state, leaving CPUs associated with freed memory.
>
> On initialization failure and normal IRS teardown, clear the per-CPU
> IRS association by removing the stale pointer to irs_data. Also clear
> the per-CPU IAFFID state for any CPUs that were tied to the IRS before
> it was freed.
>
> Fixes: 5cb1b6dab2de ("irqchip/gic-v5: Add GICv5 IRS/SPI support")
> Fixes: 35866efa52fe ("irqchip/gic-v5: Add ACPI IRS probing")
> Link: https://sashiko.dev/#/patchset/20260724104819.1296803-1-sascha.bischoff@arm.com?part=2
> Signed-off-by: Sascha Bischoff <sascha.bischoff@arm.com>
> ---
> drivers/irqchip/irq-gic-v5-irs.c | 16 ++++++++++++++++
> 1 file changed, 16 insertions(+)
Thank you Sascha, a minor comment below otherwise:
Reviewed-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> diff --git a/drivers/irqchip/irq-gic-v5-irs.c b/drivers/irqchip/irq-gic-v5-irs.c
> index f3fce0b1e25d9..67940ea9e39b7 100644
> --- a/drivers/irqchip/irq-gic-v5-irs.c
> +++ b/drivers/irqchip/irq-gic-v5-irs.c
> @@ -651,6 +651,19 @@ static int __init gicv5_irs_of_init_affinity(struct device_node *node,
> return ret;
> }
>
> +static void __init gicv5_irs_clear_affinity(struct gicv5_irs_chip_data *irs_data)
> +{
> + int cpu;
> +
> + for_each_possible_cpu(cpu) {
> + if (per_cpu(per_cpu_irs_data, cpu) == irs_data) {
> + per_cpu(cpu_iaffid, cpu).iaffid = 0;
As long we set valid to false this is not necessarily needed, 0 is a valid
value.
Thanks,
Lorenzo
> + per_cpu(cpu_iaffid, cpu).valid = false;
> + per_cpu(per_cpu_irs_data, cpu) = NULL;
> + }
> + }
> +}
> +
> static void irs_setup_pri_bits(u32 idr1)
> {
> switch (FIELD_GET(GICV5_IRS_IDR1_PRIORITY_BITS, idr1)) {
> @@ -773,6 +786,7 @@ static int __init gicv5_irs_of_init(struct device_node *node)
> return ret;
>
> out_iomem:
> + gicv5_irs_clear_affinity(irs_data);
> iounmap(irs_base);
> out_err:
> kfree(irs_data);
> @@ -787,6 +801,7 @@ void __init gicv5_irs_remove(void)
> gicv5_deinit_lpis();
>
> list_for_each_entry_safe(irs_data, tmp_data, &irs_nodes, entry) {
> + gicv5_irs_clear_affinity(irs_data);
> iounmap(irs_data->irs_base);
> list_del(&irs_data->entry);
> kfree(irs_data);
> @@ -951,6 +966,7 @@ static int __init gic_acpi_parse_madt_irs(union acpi_subtable_headers *header,
> return 0;
>
> out_map:
> + gicv5_irs_clear_affinity(irs_data);
> iounmap(irs_base);
> out_release:
> release_mem_region(r->start, resource_size(r));
> --
> 2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-10 11:36 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-10 10:27 [PATCH 0/5] arm64: gic-v5: Fixes from GICv5 KVM IRS review Sascha Bischoff
2026-08-10 10:27 ` [PATCH 1/5] KVM: arm64: vgic: Free gic_kvm_info on initialization failure Sascha Bischoff
2026-08-10 10:28 ` [PATCH 2/5] irqchip/gic-v5: Clear per-CPU IRS data on teardown Sascha Bischoff
2026-08-10 11:36 ` Lorenzo Pieralisi
2026-08-10 10:28 ` [PATCH 3/5] irqchip/gic-v5: Synchronize CPU interface disable Sascha Bischoff
2026-08-10 10:29 ` [PATCH 4/5] KVM: arm64: vgic: Prevent speculative SPI array underflow Sascha Bischoff
2026-08-10 10:29 ` [PATCH 5/5] KVM: arm64: vgic: Reject out-of-range GICv5 PPI IDs Sascha Bischoff
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox