|
@@ -1806,6 +1806,7 @@ static const bool vtd_qualified_faults[] = {
|
|
[VTD_FR_FS_PAGING_ENTRY_US] = true,
|
|
[VTD_FR_FS_PAGING_ENTRY_US] = true,
|
|
[VTD_FR_SM_WRITE] = true,
|
|
[VTD_FR_SM_WRITE] = true,
|
|
[VTD_FR_SM_INTERRUPT_ADDR] = true,
|
|
[VTD_FR_SM_INTERRUPT_ADDR] = true,
|
|
|
|
+ [VTD_FR_FS_BIT_UPDATE_FAILED] = true,
|
|
[VTD_FR_MAX] = false,
|
|
[VTD_FR_MAX] = false,
|
|
};
|
|
};
|
|
|
|
|
|
@@ -1925,6 +1926,20 @@ static bool vtd_iova_fl_check_canonical(IntelIOMMUState *s, uint64_t iova,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static MemTxResult vtd_set_flag_in_pte(dma_addr_t base_addr, uint32_t index,
|
|
|
|
+ uint64_t pte, uint64_t flag)
|
|
|
|
+{
|
|
|
|
+ if (pte & flag) {
|
|
|
|
+ return MEMTX_OK;
|
|
|
|
+ }
|
|
|
|
+ pte |= flag;
|
|
|
|
+ pte = cpu_to_le64(pte);
|
|
|
|
+ return dma_memory_write(&address_space_memory,
|
|
|
|
+ base_addr + index * sizeof(pte),
|
|
|
|
+ &pte, sizeof(pte),
|
|
|
|
+ MEMTXATTRS_UNSPECIFIED);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Given the @iova, get relevant @flptep. @flpte_level will be the last level
|
|
* Given the @iova, get relevant @flptep. @flpte_level will be the last level
|
|
* of the translation, can be used for deciding the size of large page.
|
|
* of the translation, can be used for deciding the size of large page.
|
|
@@ -1938,7 +1953,7 @@ static int vtd_iova_to_flpte(IntelIOMMUState *s, VTDContextEntry *ce,
|
|
dma_addr_t addr = vtd_get_iova_pgtbl_base(s, ce, pasid);
|
|
dma_addr_t addr = vtd_get_iova_pgtbl_base(s, ce, pasid);
|
|
uint32_t level = vtd_get_iova_level(s, ce, pasid);
|
|
uint32_t level = vtd_get_iova_level(s, ce, pasid);
|
|
uint32_t offset;
|
|
uint32_t offset;
|
|
- uint64_t flpte;
|
|
|
|
|
|
+ uint64_t flpte, flag_ad = VTD_FL_A;
|
|
|
|
|
|
if (!vtd_iova_fl_check_canonical(s, iova, ce, pasid)) {
|
|
if (!vtd_iova_fl_check_canonical(s, iova, ce, pasid)) {
|
|
error_report_once("%s: detected non canonical IOVA (iova=0x%" PRIx64 ","
|
|
error_report_once("%s: detected non canonical IOVA (iova=0x%" PRIx64 ","
|
|
@@ -1985,6 +2000,14 @@ static int vtd_iova_to_flpte(IntelIOMMUState *s, VTDContextEntry *ce,
|
|
return -VTD_FR_FS_PAGING_ENTRY_RSVD;
|
|
return -VTD_FR_FS_PAGING_ENTRY_RSVD;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (vtd_is_last_pte(flpte, level) && is_write) {
|
|
|
|
+ flag_ad |= VTD_FL_D;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (vtd_set_flag_in_pte(addr, offset, flpte, flag_ad) != MEMTX_OK) {
|
|
|
|
+ return -VTD_FR_FS_BIT_UPDATE_FAILED;
|
|
|
|
+ }
|
|
|
|
+
|
|
if (vtd_is_last_pte(flpte, level)) {
|
|
if (vtd_is_last_pte(flpte, level)) {
|
|
*flptep = flpte;
|
|
*flptep = flpte;
|
|
*flpte_level = level;
|
|
*flpte_level = level;
|