drivers/iommu/generic_pt/pt_iter.h

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

File Facts

System
Linux kernel
Corpus path
drivers/iommu/generic_pt/pt_iter.h
Extension
.h
Size
20360 bytes
Lines
659
Domain
Driver Families
Bucket
drivers/iommu
Inferred role
Driver Families: implementation source
Status
source 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

#ifndef __GENERIC_PT_PT_ITER_H
#define __GENERIC_PT_PT_ITER_H

#include "pt_common.h"

#include <linux/errno.h>

/*
 * Use to mangle symbols so that backtraces and the symbol table are
 * understandable. Any non-inlined function should get mangled like this.
 */
#define NS(fn) CONCATENATE(PTPFX, fn)

/**
 * pt_check_range() - Validate the range can be iterated
 * @range: Range to validate
 *
 * Check that VA and last_va fall within the permitted range of VAs. If the
 * format is using PT_FEAT_SIGN_EXTEND then this also checks the sign extension
 * is correct.
 */
static inline int pt_check_range(struct pt_range *range)
{
	pt_vaddr_t prefix;

	PT_WARN_ON(!range->max_vasz_lg2);

	if (pt_feature(range->common, PT_FEAT_SIGN_EXTEND)) {
		PT_WARN_ON(range->common->max_vasz_lg2 != range->max_vasz_lg2);
		prefix = fvalog2_div(range->va, range->max_vasz_lg2 - 1) ?
				 PT_VADDR_MAX :
				 0;
	} else {
		prefix = pt_full_va_prefix(range->common);
	}

	if (!fvalog2_div_eq(range->va, prefix, range->max_vasz_lg2) ||
	    !fvalog2_div_eq(range->last_va, prefix, range->max_vasz_lg2))
		return -ERANGE;
	return 0;
}

/**
 * pt_index_to_va() - Update range->va to the current pts->index
 * @pts: Iteration State
 *
 * Adjust range->va to match the current index. This is done in a lazy manner
 * since computing the VA takes several instructions and is rarely required.
 */
static inline void pt_index_to_va(struct pt_state *pts)
{
	pt_vaddr_t lower_va;

	lower_va = log2_mul(pts->index, pt_table_item_lg2sz(pts));
	pts->range->va = fvalog2_set_mod(pts->range->va, lower_va,
					 pt_table_oa_lg2sz(pts));
}

/*
 * Add index_count_lg2 number of entries to pts's VA and index. The VA will be
 * adjusted to the end of the contiguous block if it is currently in the middle.
 */
static inline void _pt_advance(struct pt_state *pts,
			       unsigned int index_count_lg2)
{
	pts->index = log2_set_mod(pts->index + log2_to_int(index_count_lg2), 0,
				  index_count_lg2);
}

/**
 * pt_entry_fully_covered() - Check if the item or entry is entirely contained
 *                            within pts->range
 * @pts: Iteration State
 * @oasz_lg2: The size of the item to check, pt_table_item_lg2sz() or
 *            pt_entry_oa_lg2sz()
 *
 * Returns: true if the item is fully enclosed by the pts->range.
 */
static inline bool pt_entry_fully_covered(const struct pt_state *pts,
					  unsigned int oasz_lg2)
{
	struct pt_range *range = pts->range;

	/* Range begins at the start of the entry */
	if (log2_mod(pts->range->va, oasz_lg2))
		return false;

	/* Range ends past the end of the entry */
	if (!log2_div_eq(range->va, range->last_va, oasz_lg2))
		return true;

Annotation

Implementation Notes