drivers/iommu/generic_pt/iommu_pt.h

Source file repositories/reference/linux-study-clean/drivers/iommu/generic_pt/iommu_pt.h

File Facts

System
Linux kernel
Corpus path
drivers/iommu/generic_pt/iommu_pt.h
Extension
.h
Size
39929 bytes
Lines
1370
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

struct iommupt_pending_gather {
	struct iommu_iotlb_gather *iotlb_gather;
	struct iommu_pages_list free_list;
	u8 leaf_levels_bitmap;
	u8 table_levels_bitmap;
};

static void gather_add_table(struct iommupt_pending_gather *pending,
			     const struct pt_state *pts,
			     struct pt_table_p *table)
{
	iommu_pages_list_add(&pending->free_list, table);
	if (pts_feature(pts, PT_FEAT_DETAILED_GATHER))
		pending->table_levels_bitmap |= BIT(pts->level);
}

static void gather_add_leaf(struct iommupt_pending_gather *pending,
			    const struct pt_state *pts)
{
	if (!pts_feature(pts, PT_FEAT_DETAILED_GATHER))
		return;

	pending->leaf_levels_bitmap |= BIT(pts->level);
}

static void gather_range_pending(struct iommupt_pending_gather *pending,
				 struct pt_iommu *iommu_table, pt_vaddr_t iova,
				 pt_vaddr_t len)
{
	struct iommu_iotlb_gather *iotlb_gather = pending->iotlb_gather;
	struct pt_common *common = common_from_iommu(iommu_table);

	if (pt_feature(common, PT_FEAT_DMA_INCOHERENT))
		iommu_pages_stop_incoherent_list(&pending->free_list,
						 iommu_table->iommu_device);

	/*
	 * If running in DMA-FQ mode then the unmap will be followed by an IOTLB
	 * flush all so we need to optimize by never flushing the IOTLB here.
	 *
	 * For NO_GAPS the user gets to pick if flushing all or doing micro
	 * flushes is better for their work load by choosing DMA vs DMA-FQ
	 * operation. Drivers should also see shadow_on_flush.
	 */
	if (!iommu_iotlb_gather_queued(iotlb_gather)) {
		if (pt_feature(common, PT_FEAT_FLUSH_RANGE_NO_GAPS) &&
		    iommu_iotlb_gather_is_disjoint(iotlb_gather, iova, len)) {
			iommu_iotlb_sync(&iommu_table->domain, iotlb_gather);
			/*
			 * Note that the sync frees the gather's free list, so
			 * we must not have any pages on that list that are
			 * covered by iova/len
			 */
		}
		iommu_iotlb_gather_add_range(iotlb_gather, iova, len);
	}

	iommu_pages_list_splice(&pending->free_list, &iotlb_gather->freelist);
	INIT_LIST_HEAD(&pending->free_list.pages);

	if (pt_feature(common, PT_FEAT_DETAILED_GATHER)) {
		iotlb_gather->pt.leaf_levels_bitmap |=
			pending->leaf_levels_bitmap;
		iotlb_gather->pt.table_levels_bitmap |=
			pending->table_levels_bitmap;
		pending->leaf_levels_bitmap = 0;
		pending->table_levels_bitmap = 0;
	}
}

#define DOMAIN_NS(op) CONCATENATE(CONCATENATE(pt_iommu_, PTPFX), op)

static int make_range_ul(struct pt_common *common, struct pt_range *range,
			 unsigned long iova, unsigned long len)
{
	unsigned long last;

	if (unlikely(len == 0))
		return -EINVAL;

	if (check_add_overflow(iova, len - 1, &last))
		return -EOVERFLOW;

	*range = pt_make_range(common, iova, last);
	if (sizeof(iova) > sizeof(range->va)) {
		if (unlikely(range->va != iova || range->last_va != last))
			return -EOVERFLOW;
	}
	return 0;
}

Annotation

Implementation Notes