[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen stable-4.12] VT-d: split domid map cleanup check into a function
commit 5f3027e00666c248e8a25015b8e202cd321890ab Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Tue Apr 5 15:36:09 2022 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Tue Apr 5 15:36:09 2022 +0200 VT-d: split domid map cleanup check into a function This logic will want invoking from elsewhere. No functional change intended. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx> master commit: 9fdc10abe9457e4c9879a266f82372cb08e88ffb master date: 2021-11-24 11:06:20 +0100 --- xen/drivers/passthrough/vtd/iommu.c | 104 ++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 40 deletions(-) diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c index e7ba56e809..410dc216b2 100644 --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -152,6 +152,68 @@ static void __init free_intel_iommu(struct intel_iommu *intel) xfree(intel); } +static void cleanup_domid_map(struct domain *domain, struct iommu *iommu) +{ + int iommu_domid = domain_iommu_domid(domain, iommu); + + if ( iommu_domid >= 0 ) + { + /* + * Update domid_map[] /before/ domid_bitmap[] to avoid a race with + * context_set_domain_id(), setting the slot to DOMID_INVALID for + * ->domid_map[] reads to produce a suitable value while the bit is + * still set. + */ + iommu->domid_map[iommu_domid] = DOMID_INVALID; + clear_bit(iommu_domid, iommu->domid_bitmap); + } +} + +static bool any_pdev_behind_iommu(const struct domain *d, + const struct pci_dev *exclude, + const struct iommu *iommu) +{ + const struct pci_dev *pdev; + + for_each_pdev ( d, pdev ) + { + const struct acpi_drhd_unit *drhd; + + if ( pdev == exclude ) + continue; + + drhd = acpi_find_matched_drhd_unit(pdev); + if ( drhd && drhd->iommu == iommu ) + return true; + } + + return false; +} + +/* + * If no other devices under the same iommu owned by this domain, + * clear iommu in iommu_bitmap and clear domain_id in domid_bitmap. + */ +static void check_cleanup_domid_map(struct domain *d, + const struct pci_dev *exclude, + struct iommu *iommu) +{ + bool found = any_pdev_behind_iommu(d, exclude, iommu); + + /* + * Hidden devices are associated with DomXEN but usable by the hardware + * domain. Hence they need considering here as well. + */ + if ( !found && is_hardware_domain(d) ) + found = any_pdev_behind_iommu(dom_xen, exclude, iommu); + + if ( !found ) + { + clear_bit(iommu->index, &dom_iommu(d)->arch.iommu_bitmap); + cleanup_domid_map(d, iommu); + } +} + static int iommus_incoherent; static void sync_cache(const void *addr, unsigned int size) @@ -1671,7 +1733,6 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, struct iommu *iommu; int ret = 0; u8 seg = pdev->seg, bus = pdev->bus, tmp_bus, tmp_devfn, secbus; - int found = 0; drhd = acpi_find_matched_drhd_unit(pdev); if ( !drhd ) @@ -1740,45 +1801,8 @@ static int domain_context_unmap(struct domain *domain, u8 devfn, goto out; } - /* - * if no other devices under the same iommu owned by this domain, - * clear iommu in iommu_bitmap and clear domain_id in domid_bitmp - */ - for_each_pdev ( domain, pdev ) - { - if ( pdev->seg == seg && pdev->bus == bus && pdev->devfn == devfn ) - continue; - - drhd = acpi_find_matched_drhd_unit(pdev); - if ( drhd && drhd->iommu == iommu ) - { - found = 1; - break; - } - } - - if ( found == 0 ) - { - int iommu_domid; - - clear_bit(iommu->index, &dom_iommu(domain)->arch.iommu_bitmap); - - iommu_domid = domain_iommu_domid(domain, iommu); - if ( iommu_domid == -1 ) - { - ret = -EINVAL; - goto out; - } - - /* - * Update domid_map[] /before/ domid_bitmap[] to avoid a race with - * context_set_domain_id(), setting the slot to DOMID_INVALID for - * ->domid_map[] reads to produce a suitable value while the bit is - * still set. - */ - iommu->domid_map[iommu_domid] = DOMID_INVALID; - clear_bit(iommu_domid, iommu->domid_bitmap); - } + if ( !ret ) + check_cleanup_domid_map(domain, pdev, iommu); out: return ret; -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.12
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |