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

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/kvm/x86/hyperv_cpuid.c
Extension
.c
Size
4383 bytes
Lines
171
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

switch (entry->function) {
		case 0x40000000:
			test_val = 0x40000082;

			TEST_ASSERT(entry->eax == test_val,
				    "Wrong max leaf report in 0x40000000.EAX: %x"
				    " (evmcs=%d)",
				    entry->eax, evmcs_expected
				);
			break;
		case 0x40000003:
			TEST_ASSERT(has_irqchip || !(entry->edx & BIT(19)),
				    "\"Direct\" Synthetic Timers should require in-kernel APIC");
			break;
		case 0x40000004:
			test_val = entry->eax & (1UL << 18);

			TEST_ASSERT(!!test_val == !is_smt_possible(),
				    "NoNonArchitecturalCoreSharing bit"
				    " doesn't reflect SMT setting");

			TEST_ASSERT(has_irqchip || !(entry->eax & BIT(10)),
				    "Cluster IPI (i.e. SEND_IPI) should require in-kernel APIC");
			break;
		case 0x4000000A:
			TEST_ASSERT(entry->eax & (1UL << 19),
				    "Enlightened MSR-Bitmap should always be supported"
				    " 0x40000000.EAX: %x", entry->eax);
			if (evmcs_expected)
				TEST_ASSERT((entry->eax & 0xffff) == 0x101,
				    "Supported Enlightened VMCS version range is supposed to be 1:1"
				    " 0x40000000.EAX: %x", entry->eax);

			break;
		default:
			break;

		}
		/*
		 * If needed for debug:
		 * fprintf(stdout,
		 *	"CPUID%lx EAX=0x%lx EBX=0x%lx ECX=0x%lx EDX=0x%lx\n",
		 *	entry->function, entry->eax, entry->ebx, entry->ecx,
		 *	entry->edx);
		 */
	}

	/*
	 * Note, the CPUID array returned by the system-scoped helper is a one-
	 * time allocation, i.e. must not be freed.
	 */
	if (vcpu)
		free((void *)hv_cpuid_entries);
}

static void test_hv_cpuid_e2big(struct kvm_vm *vm, struct kvm_vcpu *vcpu)
{
	static struct kvm_cpuid2 cpuid = {.nent = 0};
	int ret;

	if (vcpu)
		ret = __vcpu_ioctl(vcpu, KVM_GET_SUPPORTED_HV_CPUID, &cpuid);
	else
		ret = __kvm_ioctl(vm->kvm_fd, KVM_GET_SUPPORTED_HV_CPUID, &cpuid);

	TEST_ASSERT(ret == -1 && errno == E2BIG,
		    "%s KVM_GET_SUPPORTED_HV_CPUID didn't fail with -E2BIG when"
		    " it should have: %d %d", !vcpu ? "KVM" : "vCPU", ret, errno);
}

int main(int argc, char *argv[])
{
	struct kvm_vm *vm;
	struct kvm_vcpu *vcpu;

	TEST_REQUIRE(kvm_has_cap(KVM_CAP_HYPERV_CPUID));

	/* Test the vCPU ioctl without an in-kernel local APIC. */
	vm = vm_create_barebones();
	vcpu = __vm_vcpu_add(vm, 0);
	test_hv_cpuid(vcpu, false);
	kvm_vm_free(vm);

	/* Test vCPU ioctl version */
	vm = vm_create_with_one_vcpu(&vcpu, guest_code);
	test_hv_cpuid_e2big(vm, vcpu);
	test_hv_cpuid(vcpu, false);

	if (!kvm_cpu_has(X86_FEATURE_VMX) ||
	    !kvm_has_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {

Annotation

Implementation Notes