Commit 47e231cb authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'iommu-fixes-v7.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux

Pull iommu fixes from Joerg Roedel:
 "Intel VT-d:
   - Abort all pending requests on dev_tlb_inv timeout to avoid
     hardlockup
   - Limit IOPF handling to PRI-capable device to avoid SVA attach
     failure

  AMD-Vi:
   - Make sure identity domain is not used when SNP is active

  Core fixes:
   - Handle mapping IOVA 0x0 correctly
   - Fix crash in SVA code
   - Kernel-doc fix in IO-PGTable code"

* tag 'iommu-fixes-v7.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux:
  iommu/amd: Block identity domain when SNP enabled
  iommu/sva: Fix crash in iommu_sva_unbind_device()
  iommu/io-pgtable: fix all kernel-doc warnings in io-pgtable.h
  iommu: Fix mapping check for 0x0 to avoid re-mapping it
  iommu/vt-d: Only handle IOPF for SVA when PRI is supported
  iommu/vt-d: Fix intel iommu iotlb sync hardlockup and retry
parents 16516026 ba17de98
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -2909,8 +2909,21 @@ static struct iommu_domain blocked_domain = {

static struct protection_domain identity_domain;

static int amd_iommu_identity_attach(struct iommu_domain *dom, struct device *dev,
				     struct iommu_domain *old)
{
	/*
	 * Don't allow attaching a device to the identity domain if SNP is
	 * enabled.
	 */
	if (amd_iommu_snp_en)
		return -EINVAL;

	return amd_iommu_attach_device(dom, dev, old);
}

static const struct iommu_domain_ops identity_domain_ops = {
	.attach_dev = amd_iommu_attach_device,
	.attach_dev = amd_iommu_identity_attach,
};

void amd_iommu_init_identity_domain(void)
+1 −2
Original line number Diff line number Diff line
@@ -1314,7 +1314,6 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index)
	if (fault & DMA_FSTS_ITE) {
		head = readl(iommu->reg + DMAR_IQH_REG);
		head = ((head >> shift) - 1 + QI_LENGTH) % QI_LENGTH;
		head |= 1;
		tail = readl(iommu->reg + DMAR_IQT_REG);
		tail = ((tail >> shift) - 1 + QI_LENGTH) % QI_LENGTH;

@@ -1331,7 +1330,7 @@ static int qi_check_fault(struct intel_iommu *iommu, int index, int wait_index)
		do {
			if (qi->desc_status[head] == QI_IN_USE)
				qi->desc_status[head] = QI_ABORT;
			head = (head - 2 + QI_LENGTH) % QI_LENGTH;
			head = (head - 1 + QI_LENGTH) % QI_LENGTH;
		} while (head != tail);

		/*
+8 −4
Original line number Diff line number Diff line
@@ -164,9 +164,12 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
	if (IS_ERR(dev_pasid))
		return PTR_ERR(dev_pasid);

	/* SVA with non-IOMMU/PRI IOPF handling is allowed. */
	if (info->pri_supported) {
		ret = iopf_for_domain_replace(domain, old, dev);
		if (ret)
			goto out_remove_dev_pasid;
	}

	/* Setup the pasid table: */
	sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
@@ -181,6 +184,7 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,

	return 0;
out_unwind_iopf:
	if (info->pri_supported)
		iopf_for_domain_replace(old, domain, dev);
out_remove_dev_pasid:
	domain_remove_dev_pasid(domain, dev, pasid);
+6 −6
Original line number Diff line number Diff line
@@ -182,15 +182,15 @@ void iommu_sva_unbind_device(struct iommu_sva *handle)
	iommu_detach_device_pasid(domain, dev, iommu_mm->pasid);
	if (--domain->users == 0) {
		list_del(&domain->next);
		iommu_domain_free(domain);
	}

		if (list_empty(&iommu_mm->sva_domains)) {
			list_del(&iommu_mm->mm_list_elm);
			if (list_empty(&iommu_sva_mms))
				iommu_sva_present = false;
		}

		iommu_domain_free(domain);
	}

	mutex_unlock(&iommu_sva_lock);
	kfree(handle);
}
+5 −1
Original line number Diff line number Diff line
@@ -1213,7 +1213,11 @@ static int iommu_create_device_direct_mappings(struct iommu_domain *domain,
			if (addr == end)
				goto map_end;

			phys_addr = iommu_iova_to_phys(domain, addr);
			/*
			 * Return address by iommu_iova_to_phys for 0 is
			 * ambiguous. Offset to address 1 if addr is 0.
			 */
			phys_addr = iommu_iova_to_phys(domain, addr ? addr : 1);
			if (!phys_addr) {
				map_size += pg_size;
				continue;
Loading