mirror of
https://github.com/torvalds/linux.git
synced 2024-12-28 22:02:28 +00:00
iommu/vt-d: Fix VM domain ID leak
This continues the attempt to fix commitfb170fb4c5
("iommu/vt-d: Introduce helper functions to make code symmetric for readability"). The previous attempt in commit7168440690
("iommu/vt-d: Detach domain *only* from attached iommus") overlooked the fact that dmar_domain.iommu_bmp gets cleared for VM domains when devices are detached: intel_iommu_detach_device domain_remove_one_dev_info domain_detach_iommu The domain is detached from the iommu, but the iommu is still attached to the domain, for whatever reason. Thus when we get to domain_exit(), we can't rely on iommu_bmp for VM domains to find the active iommus, we must check them all. Without that, the corresponding bit in intel_iommu.domain_ids doesn't get cleared and repeated VM domain creation and destruction will run out of domain IDs. Meanwhile we still can't call iommu_detach_domain() on arbitrary non-VM domains or we risk clearing in-use domain IDs, as7168440690
attempted to address. It's tempting to modify iommu_detach_domain() to test the domain iommu_bmp, but the call ordering from domain_remove_one_dev_info() prevents it being able to work asfb170fb4c5
seems to have intended. Caching of unused VM domains on the iommu object seems to be the root of the problem, but this code is far too fragile for that kind of rework to be proposed for stable, so we simply revert this chunk to its state prior tofb170fb4c5
. Fixes:fb170fb4c5
("iommu/vt-d: Introduce helper functions to make code symmetric for readability") Fixes:7168440690
("iommu/vt-d: Detach domain *only* from attached iommus") Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Cc: Jiang Liu <jiang.liu@linux.intel.com> Cc: stable@vger.kernel.org # v3.17+ Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
5e92946c39
commit
46ebb7af7b
@ -1830,8 +1830,9 @@ static int domain_init(struct dmar_domain *domain, int guest_width)
|
||||
|
||||
static void domain_exit(struct dmar_domain *domain)
|
||||
{
|
||||
struct dmar_drhd_unit *drhd;
|
||||
struct intel_iommu *iommu;
|
||||
struct page *freelist = NULL;
|
||||
int i;
|
||||
|
||||
/* Domain 0 is reserved, so dont process it */
|
||||
if (!domain)
|
||||
@ -1851,8 +1852,10 @@ static void domain_exit(struct dmar_domain *domain)
|
||||
|
||||
/* clear attached or cached domains */
|
||||
rcu_read_lock();
|
||||
for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus)
|
||||
iommu_detach_domain(domain, g_iommus[i]);
|
||||
for_each_active_iommu(iommu, drhd)
|
||||
if (domain_type_is_vm(domain) ||
|
||||
test_bit(iommu->seq_id, domain->iommu_bmp))
|
||||
iommu_detach_domain(domain, iommu);
|
||||
rcu_read_unlock();
|
||||
|
||||
dma_free_pagelist(freelist);
|
||||
|
Loading…
Reference in New Issue
Block a user