intel_iommu: add present bit check for pasid table entries

The present bit check for pasid entry (pe) and pasid directory
entry (pdire) were missed in previous commits as fpd bit check
doesn't require present bit as "Set". This patch adds the present
bit check for callers which wants to get a valid pe/pdire.

Cc: qemu-stable@nongnu.org
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Yi Sun <yi.y.sun@linux.intel.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
Message-Id: <1578058086-4288-3-git-send-email-yi.l.liu@intel.com>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Liu Yi L 2020-01-03 21:28:06 +08:00 committed by Michael S. Tsirkin
parent a2e1cd41cc
commit 56fc1e6ac6
2 changed files with 74 additions and 19 deletions

View File

@ -686,7 +686,16 @@ static inline bool vtd_pe_type_check(X86IOMMUState *x86_iommu,
return true; return true;
} }
static int vtd_get_pasid_dire(dma_addr_t pasid_dir_base, 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, uint32_t pasid,
VTDPASIDDirEntry *pdire) VTDPASIDDirEntry *pdire)
{ {
@ -703,18 +712,22 @@ static int vtd_get_pasid_dire(dma_addr_t pasid_dir_base,
return 0; return 0;
} }
static int vtd_get_pasid_entry(IntelIOMMUState *s, 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, uint32_t pasid,
VTDPASIDDirEntry *pdire, dma_addr_t addr,
VTDPASIDEntry *pe) VTDPASIDEntry *pe)
{ {
uint32_t index; uint32_t index;
dma_addr_t addr, entry_size; dma_addr_t entry_size;
X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s); X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
index = VTD_PASID_TABLE_INDEX(pasid); index = VTD_PASID_TABLE_INDEX(pasid);
entry_size = VTD_PASID_ENTRY_SIZE; entry_size = VTD_PASID_ENTRY_SIZE;
addr = pdire->val & VTD_PASID_TABLE_BASE_ADDR_MASK;
addr = addr + index * entry_size; addr = addr + index * entry_size;
if (dma_memory_read(&address_space_memory, addr, pe, entry_size)) { if (dma_memory_read(&address_space_memory, addr, pe, entry_size)) {
return -VTD_FR_PASID_TABLE_INV; return -VTD_FR_PASID_TABLE_INV;
@ -732,7 +745,27 @@ static int vtd_get_pasid_entry(IntelIOMMUState *s,
return 0; return 0;
} }
static int vtd_get_pasid_entry_from_pasid(IntelIOMMUState *s, /**
* 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, dma_addr_t pasid_dir_base,
uint32_t pasid, uint32_t pasid,
VTDPASIDEntry *pe) VTDPASIDEntry *pe)
@ -740,17 +773,26 @@ static int vtd_get_pasid_entry_from_pasid(IntelIOMMUState *s,
int ret; int ret;
VTDPASIDDirEntry pdire; 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) { if (ret) {
return 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) { if (ret) {
return 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, 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 = VTD_CE_GET_RID2PASID(ce);
pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(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; return ret;
} }
@ -781,7 +823,11 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
pasid = VTD_CE_GET_RID2PASID(ce); pasid = VTD_CE_GET_RID2PASID(ce);
pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(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) { if (ret) {
return ret; return ret;
} }
@ -791,7 +837,15 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s,
return 0; 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) { if (ret) {
return ret; return ret;
} }

View File

@ -479,6 +479,7 @@ typedef struct VTDRootEntry VTDRootEntry;
#define VTD_PASID_ENTRY_FPD (1ULL << 1) /* Fault Processing Disable */ #define VTD_PASID_ENTRY_FPD (1ULL << 1) /* Fault Processing Disable */
/* PASID Granular Translation Type Mask */ /* PASID Granular Translation Type Mask */
#define VTD_PASID_ENTRY_P 1ULL
#define VTD_SM_PASID_ENTRY_PGTT (7ULL << 6) #define VTD_SM_PASID_ENTRY_PGTT (7ULL << 6)
#define VTD_SM_PASID_ENTRY_FLT (1ULL << 6) #define VTD_SM_PASID_ENTRY_FLT (1ULL << 6)
#define VTD_SM_PASID_ENTRY_SLT (2ULL << 6) #define VTD_SM_PASID_ENTRY_SLT (2ULL << 6)