tools/testing/selftests/kvm/kvm_page_table_test.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/kvm_page_table_test.c
Extension
.c
Size
13680 bytes
Lines
491
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_args {
	struct kvm_vm *vm;
	u64 guest_test_virt_mem;
	u64 host_page_size;
	u64 host_num_pages;
	u64 large_page_size;
	u64 large_num_pages;
	u64 host_pages_per_lpage;
	enum vm_mem_backing_src_type src_type;
	struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
};

/*
 * Guest variables. Use addr_gva2hva() if these variables need
 * to be changed in host.
 */
static enum test_stage guest_test_stage;

/* Host variables */
static u32 nr_vcpus = 1;
static struct test_args test_args;
static enum test_stage *current_stage;
static bool host_quit;

/* Whether the test stage is updated, or completed */
static sem_t test_stage_updated;
static sem_t test_stage_completed;

/*
 * Guest physical memory offset of the testing memory slot.
 * This will be set to the topmost valid physical address minus
 * the test memory size.
 */
static u64 guest_test_phys_mem;

/*
 * Guest virtual memory offset of the testing memory slot.
 * Must not conflict with identity mapped test code.
 */
static u64 guest_test_virt_mem = DEFAULT_GUEST_TEST_MEM;

static void guest_code(bool do_write)
{
	struct test_args *p = &test_args;
	enum test_stage *current_stage = &guest_test_stage;
	u64 addr;
	int i, j;

	while (true) {
		addr = p->guest_test_virt_mem;

		switch (READ_ONCE(*current_stage)) {
		/*
		 * All vCPU threads will be started in this stage,
		 * where guest code of each vCPU will do nothing.
		 */
		case KVM_BEFORE_MAPPINGS:
			break;

		/*
		 * Before dirty logging, vCPUs concurrently access the first
		 * 8 bytes of each page (host page/large page) within the same
		 * memory region with different accessing types (read/write).
		 * Then KVM will create normal page mappings or huge block
		 * mappings for them.
		 */
		case KVM_CREATE_MAPPINGS:
			for (i = 0; i < p->large_num_pages; i++) {
				if (do_write)
					*(u64 *)addr = 0x0123456789ABCDEF;
				else
					READ_ONCE(*(u64 *)addr);

				addr += p->large_page_size;
			}
			break;

		/*
		 * During dirty logging, KVM will only update attributes of the
		 * normal page mappings from RO to RW if memory backing src type
		 * is anonymous. In other cases, KVM will split the huge block
		 * mappings into normal page mappings if memory backing src type
		 * is THP or HUGETLB.
		 */
		case KVM_UPDATE_MAPPINGS:
			if (p->src_type == VM_MEM_SRC_ANONYMOUS) {
				for (i = 0; i < p->host_num_pages; i++) {
					*(u64 *)addr = 0x0123456789ABCDEF;
					addr += p->host_page_size;
				}

Annotation

Implementation Notes