tools/testing/selftests/kvm/access_tracking_perf_test.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/access_tracking_perf_test.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/access_tracking_perf_test.c
Extension
.c
Size
18055 bytes
Lines
610
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct test_params {
	/* The backing source for the region of memory. */
	enum vm_mem_backing_src_type backing_src;

	/* The amount of memory to allocate for each vCPU. */
	u64 vcpu_memory_bytes;

	/* The number of vCPUs to create in the VM. */
	int nr_vcpus;
};

static u64 pread_u64(int fd, const char *filename, u64 index)
{
	u64 value;
	off_t offset = index * sizeof(value);

	TEST_ASSERT(pread(fd, &value, sizeof(value), offset) == sizeof(value),
		    "pread from %s offset 0x%" PRIx64 " failed!",
		    filename, offset);

	return value;

}

#define PAGEMAP_PRESENT (1ULL << 63)
#define PAGEMAP_PFN_MASK ((1ULL << 55) - 1)

static u64 lookup_pfn(int pagemap_fd, struct kvm_vm *vm, gva_t gva)
{
	u64 hva = (u64)addr_gva2hva(vm, gva);
	u64 entry;
	u64 pfn;

	entry = pread_u64(pagemap_fd, "pagemap", hva / getpagesize());
	if (!(entry & PAGEMAP_PRESENT))
		return 0;

	pfn = entry & PAGEMAP_PFN_MASK;
	__TEST_REQUIRE(pfn, "Looking up PFNs requires CAP_SYS_ADMIN");

	return pfn;
}

static bool is_page_idle(int page_idle_fd, u64 pfn)
{
	u64 bits = pread_u64(page_idle_fd, "page_idle", pfn / 64);

	return !!((bits >> (pfn % 64)) & 1);
}

static void mark_page_idle(int page_idle_fd, u64 pfn)
{
	u64 bits = 1ULL << (pfn % 64);

	TEST_ASSERT(pwrite(page_idle_fd, &bits, 8, 8 * (pfn / 64)) == 8,
		    "Set page_idle bits for PFN 0x%" PRIx64, pfn);
}

static void too_many_idle_pages(long idle_pages, long total_pages, int vcpu_idx)
{
	char prefix[18] = {};

	if (vcpu_idx >= 0)
		snprintf(prefix, 18, "vCPU%d: ", vcpu_idx);

	TEST_ASSERT(idle_pages_warn_only,
		    "%sToo many pages still idle (%lu out of %lu)",
		    prefix, idle_pages, total_pages);

	printf("WARNING: %sToo many pages still idle (%lu out of %lu), "
	       "this will affect performance results.\n",
	       prefix, idle_pages, total_pages);
}

static void pageidle_mark_vcpu_memory_idle(struct kvm_vm *vm,
					   struct memstress_vcpu_args *vcpu_args)
{
	int vcpu_idx = vcpu_args->vcpu_idx;
	gva_t base_gva = vcpu_args->gva;
	u64 pages = vcpu_args->pages;
	u64 page;
	u64 still_idle = 0;
	u64 no_pfn = 0;
	int page_idle_fd;
	int pagemap_fd;

	/* If vCPUs are using an overlapping region, let vCPU 0 mark it idle. */
	if (overlap_memory_access && vcpu_idx)
		return;

Annotation

Implementation Notes