summaryrefslogtreecommitdiff |
diff options
author | Denis Kirjanov <dkirjanov@suse.com> | 2019-09-25 15:31:15 +0300 |
---|---|---|
committer | Denis Kirjanov <dkirjanov@suse.com> | 2019-09-25 15:32:39 +0300 |
commit | 71e571706068dbd2331aef8758c56d14e8c1e73d (patch) | |
tree | b197d0fa664b441894a5d850157e957d37bfedee | |
parent | 434960562dc6d7386ca8cbff6247fa07f7bd10ae (diff) | |
parent | 0af899fa7efb2be934263241a9fa9117ce2a3ebc (diff) |
Merge 'users/jroedel/SLE12-SP5/for-next' into SLE12-SP5
Pull iommu fixes from Joerg Roedel
suse-commit: 846b396cb42728e55cfe179cce20d49117fd4547
-rw-r--r-- | drivers/iommu/amd_iommu.c | 40 | ||||
-rw-r--r-- | drivers/iommu/dma-iommu.c | 4 | ||||
-rw-r--r-- | drivers/iommu/iommu.c | 4 | ||||
-rw-r--r-- | drivers/iommu/iova.c | 4 |
4 files changed, 43 insertions, 9 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index c5de09e89b21..5b87e3af0dbe 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1154,6 +1154,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu *iommu) iommu_completion_wait(iommu); } +static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id) +{ + struct iommu_cmd cmd; + + build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS, + dom_id, 1); + iommu_queue_command(iommu, &cmd); + + iommu_completion_wait(iommu); +} + static void amd_iommu_flush_all(struct amd_iommu *iommu) { struct iommu_cmd cmd; @@ -1330,18 +1341,21 @@ static void domain_flush_devices(struct protection_domain *domain) * another level increases the size of the address space by 9 bits to a size up * to 64 bits. */ -static bool increase_address_space(struct protection_domain *domain, +static void increase_address_space(struct protection_domain *domain, gfp_t gfp) { + unsigned long flags; u64 *pte; - if (domain->mode == PAGE_MODE_6_LEVEL) + spin_lock_irqsave(&domain->lock, flags); + + if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL)) /* address space already 64 bit large */ - return false; + goto out; pte = (void *)get_zeroed_page(gfp); if (!pte) - return false; + goto out; *pte = PM_LEVEL_PDE(domain->mode, iommu_virt_to_phys(domain->pt_root)); @@ -1349,7 +1363,10 @@ static bool increase_address_space(struct protection_domain *domain, domain->mode += 1; domain->updated = true; - return true; +out: + spin_unlock_irqrestore(&domain->lock, flags); + + return; } static u64 *alloc_pte(struct protection_domain *domain, @@ -1838,6 +1855,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) { u64 pte_root = 0; u64 flags = 0; + u32 old_domid; if (domain->mode != PAGE_MODE_NONE) pte_root = iommu_virt_to_phys(domain->pt_root); @@ -1880,8 +1898,20 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) flags &= ~DEV_DOMID_MASK; flags |= domain->id; + old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK; amd_iommu_dev_table[devid].data[1] = flags; amd_iommu_dev_table[devid].data[0] = pte_root; + + /* + * A kdump kernel might be replacing a domain ID that was copied from + * the previous kernel--if so, it needs to flush the translation cache + * entries for the old domain ID that is being overwritten + */ + if (old_domid) { + struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; + + amd_iommu_flush_tlb_domid(iommu, old_domid); + } } static void clear_dte_entry(u16 devid) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 77b46701d707..bfecb837d009 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -292,13 +292,15 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, u64 size, struct device *dev) { struct iommu_dma_cookie *cookie = domain->iova_cookie; - struct iova_domain *iovad = &cookie->iovad; unsigned long order, base_pfn, end_pfn; + struct iova_domain *iovad; int attr; if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE) return -EINVAL; + iovad = &cookie->iovad; + /* Use the smallest supported page size for IOVA granularity */ order = __ffs(domain->pgsize_bitmap); base_pfn = max_t(unsigned long, 1, base >> order); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 5073ace42f58..9d20cce66ce2 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -134,8 +134,8 @@ static int __init iommu_subsys_init(void) else iommu_set_default_translated(false); - if (iommu_default_passthrough() && sme_active()) { - pr_info("SME detected - Disabling default IOMMU Passthrough\n"); + if (iommu_default_passthrough() && mem_encrypt_active()) { + pr_info("Memory encryption detected - Disabling default IOMMU Passthrough\n"); iommu_set_default_translated(false); } } diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c index 7b8d3afa35c3..c8032721c337 100644 --- a/drivers/iommu/iova.c +++ b/drivers/iommu/iova.c @@ -589,7 +589,9 @@ void queue_iova(struct iova_domain *iovad, spin_unlock_irqrestore(&fq->lock, flags); - if (atomic_cmpxchg(&iovad->fq_timer_on, 0, 1) == 0) + /* Avoid false sharing as much as possible. */ + if (!atomic_read(&iovad->fq_timer_on) && + !atomic_cmpxchg(&iovad->fq_timer_on, 0, 1)) mod_timer(&iovad->fq_timer, jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT)); |