drivers/iommu/iommu-sva.c

Source file repositories/reference/linux-study-clean/drivers/iommu/iommu-sva.c

File Facts

System
Linux kernel
Corpus path
drivers/iommu/iommu-sva.c
Extension
.c
Size
8678 bytes
Lines
343
Domain
Driver Families
Bucket
drivers/iommu
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

ret = handle_mm_fault(vma, prm->addr, fault_flags, NULL);
	status = ret & VM_FAULT_ERROR ? IOMMU_PAGE_RESP_INVALID :
		IOMMU_PAGE_RESP_SUCCESS;

out_put_mm:
	mmap_read_unlock(mm);
	mmput(mm);

	return status;
}

static void iommu_sva_handle_iopf(struct work_struct *work)
{
	struct iopf_fault *iopf;
	struct iopf_group *group;
	enum iommu_page_response_code status = IOMMU_PAGE_RESP_SUCCESS;

	group = container_of(work, struct iopf_group, work);
	list_for_each_entry(iopf, &group->faults, list) {
		/*
		 * For the moment, errors are sticky: don't handle subsequent
		 * faults in the group if there is an error.
		 */
		if (status != IOMMU_PAGE_RESP_SUCCESS)
			break;

		status = iommu_sva_handle_mm(&iopf->fault,
					     group->attach_handle->domain->mm);
	}

	iopf_group_response(group, status);
	iopf_free_group(group);
}

static int iommu_sva_iopf_handler(struct iopf_group *group)
{
	struct iommu_fault_param *fault_param = group->fault_param;

	INIT_WORK(&group->work, iommu_sva_handle_iopf);
	if (!queue_work(fault_param->queue->wq, &group->work))
		return -EBUSY;

	return 0;
}

static struct iommu_domain *iommu_sva_domain_alloc(struct device *dev,
						   struct mm_struct *mm)
{
	const struct iommu_ops *ops = dev_iommu_ops(dev);
	struct iommu_domain *domain;

	if (!ops->domain_alloc_sva)
		return ERR_PTR(-EOPNOTSUPP);

	domain = ops->domain_alloc_sva(dev, mm);
	if (IS_ERR(domain))
		return domain;

	domain->type = IOMMU_DOMAIN_SVA;
	domain->cookie_type = IOMMU_COOKIE_SVA;
	mmgrab(mm);
	domain->mm = mm;
	domain->owner = ops;
	domain->iopf_handler = iommu_sva_iopf_handler;

	return domain;
}

void iommu_sva_invalidate_kva_range(unsigned long start, unsigned long end)
{
	struct iommu_mm_data *iommu_mm;

	guard(mutex)(&iommu_sva_lock);
	if (!iommu_sva_present)
		return;

	list_for_each_entry(iommu_mm, &iommu_sva_mms, mm_list_elm)
		mmu_notifier_arch_invalidate_secondary_tlbs(iommu_mm->mm, start, end);
}

Annotation

Implementation Notes