ppt_pci_reset() issues an FLR with force=true at every assignment and
unassignment. An Intel integrated GPU whose display engine is scanning
out at that moment (the firmware's framebuffer at the first assignment
after boot, or the host console on efifb) does not go idle: pcie_flr()
prints "Transactions pending after FLR!" and the GPU keeps fetching with
its configuration reset underneath it, still in the host's IOMMU domain
(iommu_add_device() comes after the reset). Moments later other host
devices find their DMA structures overwritten: on a ThinkPad X1 Carbon
gen 6 (i5-8250U, UHD 620) the host's xHCI halted and the NVMe controller
went into fatal status with "Received Master Abort" set on both, 2 s
after the guest got the GPU, and once a page of a file being written was
replaced by the contents of unrelated kernel memory. With the same
build and guest configuration, the reset path crashed 4 times in 16
cold boots (rounds 6, 1, 7 and 2 of four runs) and the patched path 0
times in 20 (plus 0 in 60 earlier boots without the reset); no VT-d
fault was recorded and the IOMMU tables were verified intact at the
panic, so this is the device, not the IOMMU. Reading the GPU's config
space 100 ms after the FLR gave all ones (GGC, BDSM, command register):
the device had dropped off the bus, so pci_restore_state() was lost
too, and it came back with reset configuration while still scanning
out.
Nobody can turn the display off first without a host driver, so do not
reset the IGD at all; the guest's driver initializes it anyway. The
guest-requested FLR path (ppt_reset_device) is left as it is: there the guest's driver asked for the
reset after quiescing the device, and the GPU is in the guest's domain.
Signed-off-by: Wanpeng Qian <wanpengqian@gmail.com>
Sponsored by: keelos.dev