@@ -686,9 +686,18 @@ static inline bool vtd_pe_type_check(X86IOMMUState *x86_iommu,
return true;
}
-static int vtd_get_pasid_dire(dma_addr_t pasid_dir_base,
- uint32_t pasid,
- VTDPASIDDirEntry *pdire)
+static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire)
+{
+ return pdire->val & 1;
+}
+
+/**
+ * Caller of this function should check present bit if wants
+ * to use pdir entry for futher usage except for fpd bit check.
+ */
+static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base,
+ uint32_t pasid,
+ VTDPASIDDirEntry *pdire)
{
uint32_t index;
dma_addr_t addr, entry_size;
@@ -703,18 +712,22 @@ static int vtd_get_pasid_dire(dma_addr_t pasid_dir_base,
return 0;
}
-static int vtd_get_pasid_entry(IntelIOMMUState *s,
- uint32_t pasid,
- VTDPASIDDirEntry *pdire,
- VTDPASIDEntry *pe)
+static inline bool vtd_pe_present(VTDPASIDEntry *pe)
+{
+ return pe->val[0] & VTD_PASID_ENTRY_P;
+}
+
+static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s,
+ uint32_t pasid,
+ dma_addr_t addr,
+ VTDPASIDEntry *pe)
{
uint32_t index;
- dma_addr_t addr, entry_size;
+ dma_addr_t entry_size;
X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
index = VTD_PASID_TABLE_INDEX(pasid);
entry_size = VTD_PASID_ENTRY_SIZE;
- addr = pdire->val & VTD_PASID_TABLE_BASE_ADDR_MASK;
addr = addr + index * entry_size;
if (dma_memory_read(&address_space_memory, addr, pe, entry_size)) {
return -VTD_FR_PASID_TABLE_INV;
@@ -732,25 +745,54 @@ static int vtd_get_pasid_entry(IntelIOMMUState *s,
return 0;
}
-static int vtd_get_pasid_entry_from_pasid(IntelIOMMUState *s,
- dma_addr_t pasid_dir_base,
- uint32_t pasid,
- VTDPASIDEntry *pe)
+/**
+ * Caller of this function should check present bit if wants
+ * to use pasid entry for futher usage except for fpd bit check.
+ */
+static int vtd_get_pe_from_pdire(IntelIOMMUState *s,
+ uint32_t pasid,
+ VTDPASIDDirEntry *pdire,
+ VTDPASIDEntry *pe)
+{
+ dma_addr_t addr = pdire->val & VTD_PASID_TABLE_BASE_ADDR_MASK;
+
+ return vtd_get_pe_in_pasid_leaf_table(s, pasid, addr, pe);
+}
+
+/**
+ * This function gets a pasid entry from a specified pasid
+ * table (includes dir and leaf table) with a specified pasid.
+ * Sanity check should be done to ensure return a present
+ * pasid entry to caller.
+ */
+static int vtd_get_pe_from_pasid_table(IntelIOMMUState *s,
+ dma_addr_t pasid_dir_base,
+ uint32_t pasid,
+ VTDPASIDEntry *pe)
{
int ret;
VTDPASIDDirEntry pdire;
- ret = vtd_get_pasid_dire(pasid_dir_base, pasid, &pdire);
+ ret = vtd_get_pdire_from_pdir_table(pasid_dir_base,
+ pasid, &pdire);
if (ret) {
return ret;
}
- ret = vtd_get_pasid_entry(s, pasid, &pdire, pe);
+ if (!vtd_pdire_present(&pdire)) {
+ return -VTD_FR_PASID_TABLE_INV;
+ }
+
+ ret = vtd_get_pe_from_pdire(s, pasid, &pdire, pe);
if (ret) {
return ret;
}
- return ret;
+ if (!vtd_pe_present(pe)) {
+ return -VTD_FR_PASID_TABLE_INV;
+ }
+
+ return 0;
}
static int vtd_ce_get_rid2pasid_entry(IntelIOMMUState *s,
@@ -763,7 +805,7 @@ static int vtd_ce_get_rid2pasid_entry(IntelIOMMUState *s,
pasid = VTD_CE_GET_RID2PASID(ce);
pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
- ret = vtd_get_pasid_entry_from_pasid(s, pasid_dir_base, pasid, pe);
+ ret = vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe);
return ret;
}
@@ -781,7 +823,11 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
pasid = VTD_CE_GET_RID2PASID(ce);
pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce);
- ret = vtd_get_pasid_dire(pasid_dir_base, pasid, &pdire);
+ /*
+ * No present bit check since fpd is meaningful even
+ * if the present bit is clear.
+ */
+ ret = vtd_get_pdire_from_pdir_table(pasid_dir_base, pasid, &pdire);
if (ret) {
return ret;
}
@@ -791,7 +837,15 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
return 0;
}
- ret = vtd_get_pasid_entry(s, pasid, &pdire, &pe);
+ if (!vtd_pdire_present(&pdire)) {
+ return -VTD_FR_PASID_TABLE_INV;
+ }
+
+ /*
+ * No present bit check since fpd is meaningful even
+ * if the present bit is clear.
+ */
+ ret = vtd_get_pe_from_pdire(s, pasid, &pdire, &pe);
if (ret) {
return ret;
}
@@ -479,6 +479,7 @@ typedef struct VTDRootEntry VTDRootEntry;
#define VTD_PASID_ENTRY_FPD (1ULL << 1) /* Fault Processing Disable */
/* PASID Granular Translation Type Mask */
+#define VTD_PASID_ENTRY_P 1ULL
#define VTD_SM_PASID_ENTRY_PGTT (7ULL << 6)
#define VTD_SM_PASID_ENTRY_FLT (1ULL << 6)
#define VTD_SM_PASID_ENTRY_SLT (2ULL << 6)