Unverified Commit b3d782eb authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!4875 [OLK-6.6] backport latest v6.8 iommu fixes

Merge Pull Request from: @x56Jason 
 
# Description
Upstream Linus tree merged some latest iommu fixes in v6.8-rc6 cycle, which need backport.

# ISSUE
#I938E2

# Test
    - IOMMU Kernel selftest (with known upstream issue workaround)
        - All PASS
    - X86 Kernel Selftest
        - All PASS except LAM/shadow-stack cases which are not enabled and the result is the same as in baseline
    - VM Test with traditional VFIO/IOMMU api
        - Use Qemu to passthrough a NIC to guest VM, which exercises traditional VFIO/IOMMU code
            - Guest VM can run successfully and the NIC works well
    - VM Test with new VFIO/iommufd api
        - Use new Qemu command line to specify iommufd to passthrough a NIC to guest VM
            - Guest VM can run successfully and the NIC works well
    - SVA Test
        - Use DSA device (SVA enabled) on Intel EMR platform to do DMA memory copy
            - PASS, and IO page fault can be seen and handled successfully

# Known Issue
NA

# Default Kernel Config Change
NA
 
 
Link:https://gitee.com/openeuler/kernel/pulls/4875

 

Reviewed-by: default avatarAichun Shi <aichun.shi@intel.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents 40f699bc fc89654f
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -117,11 +117,11 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
	if (ret)
		goto out_free_domain;
	domain->users = 1;
	refcount_set(&handle->users, 1);
	list_add(&domain->next, &mm->iommu_mm->sva_domains);
	list_add(&handle->handle_item, &mm->iommu_mm->sva_handles);

out:
	refcount_set(&handle->users, 1);
	list_add(&handle->handle_item, &mm->iommu_mm->sva_handles);
	mutex_unlock(&iommu_sva_lock);
	handle->dev = dev;
	handle->domain = domain;
+6 −3
Original line number Diff line number Diff line
@@ -1330,20 +1330,23 @@ int iopt_disable_large_pages(struct io_pagetable *iopt)

int iopt_add_access(struct io_pagetable *iopt, struct iommufd_access *access)
{
	u32 new_id;
	int rc;

	down_write(&iopt->domains_rwsem);
	down_write(&iopt->iova_rwsem);
	rc = xa_alloc(&iopt->access_list, &access->iopt_access_list_id, access,
		      xa_limit_16b, GFP_KERNEL_ACCOUNT);
	rc = xa_alloc(&iopt->access_list, &new_id, access, xa_limit_16b,
		      GFP_KERNEL_ACCOUNT);

	if (rc)
		goto out_unlock;

	rc = iopt_calculate_iova_alignment(iopt);
	if (rc) {
		xa_erase(&iopt->access_list, access->iopt_access_list_id);
		xa_erase(&iopt->access_list, new_id);
		goto out_unlock;
	}
	access->iopt_access_list_id = new_id;

out_unlock:
	up_write(&iopt->iova_rwsem);
+48 −21
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ static struct mock_bus_type iommufd_mock_bus_type = {
	},
};

static atomic_t mock_dev_num;
static DEFINE_IDA(mock_dev_ida);

