Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
xen.26345
xsa400-00c.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa400-00c.patch of Package xen.26345
# Commit 32655880057ce2829f962d46916ea6cec60f98d3 # Date 2021-06-24 16:29:13 +0200 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> VT-d: adjust domid map updating when unmapping context When an earlier error occurred, cleaning up the domid mapping data is wrong, as references likely still exist. The only exception to this is when the actual unmapping worked, but some flush failed (supposedly impossible after XSA-373). The guest will get crashed in such a case though, so add fallback cleanup to domain destruction to cover this case. This in turn makes it desirable to silence the dprintk() in domain_iommu_domid(). Note that no error will be returned anymore when the lookup fails - in the common case lookup failure would already have caused domain_context_unmap_one() to fail, yet even from a more general perspective it doesn't look right to fail domain_context_unmap() in such a case when this was the last device, but not when any earlier unmap was otherwise successful. Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> --- a/xen/drivers/passthrough/vtd/iommu.c +++ b/xen/drivers/passthrough/vtd/iommu.c @@ -67,9 +67,11 @@ static int domain_iommu_domid(struct dom i = find_next_bit(iommu->domid_bitmap, nr_dom, i+1); } - dprintk(XENLOG_ERR VTDPREFIX, - "Cannot get valid iommu domid: domid=%d iommu->index=%d\n", - d->domain_id, iommu->index); + if ( !d->is_dying ) + dprintk(XENLOG_ERR VTDPREFIX, + "Cannot get valid iommu %u domid: Dom%d\n", + iommu->index, d->domain_id); + return -1; } @@ -152,6 +154,23 @@ static void __init free_intel_iommu(stru 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 int iommus_incoherent; static void sync_cache(const void *addr, unsigned int size) @@ -1732,6 +1751,9 @@ static int domain_context_unmap(struct d goto out; } + if ( ret ) + 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 @@ -1751,25 +1773,8 @@ static int domain_context_unmap(struct d 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); + cleanup_domid_map(domain, iommu); } out: @@ -1779,6 +1784,7 @@ out: static void iommu_domain_teardown(struct domain *d) { struct domain_iommu *hd = dom_iommu(d); + const struct acpi_drhd_unit *drhd; if ( list_empty(&acpi_drhd_units) ) return; @@ -1792,6 +1798,9 @@ static void iommu_domain_teardown(struct iommu_free_pagetable(hd->arch.pgd_maddr, agaw_to_level(hd->arch.agaw)); hd->arch.pgd_maddr = 0; spin_unlock(&hd->arch.mapping_lock); + + for_each_drhd_unit ( drhd ) + cleanup_domid_map(d, drhd->iommu); } static int __must_check intel_iommu_map_page(struct domain *d,
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor