tools/testing/selftests/kvm/mmu_stress_test.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/mmu_stress_test.c
Extension
.c
Size
12029 bytes
Lines
426
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 vcpu_info {
	struct kvm_vcpu *vcpu;
	u64 start_gpa;
	u64 end_gpa;
};

static int nr_vcpus;
static atomic_t rendezvous;
static atomic_t nr_ro_faults;

static void rendezvous_with_boss(void)
{
	int orig = atomic_read(&rendezvous);

	if (orig > 0) {
		atomic_dec_and_test(&rendezvous);
		while (atomic_read(&rendezvous) > 0)
			cpu_relax();
	} else {
		atomic_inc(&rendezvous);
		while (atomic_read(&rendezvous) < 0)
			cpu_relax();
	}
}

static void assert_sync_stage(struct kvm_vcpu *vcpu, int stage)
{
	struct ucall uc;

	TEST_ASSERT_EQ(get_ucall(vcpu, &uc), UCALL_SYNC);
	TEST_ASSERT_EQ(uc.args[1], stage);
}

static void run_vcpu(struct kvm_vcpu *vcpu, int stage)
{
	vcpu_run(vcpu);
	assert_sync_stage(vcpu, stage);
}

static void *vcpu_worker(void *data)
{
	struct kvm_sregs __maybe_unused sregs;
	struct vcpu_info *info = data;
	struct kvm_vcpu *vcpu = info->vcpu;
	struct kvm_vm *vm = vcpu->vm;
	int r;

	vcpu_args_set(vcpu, 3, info->start_gpa, info->end_gpa, vm->page_size);

	rendezvous_with_boss();

	/* Stage 0, write all of guest memory. */
	run_vcpu(vcpu, 0);
	rendezvous_with_boss();
#ifdef __x86_64__
	vcpu_sregs_get(vcpu, &sregs);
	/* Toggle CR0.WP to trigger a MMU context reset. */
	sregs.cr0 ^= X86_CR0_WP;
	vcpu_sregs_set(vcpu, &sregs);
#endif
	rendezvous_with_boss();

	/* Stage 1, re-write all of guest memory. */
	run_vcpu(vcpu, 1);
	rendezvous_with_boss();

	/* Stage 2, read all of guest memory, which is now read-only. */
	run_vcpu(vcpu, 2);

	/*
	 * Stage 3, write guest memory and verify KVM returns -EFAULT for once
	 * the mprotect(PROT_READ) lands.  Only architectures that support
	 * validating *all* of guest memory sync for this stage, as vCPUs will
	 * be stuck on the faulting instruction for other architectures.  Go to
	 * stage 3 without a rendezvous
	 */
	r = _vcpu_run(vcpu);
	TEST_ASSERT(r == -1 && errno == EFAULT,
		    "Expected EFAULT on write to RO memory, got r = %d, errno = %d", r, errno);

	atomic_inc(&nr_ro_faults);
	if (atomic_read(&nr_ro_faults) == nr_vcpus) {
		WRITE_ONCE(all_vcpus_hit_ro_fault, true);
		sync_global_to_guest(vm, all_vcpus_hit_ro_fault);
	}

#if defined(__x86_64__) || defined(__aarch64__)
	/*
	 * Verify *all* writes from the guest hit EFAULT due to the VMA now
	 * being read-only.  x86 and arm64 only at this time as skipping the

Annotation

Implementation Notes