[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v6 08/20] intel_iommu: Check stage-1 translation result with inte
From: |
Zhenzhong Duan |
Subject: |
[PATCH v6 08/20] intel_iommu: Check stage-1 translation result with interrupt range |
Date: |
Thu, 12 Dec 2024 16:37:45 +0800 |
Per VT-d spec 4.1 section 3.15, "Untranslated requests and translation
requests that result in an address in the interrupt range will be
blocked with condition code LGN.4 or SGN.8."
This applies to both stage-1 and stage-2 IOMMU page table, move the
check from vtd_iova_to_slpte() to vtd_do_iommu_translate() so stage-1
page table could also be checked.
By this chance, update the comment with correct section number.
Suggested-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Zhenzhong Duan <zhenzhong.duan@intel.com>
Reviewed-by: Clément Mathieu--Drif<clement.mathieu--drif@eviden.com>
Acked-by: Jason Wang <jasowang@redhat.com>
---
hw/i386/intel_iommu.c | 48 ++++++++++++++++++++++---------------------
1 file changed, 25 insertions(+), 23 deletions(-)
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c
index a4a2a44f92..594c8e3272 100644
--- a/hw/i386/intel_iommu.c
+++ b/hw/i386/intel_iommu.c
@@ -1138,7 +1138,6 @@ static int vtd_iova_to_slpte(IntelIOMMUState *s,
VTDContextEntry *ce,
uint32_t offset;
uint64_t slpte;
uint64_t access_right_check;
- uint64_t xlat, size;
if (!vtd_iova_sl_range_check(s, iova, ce, aw_bits, pasid)) {
error_report_once("%s: detected IOVA overflow (iova=0x%" PRIx64 ","
@@ -1191,28 +1190,7 @@ static int vtd_iova_to_slpte(IntelIOMMUState *s,
VTDContextEntry *ce,
level--;
}
- xlat = vtd_get_pte_addr(*slptep, aw_bits);
- size = ~vtd_pt_level_page_mask(level) + 1;
-
- /*
- * From VT-d spec 3.14: Untranslated requests and translation
- * requests that result in an address in the interrupt range will be
- * blocked with condition code LGN.4 or SGN.8.
- */
- if ((xlat > VTD_INTERRUPT_ADDR_LAST ||
- xlat + size - 1 < VTD_INTERRUPT_ADDR_FIRST)) {
- return 0;
- } else {
- error_report_once("%s: xlat address is in interrupt range "
- "(iova=0x%" PRIx64 ", level=0x%" PRIx32 ", "
- "slpte=0x%" PRIx64 ", write=%d, "
- "xlat=0x%" PRIx64 ", size=0x%" PRIx64 ", "
- "pasid=0x%" PRIx32 ")",
- __func__, iova, level, slpte, is_write,
- xlat, size, pasid);
- return s->scalable_mode ? -VTD_FR_SM_INTERRUPT_ADDR :
- -VTD_FR_INTERRUPT_ADDR;
- }
+ return 0;
}
typedef int (*vtd_page_walk_hook)(const IOMMUTLBEvent *event, void *private);
@@ -2064,6 +2042,7 @@ static bool vtd_do_iommu_translate(VTDAddressSpace
*vtd_as, PCIBus *bus,
uint8_t access_flags;
bool rid2pasid = (pasid == PCI_NO_PASID) && s->root_scalable;
VTDIOTLBEntry *iotlb_entry;
+ uint64_t xlat, size;
/*
* We have standalone memory region for interrupt addresses, we
@@ -2173,6 +2152,29 @@ static bool vtd_do_iommu_translate(VTDAddressSpace
*vtd_as, PCIBus *bus,
ret_fr = vtd_iova_to_slpte(s, &ce, addr, is_write, &pte, &level,
&reads, &writes, s->aw_bits, pasid);
}
+ if (!ret_fr) {
+ xlat = vtd_get_pte_addr(pte, s->aw_bits);
+ size = ~vtd_pt_level_page_mask(level) + 1;
+
+ /*
+ * Per VT-d spec 4.1 section 3.15: Untranslated requests and
translation
+ * requests that result in an address in the interrupt range will be
+ * blocked with condition code LGN.4 or SGN.8.
+ */
+ if ((xlat <= VTD_INTERRUPT_ADDR_LAST &&
+ xlat + size - 1 >= VTD_INTERRUPT_ADDR_FIRST)) {
+ error_report_once("%s: xlat address is in interrupt range "
+ "(iova=0x%" PRIx64 ", level=0x%" PRIx32 ", "
+ "pte=0x%" PRIx64 ", write=%d, "
+ "xlat=0x%" PRIx64 ", size=0x%" PRIx64 ", "
+ "pasid=0x%" PRIx32 ")",
+ __func__, addr, level, pte, is_write,
+ xlat, size, pasid);
+ ret_fr = s->scalable_mode ? -VTD_FR_SM_INTERRUPT_ADDR :
+ -VTD_FR_INTERRUPT_ADDR;
+ }
+ }
+
if (ret_fr) {
vtd_report_fault(s, -ret_fr, is_fpd_set, source_id,
addr, is_write, pasid != PCI_NO_PASID, pasid);
--
2.34.1
- [PATCH v6 00/20] intel_iommu: Enable stage-1 translation for emulated device, Zhenzhong Duan, 2024/12/12
- [PATCH v6 01/20] intel_iommu: Use the latest fault reasons defined by spec, Zhenzhong Duan, 2024/12/12
- [PATCH v6 02/20] intel_iommu: Make pasid entry type check accurate, Zhenzhong Duan, 2024/12/12
- [PATCH v6 03/20] intel_iommu: Add a placeholder variable for scalable mode stage-1 translation, Zhenzhong Duan, 2024/12/12
- [PATCH v6 04/20] intel_iommu: Flush stage-2 cache in PASID-selective PASID-based iotlb invalidation, Zhenzhong Duan, 2024/12/12
- [PATCH v6 05/20] intel_iommu: Rename slpte to pte, Zhenzhong Duan, 2024/12/12
- [PATCH v6 06/20] intel_iommu: Implement stage-1 translation, Zhenzhong Duan, 2024/12/12
- [PATCH v6 07/20] intel_iommu: Check if the input address is canonical, Zhenzhong Duan, 2024/12/12
- [PATCH v6 09/20] intel_iommu: Set accessed and dirty bits during stage-1 translation, Zhenzhong Duan, 2024/12/12
- [PATCH v6 08/20] intel_iommu: Check stage-1 translation result with interrupt range,
Zhenzhong Duan <=
- [PATCH v6 10/20] intel_iommu: Flush stage-1 cache in iotlb invalidation, Zhenzhong Duan, 2024/12/12
- [PATCH v6 12/20] intel_iommu: Add an internal API to find an address space with PASID, Zhenzhong Duan, 2024/12/12
- [PATCH v6 14/20] intel_iommu: piotlb invalidation should notify unmap, Zhenzhong Duan, 2024/12/12
- [PATCH v6 11/20] intel_iommu: Process PASID-based iotlb invalidation, Zhenzhong Duan, 2024/12/12
- [PATCH v6 13/20] intel_iommu: Add support for PASID-based device IOTLB invalidation, Zhenzhong Duan, 2024/12/12
- [PATCH v6 16/20] intel_iommu: Set default aw_bits to 48 starting from QEMU 9.2, Zhenzhong Duan, 2024/12/12
- [PATCH v6 15/20] tests/acpi: q35: allow DMAR acpi table changes, Zhenzhong Duan, 2024/12/12
- [PATCH v6 17/20] tests/acpi: q35: Update host address width in DMAR, Zhenzhong Duan, 2024/12/12
- [PATCH v6 18/20] intel_iommu: Introduce a property x-flts for stage-1 translation, Zhenzhong Duan, 2024/12/12