drivers/iommu/io-pgfault.c

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

File Facts

System
Linux kernel
Corpus path
drivers/iommu/io-pgfault.c
Extension
.c
Size
16426 bytes
Lines
550
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

if (IS_ERR(attach_handle)) {
			const struct iommu_ops *ops = dev_iommu_ops(dev);

			if (!ops->user_pasid_table)
				return NULL;
			/*
			 * The iommu driver for this device supports user-
			 * managed PASID table. Therefore page faults for
			 * any PASID should go through the NESTING domain
			 * attached to the device RID.
			 */
			attach_handle = iommu_attach_handle_get(
					dev->iommu_group, IOMMU_NO_PASID,
					IOMMU_DOMAIN_NESTED);
			if (IS_ERR(attach_handle))
				return NULL;
		}
	} else {
		attach_handle = iommu_attach_handle_get(dev->iommu_group,
				IOMMU_NO_PASID, 0);

		if (IS_ERR(attach_handle))
			return NULL;
	}

	if (!attach_handle->domain->iopf_handler)
		return NULL;

	return attach_handle;
}

static void iopf_error_response(struct device *dev, struct iopf_fault *evt)
{
	const struct iommu_ops *ops = dev_iommu_ops(dev);
	struct iommu_fault *fault = &evt->fault;
	struct iommu_page_response resp = {
		.pasid = fault->prm.pasid,
		.grpid = fault->prm.grpid,
		.code = IOMMU_PAGE_RESP_INVALID
	};

	ops->page_response(dev, evt, &resp);
}

/**
 * iommu_report_device_fault() - Report fault event to device driver
 * @dev: the device
 * @evt: fault event data
 *
 * Called by IOMMU drivers when a fault is detected, typically in a threaded IRQ
 * handler. If this function fails then ops->page_response() was called to
 * complete evt if required.
 *
 * This module doesn't handle PCI PASID Stop Marker; IOMMU drivers must discard
 * them before reporting faults. A PASID Stop Marker (LRW = 0b100) doesn't
 * expect a response. It may be generated when disabling a PASID (issuing a
 * PASID stop request) by some PCI devices.
 *
 * The PASID stop request is issued by the device driver before unbind(). Once
 * it completes, no page request is generated for this PASID anymore and
 * outstanding ones have been pushed to the IOMMU (as per PCIe 4.0r1.0 - 6.20.1
 * and 10.4.1.2 - Managing PASID TLP Prefix Usage). Some PCI devices will wait
 * for all outstanding page requests to come back with a response before
 * completing the PASID stop request. Others do not wait for page responses, and
 * instead issue this Stop Marker that tells us when the PASID can be
 * reallocated.
 *
 * It is safe to discard the Stop Marker because it is an optimization.
 * a. Page requests, which are posted requests, have been flushed to the IOMMU
 *    when the stop request completes.
 * b. The IOMMU driver flushes all fault queues on unbind() before freeing the
 *    PASID.
 *
 * So even though the Stop Marker might be issued by the device *after* the stop
 * request completes, outstanding faults will have been dealt with by the time
 * the PASID is freed.
 *
 * Any valid page fault will be eventually routed to an iommu domain and the
 * page fault handler installed there will get called. The users of this
 * handling framework should guarantee that the iommu domain could only be
 * freed after the device has stopped generating page faults (or the iommu
 * hardware has been set to block the page faults) and the pending page faults
 * have been flushed. In case no page fault handler is attached or no iopf params
 * are setup, then the ops->page_response() is called to complete the evt.
 *
 * Returns 0 on success, or an error in case of a bad/failed iopf setup.
 */
int iommu_report_device_fault(struct device *dev, struct iopf_fault *evt)
{
	struct iommu_attach_handle *attach_handle;

Annotation

Implementation Notes