hw/vfio/pci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
Since commit 49b2dcbd2422 ("accel/accel-irq: add generic
begin_route_changes"), accel_irqchip_begin_route_changes() aborts when
no accelerator irqchip is available. This causes a fatal error when
running VFIO passthrough devices under TCG emulation:
qemu-system-aarch64: can't initiate route change, no accel irqchip available
The previous kvm_irqchip_begin_route_changes() was a simple inline
that did not have a fatal path. The VFIO code already handles the
absence of KVM MSI routing gracefully by falling back to userspace
handling, but the new generic function aborts before that fallback
can take effect.
Guard the call sites in hw/vfio/pci.c with
accel_msi_via_irqfd_enabled() so that route changes are only
initiated when an accelerator irqchip is actually present.
Fixes: 49b2dcbd2422 ("accel/accel-irq: add generic begin_route_changes")
Cc: Magnus Kulke <magnuskulke@linux.microsoft.com>
Signed-off-by: Cédric Le Goater <clg@redhat.com>
---
hw/vfio/pci.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 380dd8c15f8d5bb98b725075978eef2e4e1e6c2d..a3147d28665abd29fd804bd08bdffc3c7440033c 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -699,7 +699,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
if (msg) {
if (vdev->defer_kvm_irq_routing) {
vfio_pci_add_kvm_msi_virq(vdev, vector, nr, true);
- } else {
+ } else if (accel_msi_via_irqfd_enabled()) {
vfio_route_change = accel_irqchip_begin_route_changes();
vfio_pci_add_kvm_msi_virq(vdev, vector, nr, true);
accel_irqchip_commit_route_changes(&vfio_route_change);
@@ -801,7 +801,9 @@ void vfio_pci_prepare_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
{
assert(!vdev->defer_kvm_irq_routing);
vdev->defer_kvm_irq_routing = true;
- vfio_route_change = accel_irqchip_begin_route_changes();
+ if (accel_msi_via_irqfd_enabled()) {
+ vfio_route_change = accel_irqchip_begin_route_changes();
+ }
}
void vfio_pci_commit_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
--
2.55.0
On 21/7/26 12:50, Cédric Le Goater wrote:
> Since commit 49b2dcbd2422 ("accel/accel-irq: add generic
> begin_route_changes"), accel_irqchip_begin_route_changes() aborts when
> no accelerator irqchip is available. This causes a fatal error when
> running VFIO passthrough devices under TCG emulation:
>
> qemu-system-aarch64: can't initiate route change, no accel irqchip available
>
> The previous kvm_irqchip_begin_route_changes() was a simple inline
> that did not have a fatal path. The VFIO code already handles the
> absence of KVM MSI routing gracefully by falling back to userspace
> handling, but the new generic function aborts before that fallback
> can take effect.
>
> Guard the call sites in hw/vfio/pci.c with
> accel_msi_via_irqfd_enabled() so that route changes are only
> initiated when an accelerator irqchip is actually present.
>
> Fixes: 49b2dcbd2422 ("accel/accel-irq: add generic begin_route_changes")
> Cc: Magnus Kulke <magnuskulke@linux.microsoft.com>
> Signed-off-by: Cédric Le Goater <clg@redhat.com>
> ---
> hw/vfio/pci.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> index 380dd8c15f8d5bb98b725075978eef2e4e1e6c2d..a3147d28665abd29fd804bd08bdffc3c7440033c 100644
> --- a/hw/vfio/pci.c
> +++ b/hw/vfio/pci.c
> @@ -699,7 +699,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
> if (msg) {
> if (vdev->defer_kvm_irq_routing) {
> vfio_pci_add_kvm_msi_virq(vdev, vector, nr, true);
> - } else {
> + } else if (accel_msi_via_irqfd_enabled()) {
> vfio_route_change = accel_irqchip_begin_route_changes();
Pre-existing, either we use the accel_*() API which is agnostic to the
host hw accelerator implementation (KVM, MSHV), or we directly use the
hw API.
> vfio_pci_add_kvm_msi_virq(vdev, vector, nr, true);
Here there is an implicit KVM dependency, so I'm not sure why we have
these accel_* calls. Maybe "system/accel-irq.h" is incomplete in that
regard.
> accel_irqchip_commit_route_changes(&vfio_route_change);
> @@ -801,7 +801,9 @@ void vfio_pci_prepare_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
> {
> assert(!vdev->defer_kvm_irq_routing);
> vdev->defer_kvm_irq_routing = true;
> - vfio_route_change = accel_irqchip_begin_route_changes();
> + if (accel_msi_via_irqfd_enabled()) {
(IOW here I'd rather a kvm_msi_via_irqfd_enabled() call)
> + vfio_route_change = accel_irqchip_begin_route_changes();
> + }
> }
>
> void vfio_pci_commit_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
On 7/21/26 13:04, Philippe Mathieu-Daudé wrote:
> On 21/7/26 12:50, Cédric Le Goater wrote:
>> Since commit 49b2dcbd2422 ("accel/accel-irq: add generic
>> begin_route_changes"), accel_irqchip_begin_route_changes() aborts when
>> no accelerator irqchip is available. This causes a fatal error when
>> running VFIO passthrough devices under TCG emulation:
>>
>> qemu-system-aarch64: can't initiate route change, no accel irqchip available
>>
>> The previous kvm_irqchip_begin_route_changes() was a simple inline
>> that did not have a fatal path. The VFIO code already handles the
>> absence of KVM MSI routing gracefully by falling back to userspace
>> handling, but the new generic function aborts before that fallback
>> can take effect.
>>
>> Guard the call sites in hw/vfio/pci.c with
>> accel_msi_via_irqfd_enabled() so that route changes are only
>> initiated when an accelerator irqchip is actually present.
>>
>> Fixes: 49b2dcbd2422 ("accel/accel-irq: add generic begin_route_changes")
>> Cc: Magnus Kulke <magnuskulke@linux.microsoft.com>
>> Signed-off-by: Cédric Le Goater <clg@redhat.com>
>> ---
>> hw/vfio/pci.c | 6 ++++--
>> 1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
>> index 380dd8c15f8d5bb98b725075978eef2e4e1e6c2d..a3147d28665abd29fd804bd08bdffc3c7440033c 100644
>> --- a/hw/vfio/pci.c
>> +++ b/hw/vfio/pci.c
>> @@ -699,7 +699,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
>> if (msg) {
>> if (vdev->defer_kvm_irq_routing) {
>> vfio_pci_add_kvm_msi_virq(vdev, vector, nr, true);
>> - } else {
>> + } else if (accel_msi_via_irqfd_enabled()) {
>> vfio_route_change = accel_irqchip_begin_route_changes();
>
> Pre-existing, either we use the accel_*() API which is agnostic to the
> host hw accelerator implementation (KVM, MSHV),
> or we directly use the hw API.
That would be a partial revert. I am fine with that.
C.
>
>> vfio_pci_add_kvm_msi_virq(vdev, vector, nr, true);
>
> Here there is an implicit KVM dependency, so I'm not sure why we have
> these accel_* calls. Maybe "system/accel-irq.h" is incomplete in that
> regard.
>
>> accel_irqchip_commit_route_changes(&vfio_route_change);
>> @@ -801,7 +801,9 @@ void vfio_pci_prepare_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
>> {
>> assert(!vdev->defer_kvm_irq_routing);
>> vdev->defer_kvm_irq_routing = true;
>> - vfio_route_change = accel_irqchip_begin_route_changes();
>> + if (accel_msi_via_irqfd_enabled()) {
>
> (IOW here I'd rather a kvm_msi_via_irqfd_enabled() call)
>
>> + vfio_route_change = accel_irqchip_begin_route_changes();
>> + }
>> }
>> void vfio_pci_commit_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
>
© 2016 - 2026 Red Hat, Inc.