tools/testing/selftests/kvm/x86/kvm_clock_test.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/x86/kvm_clock_test.c
Extension
.c
Size
3562 bytes
Lines
157
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_case {
	u64 kvmclock_base;
	s64 realtime_offset;
};

static struct test_case test_cases[] = {
	{ .kvmclock_base = 0 },
	{ .kvmclock_base = 180 * NSEC_PER_SEC },
	{ .kvmclock_base = 0, .realtime_offset = -180 * NSEC_PER_SEC },
	{ .kvmclock_base = 0, .realtime_offset = 180 * NSEC_PER_SEC },
};

#define GUEST_SYNC_CLOCK(__stage, __val)			\
		GUEST_SYNC_ARGS(__stage, __val, 0, 0, 0)

static void guest_main(gpa_t pvti_pa, struct pvclock_vcpu_time_info *pvti)
{
	int i;

	wrmsr(MSR_KVM_SYSTEM_TIME_NEW, pvti_pa | KVM_MSR_ENABLED);
	for (i = 0; i < ARRAY_SIZE(test_cases); i++)
		GUEST_SYNC_CLOCK(i, __pvclock_read_cycles(pvti, rdtsc()));
}

#define EXPECTED_FLAGS (KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC)

static inline void assert_flags(struct kvm_clock_data *data)
{
	TEST_ASSERT((data->flags & EXPECTED_FLAGS) == EXPECTED_FLAGS,
		    "unexpected clock data flags: %x (want set: %x)",
		    data->flags, EXPECTED_FLAGS);
}

static void handle_sync(struct ucall *uc, struct kvm_clock_data *start,
			struct kvm_clock_data *end)
{
	u64 obs, exp_lo, exp_hi;

	obs = uc->args[2];
	exp_lo = start->clock;
	exp_hi = end->clock;

	assert_flags(start);
	assert_flags(end);

	TEST_ASSERT(exp_lo <= obs && obs <= exp_hi,
		    "unexpected kvm-clock value: %"PRIu64" expected range: [%"PRIu64", %"PRIu64"]",
		    obs, exp_lo, exp_hi);

	pr_info("kvm-clock value: %"PRIu64" expected range [%"PRIu64", %"PRIu64"]\n",
		obs, exp_lo, exp_hi);
}

static void handle_abort(struct ucall *uc)
{
	REPORT_GUEST_ASSERT(*uc);
}

static void setup_clock(struct kvm_vm *vm, struct test_case *test_case)
{
	struct kvm_clock_data data;

	memset(&data, 0, sizeof(data));

	data.clock = test_case->kvmclock_base;
	if (test_case->realtime_offset) {
		struct timespec ts;
		int r;

		data.flags |= KVM_CLOCK_REALTIME;
		do {
			r = clock_gettime(CLOCK_REALTIME, &ts);
			if (!r)
				break;
		} while (errno == EINTR);

		TEST_ASSERT(!r, "clock_gettime() failed: %d", r);

		data.realtime = ts.tv_sec * NSEC_PER_SEC;
		data.realtime += ts.tv_nsec;
		data.realtime += test_case->realtime_offset;
	}

	vm_ioctl(vm, KVM_SET_CLOCK, &data);
}

static void enter_guest(struct kvm_vcpu *vcpu)
{
	struct kvm_clock_data start, end;
	struct kvm_vm *vm = vcpu->vm;

Annotation

Implementation Notes