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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/x86/cpuid_test.c
Extension
.c
Size
6027 bytes
Lines
241
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 cpuid_mask {
	union {
		struct {
			u32 eax;
			u32 ebx;
			u32 ecx;
			u32 edx;
		};
		u32 regs[4];
	};
};

static void test_guest_cpuids(struct kvm_cpuid2 *guest_cpuid)
{
	int i;
	u32 eax, ebx, ecx, edx;

	for (i = 0; i < guest_cpuid->nent; i++) {
		__cpuid(guest_cpuid->entries[i].function,
			guest_cpuid->entries[i].index,
			&eax, &ebx, &ecx, &edx);

		GUEST_ASSERT_EQ(eax, guest_cpuid->entries[i].eax);
		GUEST_ASSERT_EQ(ebx, guest_cpuid->entries[i].ebx);
		GUEST_ASSERT_EQ(ecx, guest_cpuid->entries[i].ecx);
		GUEST_ASSERT_EQ(edx, guest_cpuid->entries[i].edx);
	}

}

static void guest_main(struct kvm_cpuid2 *guest_cpuid)
{
	GUEST_SYNC(1);

	test_guest_cpuids(guest_cpuid);

	GUEST_SYNC(2);

	GUEST_ASSERT_EQ(this_cpu_property(X86_PROPERTY_MAX_KVM_LEAF), 0x40000001);

	GUEST_DONE();
}

static struct cpuid_mask get_const_cpuid_mask(const struct kvm_cpuid_entry2 *entry)
{
	struct cpuid_mask mask;

	memset(&mask, 0xff, sizeof(mask));

	switch (entry->function) {
	case 0x1:
		mask.regs[X86_FEATURE_OSXSAVE.reg] &= ~BIT(X86_FEATURE_OSXSAVE.bit);
		break;
	case 0x7:
		mask.regs[X86_FEATURE_OSPKE.reg] &= ~BIT(X86_FEATURE_OSPKE.bit);
		break;
	case 0xd:
		/*
		 * CPUID.0xD.{0,1}.EBX enumerate XSAVE size based on the current
		 * XCR0 and IA32_XSS MSR values.
		 */
		if (entry->index < 2)
			mask.ebx = 0;
		break;
	}
	return mask;
}

static void compare_cpuids(const struct kvm_cpuid2 *cpuid1,
			   const struct kvm_cpuid2 *cpuid2)
{
	const struct kvm_cpuid_entry2 *e1, *e2;
	int i;

	TEST_ASSERT(cpuid1->nent == cpuid2->nent,
		    "CPUID nent mismatch: %d vs. %d", cpuid1->nent, cpuid2->nent);

	for (i = 0; i < cpuid1->nent; i++) {
		struct cpuid_mask mask;

		e1 = &cpuid1->entries[i];
		e2 = &cpuid2->entries[i];

		TEST_ASSERT(e1->function == e2->function &&
			    e1->index == e2->index && e1->flags == e2->flags,
			    "CPUID entries[%d] mismtach: 0x%x.%d.%x vs. 0x%x.%d.%x",
			    i, e1->function, e1->index, e1->flags,
			    e2->function, e2->index, e2->flags);

		/* Mask off dynamic bits, e.g. OSXSAVE, when comparing entries. */

Annotation

Implementation Notes