From ae243bf46f02f0ed65b5dc1345b2e3669ad771ee Mon Sep 17 00:00:00 2001 From: Shameer Kolothum Date: Mon, 15 Jun 2026 00:00:00 +0000 Subject: [PATCH] target/arm/kvm: check get_msi_direct_gpa before &address_space_memory guard For vfio-pci endpoints behind an accelerated SMMUv3, smmuv3_accel_find_add_as() returns &address_space_memory from get_address_space(). This is by design: the host S2 mappings handle DMA without an IOMMU address space on the QEMU side. pci_device_iommu_address_space() uses the same path, so it also returns &address_space_memory for these devices. kvm_arch_fixup_msi_route() then hits the early-exit guard and returns before calling pci_device_iommu_msi_direct_gpa(). The MSI route goes unfixed, the guest sees no MSI domain, and the NVIDIA driver fails to load. The bug was introduced by commit a509f10a00, which reverted the SAUCE pci_device_iommu_msi_address_space() helper and switched kvm.c back to pci_device_iommu_address_space(). That revert is correct: the upstream get_msi_direct_gpa mechanism replaces the SAUCE approach. The problem is that pci_device_iommu_msi_direct_gpa() was left after the early-exit guard rather than before it. Move pci_device_iommu_msi_direct_gpa() above the &address_space_memory guard. If the callback is implemented (accelerated SMMUv3 + vfio-pci), the doorbell GPA is obtained directly and the function jumps to set_doorbell. Otherwise the existing early-exit and translation paths run unchanged. Fixes: a509f10a00 ("Revert 'NVIDIA: SAUCE: hw/pci/pci: Introduce optional get_msi_address_space() callback'") Signed-off-by: Shameer Kolothum --- target/arm/kvm.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 9ff947ed6b..fadfc64734 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -1634,22 +1634,23 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, MemoryRegionSection mrs; MemoryRegion *mr; - if (as == &address_space_memory) { - return 0; - } - /* * We do have an IOMMU address space, but for some vIOMMU implementations * (e.g. accelerated SMMUv3) the translation tables are programmed into * the physical SMMUv3 in the host (nested S1=guest, S2=host). QEMU cannot * walk these tables in a safe way, so in that case we obtain the MSI * doorbell GPA directly from the vIOMMU backend and ignore the gIOVA - * @address. + * @address. For such devices pci_device_iommu_address_space() returns + * &address_space_memory, so this check must precede the early-exit below. */ if (pci_device_iommu_msi_direct_gpa(dev, &doorbell_gpa)) { goto set_doorbell; } + if (as == &address_space_memory) { + return 0; + } + /* MSI doorbell address is translated by an IOMMU */ rcu_read_lock();