From: Zhenzhong Duan <[email protected]>
The current code incorrectly uses "pasid != PCI_NO_PASID" to determine if
PASID should be reported in fault records. However, this check happens
after the code converts PCI_NO_PASID to PASID_0 in scalable mode.
This means that for requests that originally had PCI_NO_PASID, the check
"pasid != PCI_NO_PASID" will incorrectly return true (since pasid is now
PASID_0), causing fault records to incorrectly indicate PASID validity.
According to the VT-d specification, the PASID field in fault records is
only valid for Requests-with-PASID:
"When Set, indicates the faulted request has a PASID TLP Prefix."
Fix this by capturing the original PASID state before the PCI_NO_PASID to
PASID_0 conversion, ensuring fault records correctly reflect whether the
original request had a PASID.
Fixes: 1b2b12376c8a ("intel_iommu: process PASID-based iotlb invalidation")
Suggested-by: Yi Liu <[email protected]>
Signed-off-by: Zhenzhong Duan <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Message-Id: <[email protected]>
Reviewed-by: Clement Mathieu--Drif <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
---
hw/i386/intel_iommu.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index e15aecf5f9..539e8f5763 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -2109,6 +2109,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace
*vtd_as, PCIBus *bus,
bool is_fpd_set = false;
bool reads = true;
bool writes = true;
+ bool is_pasid = pasid != PCI_NO_PASID;
uint8_t access_flags, pgtt;
VTDIOTLBEntry *iotlb_entry;
uint64_t xlat, size;
@@ -2235,7 +2236,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace
*vtd_as, PCIBus *bus,
if (ret_fr) {
if (!vtd_is_recoverable_fault(-ret_fr, iommu_idx)) {
vtd_report_fault(s, -ret_fr, is_fpd_set, source_id,
- addr, is_write, pasid != PCI_NO_PASID, pasid);
+ addr, is_write, is_pasid, pasid);
}
goto error;
}
--
MST