enum {
	MOCK_DIRTY_TRACK = 1,
@@ -63,7 +63,7 @@ enum {
 * In syzkaller mode the 64 bit IOVA is converted into an nth area and offset
 * value. This has a much smaller randomization space and syzkaller can hit it.
 */
static unsigned long iommufd_test_syz_conv_iova(struct io_pagetable *iopt,
static unsigned long __iommufd_test_syz_conv_iova(struct io_pagetable *iopt,
						  u64 *iova)
{
	struct syz_layout {
@@ -88,6 +88,21 @@ static unsigned long iommufd_test_syz_conv_iova(struct io_pagetable *iopt,
	return 0;
}

static unsigned long iommufd_test_syz_conv_iova(struct iommufd_access *access,
						u64 *iova)
{
	unsigned long ret;

	mutex_lock(&access->ioas_lock);
	if (!access->ioas) {
		mutex_unlock(&access->ioas_lock);
		return 0;
	}
	ret = __iommufd_test_syz_conv_iova(&access->ioas->iopt, iova);
	mutex_unlock(&access->ioas_lock);
	return ret;
}

void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd,
				   unsigned int ioas_id, u64 *iova, u32 *flags)
{
@@ -100,7 +115,7 @@ void iommufd_test_syz_conv_iova_id(struct iommufd_ucmd *ucmd,
	ioas = iommufd_get_ioas(ucmd->ictx, ioas_id);
	if (IS_ERR(ioas))
		return;
	*iova = iommufd_test_syz_conv_iova(&ioas->iopt, iova);
	*iova = __iommufd_test_syz_conv_iova(&ioas->iopt, iova);
	iommufd_put_object(ucmd->ictx, &ioas->obj);
}

@@ -123,6 +138,7 @@ enum selftest_obj_type {
struct mock_dev {
	struct device dev;
	unsigned long flags;
	int id;
};

struct selftest_obj {
@@ -430,20 +446,27 @@ static size_t mock_domain_unmap_pages(struct iommu_domain *domain,

			/*
			 * iommufd generates unmaps that must be a strict
			 * superset of the map's performend So every starting
			 * IOVA should have been an iova passed to map, and the
			 * superset of the map's performend So every
			 * starting/ending IOVA should have been an iova passed
			 * to map.
			 *
			 * First IOVA must be present and have been a first IOVA
			 * passed to map_pages
			 * This simple logic doesn't work when the HUGE_PAGE is
			 * turned on since the core code will automatically
			 * switch between the two page sizes creating a break in
			 * the unmap calls. The break can land in the middle of
			 * contiguous IOVA.
			 */
			if (!(domain->pgsize_bitmap & MOCK_HUGE_PAGE_SIZE)) {
				if (first) {
					WARN_ON(ent && !(xa_to_value(ent) &
							 MOCK_PFN_START_IOVA));
					first = false;
				}
			if (pgcount == 1 && cur + MOCK_IO_PAGE_SIZE == pgsize)
				if (pgcount == 1 &&
				    cur + MOCK_IO_PAGE_SIZE == pgsize)
					WARN_ON(ent && !(xa_to_value(ent) &
							 MOCK_PFN_LAST_IOVA));
			}

			iova += MOCK_IO_PAGE_SIZE;
			ret += MOCK_IO_PAGE_SIZE;
@@ -631,7 +654,7 @@ static void mock_dev_release(struct device *dev)
{
	struct mock_dev *mdev = container_of(dev, struct mock_dev, dev);

	atomic_dec(&mock_dev_num);
	ida_free(&mock_dev_ida, mdev->id);
	kfree(mdev);
}

@@ -653,8 +676,12 @@ static struct mock_dev *mock_dev_create(unsigned long dev_flags)
	mdev->dev.release = mock_dev_release;
	mdev->dev.bus = &iommufd_mock_bus_type.bus;

	rc = dev_set_name(&mdev->dev, "iommufd_mock%u",
			  atomic_inc_return(&mock_dev_num));
	rc = ida_alloc(&mock_dev_ida, GFP_KERNEL);
	if (rc < 0)
		goto err_put;
	mdev->id = rc;

	rc = dev_set_name(&mdev->dev, "iommufd_mock%u", mdev->id);
	if (rc)
		goto err_put;

@@ -1156,7 +1183,7 @@ static int iommufd_test_access_pages(struct iommufd_ucmd *ucmd,
	}

	if (flags & MOCK_FLAGS_ACCESS_SYZ)
		iova = iommufd_test_syz_conv_iova(&staccess->access->ioas->iopt,
		iova = iommufd_test_syz_conv_iova(staccess->access,
					&cmd->access_pages.iova);

	npages = (ALIGN(iova + length, PAGE_SIZE) -
@@ -1258,7 +1285,7 @@ static int iommufd_test_access_rw(struct iommufd_ucmd *ucmd,
	}

	if (flags & MOCK_FLAGS_ACCESS_SYZ)
		iova = iommufd_test_syz_conv_iova(&staccess->access->ioas->iopt,
		iova = iommufd_test_syz_conv_iova(staccess->access,
				&cmd->access_rw.iova);

	rc = iommufd_access_rw(staccess->access, iova, tmp, length, flags);