lib/test_hmm.c

Source file repositories/reference/linux-study-clean/lib/test_hmm.c

File Facts

System
Linux kernel
Corpus path
lib/test_hmm.c
Extension
.c
Size
46546 bytes
Lines
1874
Domain
Kernel Services
Bucket
lib
Inferred role
Kernel Services: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations dmirror_fops = {
	.open		= dmirror_fops_open,
	.release	= dmirror_fops_release,
	.mmap		= dmirror_fops_mmap,
	.unlocked_ioctl = dmirror_fops_unlocked_ioctl,
	.llseek		= default_llseek,
	.owner		= THIS_MODULE,
};

static void dmirror_devmem_free(struct folio *folio)
{
	struct page *page = &folio->page;
	struct page *rpage = BACKING_PAGE(page);
	struct dmirror_device *mdevice;
	struct folio *rfolio = page_folio(rpage);
	unsigned int order = folio_order(rfolio);

	if (rpage != page) {
		if (order)
			__free_pages(rpage, order);
		else
			__free_page(rpage);
		rpage = NULL;
	}

	mdevice = dmirror_page_to_device(page);
	spin_lock(&mdevice->lock);

	/* Return page to our allocator if not freeing the chunk */
	if (!dmirror_page_to_chunk(page)->remove) {
		mdevice->cfree += 1 << order;
		if (order) {
			page->zone_device_data = mdevice->free_folios;
			mdevice->free_folios = page_folio(page);
		} else {
			page->zone_device_data = mdevice->free_pages;
			mdevice->free_pages = page;
		}
	}
	spin_unlock(&mdevice->lock);
}

static vm_fault_t dmirror_devmem_fault(struct vm_fault *vmf)
{
	struct migrate_vma args = { 0 };
	struct page *rpage;
	struct dmirror *dmirror;
	vm_fault_t ret = 0;
	unsigned int order, nr;

	/*
	 * Normally, a device would use the page->zone_device_data to point to
	 * the mirror but here we use it to hold the page for the simulated
	 * device memory and that page holds the pointer to the mirror.
	 */
	rpage = folio_zone_device_data(page_folio(vmf->page));
	dmirror = rpage->zone_device_data;

	/* FIXME demonstrate how we can adjust migrate range */
	order = folio_order(page_folio(vmf->page));
	nr = 1 << order;

	/*
	 * When folios are partially mapped, we can't rely on the folio
	 * order of vmf->page as the folio might not be fully split yet
	 */
	if (vmf->pte) {
		order = 0;
		nr = 1;
	}

	/*
	 * Consider a per-cpu cache of src and dst pfns, but with
	 * large number of cpus that might not scale well.
	 */
	args.start = ALIGN_DOWN(vmf->address, (PAGE_SIZE << order));
	args.vma = vmf->vma;
	args.end = args.start + (PAGE_SIZE << order);

	nr = (args.end - args.start) >> PAGE_SHIFT;
	args.src = kcalloc(nr, sizeof(unsigned long), GFP_KERNEL);
	args.dst = kcalloc(nr, sizeof(unsigned long), GFP_KERNEL);
	args.pgmap_owner = dmirror->mdevice;
	args.flags = dmirror_select_device(dmirror);
	args.fault_page = vmf->page;

	if (!args.src || !args.dst) {
		ret = VM_FAULT_OOM;
		goto err;
	}

Annotation

Implementation Notes