drivers/hv/hv_proc.c

Source file repositories/reference/linux-study-clean/drivers/hv/hv_proc.c

File Facts

System
Linux kernel
Corpus path
drivers/hv/hv_proc.c
Extension
.c
Size
7146 bytes
Lines
289
Domain
Driver Families
Bucket
drivers/hv
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

while (1) {
			pages[i] = alloc_pages_node(node, GFP_KERNEL, order);
			if (pages[i])
				break;
			if (!order) {
				ret = -ENOMEM;
				num_allocations = i;
				goto err_free_allocations;
			}
			--order;
		}

		split_page(pages[i], order);
		counts[i] = 1 << order;
		num_pages -= counts[i];
		i++;
	}
	num_allocations = i;

	local_irq_save(flags);

	input_page = *this_cpu_ptr(hyperv_pcpu_input_arg);

	input_page->partition_id = partition_id;

	/* Populate gpa_page_list - these will fit on the input page */
	for (i = 0, page_count = 0; i < num_allocations; ++i) {
		base_pfn = page_to_pfn(pages[i]);
		for (j = 0; j < counts[i]; ++j, ++page_count)
			input_page->gpa_page_list[page_count] = base_pfn + j;
	}
	status = hv_do_rep_hypercall(HVCALL_DEPOSIT_MEMORY,
				     page_count, 0, input_page, NULL);
	local_irq_restore(flags);
	if (!hv_result_success(status)) {
		hv_status_err(status, "\n");
		ret = hv_result_to_errno(status);
		goto err_free_allocations;
	}

	ret = 0;
	goto free_buf;

err_free_allocations:
	for (i = 0; i < num_allocations; ++i) {
		base_pfn = page_to_pfn(pages[i]);
		for (j = 0; j < counts[i]; ++j)
			__free_page(pfn_to_page(base_pfn + j));
	}

free_buf:
	free_page((unsigned long)pages);
	kfree(counts);
	return ret;
}
EXPORT_SYMBOL_GPL(hv_call_deposit_pages);

int hv_deposit_memory_node(int node, u64 partition_id,
			   u64 hv_status)
{
	u32 num_pages = 1;

	switch (hv_result(hv_status)) {
	case HV_STATUS_INSUFFICIENT_MEMORY:
		break;
	case HV_STATUS_INSUFFICIENT_CONTIGUOUS_MEMORY:
		num_pages = HV_MAX_CONTIGUOUS_ALLOCATION_PAGES;
		break;

	case HV_STATUS_INSUFFICIENT_CONTIGUOUS_ROOT_MEMORY:
		num_pages = HV_MAX_CONTIGUOUS_ALLOCATION_PAGES;
		fallthrough;
	case HV_STATUS_INSUFFICIENT_ROOT_MEMORY:
		if (!hv_root_partition()) {
			hv_status_err(hv_status, "Unexpected root memory deposit\n");
			return -ENOMEM;
		}
		partition_id = HV_PARTITION_ID_SELF;
		break;

	default:
		hv_status_err(hv_status, "Unexpected!\n");
		return -ENOMEM;
	}
	return hv_call_deposit_pages(node, partition_id, num_pages);
}
EXPORT_SYMBOL_GPL(hv_deposit_memory_node);

bool hv_result_needs_memory(u64 status)
{

Annotation

Implementation Notes