mirror of https://github.com/xqemu/xqemu.git
intel_iommu: allow dev-iotlb context entry conditionally
When device-iotlb is not specified, we should fail this check. A new function vtd_ce_type_check() is introduced. While I'm at it, clean up the vtd_dev_to_context_entry() a bit - replace many "else if" usage into direct if check. That'll make the logic more clear. Signed-off-by: Peter Xu <peterx@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
5a38cb5940
commit
f80c98740e
|
@ -600,6 +600,26 @@ static inline uint32_t vtd_ce_get_type(VTDContextEntry *ce)
|
||||||
return ce->lo & VTD_CONTEXT_ENTRY_TT;
|
return ce->lo & VTD_CONTEXT_ENTRY_TT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return true if check passed, otherwise false */
|
||||||
|
static inline bool vtd_ce_type_check(X86IOMMUState *x86_iommu,
|
||||||
|
VTDContextEntry *ce)
|
||||||
|
{
|
||||||
|
switch (vtd_ce_get_type(ce)) {
|
||||||
|
case VTD_CONTEXT_TT_MULTI_LEVEL:
|
||||||
|
/* Always supported */
|
||||||
|
break;
|
||||||
|
case VTD_CONTEXT_TT_DEV_IOTLB:
|
||||||
|
if (!x86_iommu->dt_supported) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Unknwon type */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint64_t vtd_iova_limit(VTDContextEntry *ce)
|
static inline uint64_t vtd_iova_limit(VTDContextEntry *ce)
|
||||||
{
|
{
|
||||||
uint32_t ce_agaw = vtd_ce_get_agaw(ce);
|
uint32_t ce_agaw = vtd_ce_get_agaw(ce);
|
||||||
|
@ -836,6 +856,7 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
|
||||||
{
|
{
|
||||||
VTDRootEntry re;
|
VTDRootEntry re;
|
||||||
int ret_fr;
|
int ret_fr;
|
||||||
|
X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s);
|
||||||
|
|
||||||
ret_fr = vtd_get_root_entry(s, bus_num, &re);
|
ret_fr = vtd_get_root_entry(s, bus_num, &re);
|
||||||
if (ret_fr) {
|
if (ret_fr) {
|
||||||
|
@ -846,7 +867,9 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
|
||||||
/* Not error - it's okay we don't have root entry. */
|
/* Not error - it's okay we don't have root entry. */
|
||||||
trace_vtd_re_not_present(bus_num);
|
trace_vtd_re_not_present(bus_num);
|
||||||
return -VTD_FR_ROOT_ENTRY_P;
|
return -VTD_FR_ROOT_ENTRY_P;
|
||||||
} else if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD)) {
|
}
|
||||||
|
|
||||||
|
if (re.rsvd || (re.val & VTD_ROOT_ENTRY_RSVD)) {
|
||||||
trace_vtd_re_invalid(re.rsvd, re.val);
|
trace_vtd_re_invalid(re.rsvd, re.val);
|
||||||
return -VTD_FR_ROOT_ENTRY_RSVD;
|
return -VTD_FR_ROOT_ENTRY_RSVD;
|
||||||
}
|
}
|
||||||
|
@ -860,26 +883,26 @@ static int vtd_dev_to_context_entry(IntelIOMMUState *s, uint8_t bus_num,
|
||||||
/* Not error - it's okay we don't have context entry. */
|
/* Not error - it's okay we don't have context entry. */
|
||||||
trace_vtd_ce_not_present(bus_num, devfn);
|
trace_vtd_ce_not_present(bus_num, devfn);
|
||||||
return -VTD_FR_CONTEXT_ENTRY_P;
|
return -VTD_FR_CONTEXT_ENTRY_P;
|
||||||
} else if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) ||
|
}
|
||||||
(ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO)) {
|
|
||||||
|
if ((ce->hi & VTD_CONTEXT_ENTRY_RSVD_HI) ||
|
||||||
|
(ce->lo & VTD_CONTEXT_ENTRY_RSVD_LO)) {
|
||||||
trace_vtd_ce_invalid(ce->hi, ce->lo);
|
trace_vtd_ce_invalid(ce->hi, ce->lo);
|
||||||
return -VTD_FR_CONTEXT_ENTRY_RSVD;
|
return -VTD_FR_CONTEXT_ENTRY_RSVD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the programming of context-entry is valid */
|
/* Check if the programming of context-entry is valid */
|
||||||
if (!vtd_is_level_supported(s, vtd_ce_get_level(ce))) {
|
if (!vtd_is_level_supported(s, vtd_ce_get_level(ce))) {
|
||||||
trace_vtd_ce_invalid(ce->hi, ce->lo);
|
trace_vtd_ce_invalid(ce->hi, ce->lo);
|
||||||
return -VTD_FR_CONTEXT_ENTRY_INV;
|
return -VTD_FR_CONTEXT_ENTRY_INV;
|
||||||
} else {
|
|
||||||
switch (vtd_ce_get_type(ce)) {
|
|
||||||
case VTD_CONTEXT_TT_MULTI_LEVEL:
|
|
||||||
/* fall through */
|
|
||||||
case VTD_CONTEXT_TT_DEV_IOTLB:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
trace_vtd_ce_invalid(ce->hi, ce->lo);
|
|
||||||
return -VTD_FR_CONTEXT_ENTRY_INV;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do translation type check */
|
||||||
|
if (!vtd_ce_type_check(x86_iommu, ce)) {
|
||||||
|
trace_vtd_ce_invalid(ce->hi, ce->lo);
|
||||||
|
return -VTD_FR_CONTEXT_ENTRY_INV;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue