diff mbox series

[v10,7/7] KVM: selftests: update hyperv_cpuid with SynDBG tests

Message ID 20200324074341.1770081-8-arilou@gmail.com (mailing list archive)
State New, archived
Headers show
Series x86/kvm/hyper-v: add support for synthetic debugger | expand

Commit Message

Jon Doron March 24, 2020, 7:43 a.m. UTC
From: Vitaly Kuznetsov <vkuznets () redhat ! com>

Test all four combinations with eVMCS and SynDBG capabilities,
check that we get the right number of entries and that
0x40000000.EAX always returns the correct max leaf.

Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 .../selftests/kvm/x86_64/hyperv_cpuid.c       | 139 ++++++++++++------
 1 file changed, 96 insertions(+), 43 deletions(-)

Comments

Vitaly Kuznetsov March 24, 2020, 9:05 a.m. UTC | #1
Jon Doron <arilou@gmail.com> writes:

> From: Vitaly Kuznetsov <vkuznets () redhat ! com>
>
> Test all four combinations with eVMCS and SynDBG capabilities,
> check that we get the right number of entries and that
> 0x40000000.EAX always returns the correct max leaf.
>
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Something weird happened to this patch. It fails to apply on kvm/queue
but it's also a bit different from what I've sent yesterday. I fixed and
tested it, please find the result attached.
Jon Doron April 16, 2020, 11:05 a.m. UTC | #2
Did this patchset make it into the merge window?

Thanks,
-- Jon.

On 24/03/2020, Vitaly Kuznetsov wrote:
>Jon Doron <arilou@gmail.com> writes:
>
>> From: Vitaly Kuznetsov <vkuznets () redhat ! com>
>>
>> Test all four combinations with eVMCS and SynDBG capabilities,
>> check that we get the right number of entries and that
>> 0x40000000.EAX always returns the correct max leaf.
>>
>> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
>
>Something weird happened to this patch. It fails to apply on kvm/queue
>but it's also a bit different from what I've sent yesterday. I fixed and
>tested it, please find the result attached.
>
>-- 
>Vitaly
>

>From ae2c688389c20a99d7457861e57ce97054780908 Mon Sep 17 00:00:00 2001
>From: Vitaly Kuznetsov <vkuznets () redhat ! com>
>Date: Tue, 24 Mar 2020 09:43:41 +0200
>Subject: [PATCH v10 7/7 FIXED] KVM: selftests: update hyperv_cpuid with SynDBG
> tests
>
>Test all four combinations with eVMCS and SynDBG capabilities,
>check that we get the right number of entries and that
>0x40000000.EAX always returns the correct max leaf.
>
>Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
>---
> .../selftests/kvm/x86_64/hyperv_cpuid.c       | 143 ++++++++++++------
> 1 file changed, 95 insertions(+), 48 deletions(-)
>
>diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
>index 83323f3d7ca0..5268abf9ad80 100644
>--- a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
>+++ b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
>@@ -26,18 +26,18 @@ static void guest_code(void)
> {
> }
> 
>-static int smt_possible(void)
>+static bool smt_possible(void)
> {
> 	char buf[16];
> 	FILE *f;
>-	bool res = 1;
>+	bool res = true;
> 
> 	f = fopen("/sys/devices/system/cpu/smt/control", "r");
> 	if (f) {
> 		if (fread(buf, sizeof(*buf), sizeof(buf), f) > 0) {
> 			if (!strncmp(buf, "forceoff", 8) ||
> 			    !strncmp(buf, "notsupported", 12))
>-				res = 0;
>+				res = false;
> 		}
> 		fclose(f);
> 	}
>@@ -45,30 +45,48 @@ static int smt_possible(void)
> 	return res;
> }
> 
>+void vcpu_enable_syndbg(struct kvm_vm *vm, int vcpu_id)
>+{
>+	struct kvm_enable_cap enable_syndbg_cap = {
>+		.cap = KVM_CAP_HYPERV_SYNDBG,
>+	};
>+
>+	vcpu_ioctl(vm, vcpu_id, KVM_ENABLE_CAP, &enable_syndbg_cap);
>+}
>+
> static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries,
>-			  int evmcs_enabled)
>+			  bool evmcs_enabled, bool syndbg_enabled)
> {
> 	int i;
>+	int nent = 6;
>+	u32 test_val;
>+
>+	if (evmcs_enabled)
>+		nent += 1; /* 0x4000000A */
> 
>-	if (!evmcs_enabled)
>-		TEST_ASSERT(hv_cpuid_entries->nent == 6,
>-			    "KVM_GET_SUPPORTED_HV_CPUID should return 6 entries"
>-			    " when Enlightened VMCS is disabled (returned %d)",
>-			    hv_cpuid_entries->nent);
>-	else
>-		TEST_ASSERT(hv_cpuid_entries->nent == 7,
>-			    "KVM_GET_SUPPORTED_HV_CPUID should return 7 entries"
>-			    " when Enlightened VMCS is enabled (returned %d)",
>-			    hv_cpuid_entries->nent);
>+	if (syndbg_enabled)
>+		nent += 3; /* 0x40000080 - 0x40000082 */
>+
>+	TEST_ASSERT(hv_cpuid_entries->nent == nent,
>+		    "KVM_GET_SUPPORTED_HV_CPUID should return %d entries"
>+		    " with evmcs=%d syndbg=%d (returned %d)",
>+		    nent, evmcs_enabled, syndbg_enabled,
>+		    hv_cpuid_entries->nent);
> 
> 	for (i = 0; i < hv_cpuid_entries->nent; i++) {
> 		struct kvm_cpuid_entry2 *entry = &hv_cpuid_entries->entries[i];
> 
> 		TEST_ASSERT((entry->function >= 0x40000000) &&
>-			    (entry->function <= 0x4000000A),
>+			    (entry->function <= 0x40000082),
> 			    "function %x is our of supported range",
> 			    entry->function);
> 
>+		TEST_ASSERT(evmcs_enabled || (entry->function != 0x4000000A),
>+			    "0x4000000A leaf should not be reported");
>+
>+		TEST_ASSERT(syndbg_enabled || (entry->function <= 0x4000000A),
>+			    "SYNDBG leaves should not be reported");
>+
> 		TEST_ASSERT(entry->index == 0,
> 			    ".index field should be zero");
> 
>@@ -78,12 +96,27 @@ static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries,
> 		TEST_ASSERT(!entry->padding[0] && !entry->padding[1] &&
> 			    !entry->padding[2], "padding should be zero");
> 
>-		if (entry->function == 0x40000004) {
>-			int nononarchcs = !!(entry->eax & (1UL << 18));
>-
>-			TEST_ASSERT(nononarchcs == !smt_possible(),
>+		switch (entry->function) {
>+		case 0x40000000:
>+			test_val = 0x40000005;
>+			if (evmcs_enabled)
>+				test_val = 0x4000000A;
>+			if (syndbg_enabled)
>+				test_val = 0x40000082;
>+
>+			TEST_ASSERT(entry->eax == test_val,
>+				    "Wrong max leaf report in 0x40000000.EAX: %x"
>+				    " (evmcs=%d syndbg=%d)",
>+				    entry->eax, evmcs_enabled, syndbg_enabled
>+				);
>+			break;
>+		case 0x40000004:
>+			test_val = entry->eax & (1UL << 18);
>+
>+			TEST_ASSERT(!!test_val == !smt_possible(),
> 				    "NoNonArchitecturalCoreSharing bit"
> 				    " doesn't reflect SMT setting");
>+			break;
> 		}
> 
> 		/*
>@@ -133,8 +166,9 @@ struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(struct kvm_vm *vm)
> int main(int argc, char *argv[])
> {
> 	struct kvm_vm *vm;
>-	int rv;
>+	int rv, stage;
> 	struct kvm_cpuid2 *hv_cpuid_entries;
>+	bool evmcs_enabled, syndbg_enabled;
> 
> 	/* Tell stdout not to buffer its content */
> 	setbuf(stdout, NULL);
>@@ -145,36 +179,49 @@ int main(int argc, char *argv[])
> 		exit(KSFT_SKIP);
> 	}
> 
>-	/* Create VM */
>-	vm = vm_create_default(VCPU_ID, 0, guest_code);
>-
>-	test_hv_cpuid_e2big(vm);
>-
>-	hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
>-	if (!hv_cpuid_entries)
>-		return 1;
>-
>-	test_hv_cpuid(hv_cpuid_entries, 0);
>-
>-	free(hv_cpuid_entries);
>+	for (stage = 0; stage < 5; stage++) {
>+		evmcs_enabled = false;
>+		syndbg_enabled = false;
>+
>+		vm = vm_create_default(VCPU_ID, 0, guest_code);
>+		switch (stage) {
>+		case 0:
>+			test_hv_cpuid_e2big(vm);
>+			continue;
>+		case 1:
>+			break;
>+		case 2:
>+			if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
>+				print_skip("Enlightened VMCS is unsupported");
>+				continue;
>+			}
>+			vcpu_enable_evmcs(vm, VCPU_ID);
>+			evmcs_enabled = true;
>+			break;
>+		case 3:
>+			if (!kvm_check_cap(KVM_CAP_HYPERV_SYNDBG)) {
>+				print_skip("Synthetic debugger is unsupported");
>+				continue;
>+			}
>+			vcpu_enable_syndbg(vm, VCPU_ID);
>+			syndbg_enabled = true;
>+			break;
>+		case 4:
>+			if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS) ||
>+			    !kvm_check_cap(KVM_CAP_HYPERV_SYNDBG))
>+				continue;
>+			vcpu_enable_evmcs(vm, VCPU_ID);
>+			vcpu_enable_syndbg(vm, VCPU_ID);
>+			evmcs_enabled = true;
>+			syndbg_enabled = true;
>+			break;
>+		}
> 
>-	if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
>-		print_skip("Enlightened VMCS is unsupported");
>-		goto vm_free;
>+		hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
>+		test_hv_cpuid(hv_cpuid_entries, evmcs_enabled, syndbg_enabled);
>+		free(hv_cpuid_entries);
>+		kvm_vm_free(vm);
> 	}
> 
>-	vcpu_enable_evmcs(vm, VCPU_ID);
>-
>-	hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
>-	if (!hv_cpuid_entries)
>-		return 1;
>-
>-	test_hv_cpuid(hv_cpuid_entries, 1);
>-
>-	free(hv_cpuid_entries);
>-
>-vm_free:
>-	kvm_vm_free(vm);
>-
> 	return 0;
> }
>-- 
>2.25.1
>
Vitaly Kuznetsov April 16, 2020, 1:19 p.m. UTC | #3
Jon Doron <arilou@gmail.com> writes:

> Did this patchset make it into the merge window?
>

My crystal ball tells me we should ask Paolo (To:) ;-)
diff mbox series

Patch

diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
index 443a2b54645b..e63b0e1c253d 100644
--- a/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
+++ b/tools/testing/selftests/kvm/x86_64/hyperv_cpuid.c
@@ -26,18 +26,18 @@  static void guest_code(void)
 {
 }
 
-static int smt_possible(void)
+static bool smt_possible(void)
 {
 	char buf[16];
 	FILE *f;
-	bool res = 1;
+	bool res = true;
 
 	f = fopen("/sys/devices/system/cpu/smt/control", "r");
 	if (f) {
 		if (fread(buf, sizeof(*buf), sizeof(buf), f) > 0) {
 			if (!strncmp(buf, "forceoff", 8) ||
 			    !strncmp(buf, "notsupported", 12))
-				res = 0;
+				res = false;
 		}
 		fclose(f);
 	}
@@ -45,30 +45,48 @@  static int smt_possible(void)
 	return res;
 }
 
+void vcpu_enable_syndbg(struct kvm_vm *vm, int vcpu_id)
+{
+	struct kvm_enable_cap enable_syndbg_cap = {
+		.cap = KVM_CAP_HYPERV_SYNDBG,
+	};
+
+	vcpu_ioctl(vm, vcpu_id, KVM_ENABLE_CAP, &enable_syndbg_cap);
+}
+
 static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries,
-			  int evmcs_enabled)
+			  bool evmcs_enabled, bool syndbg_enabled)
 {
 	int i;
+	int nent = 6;
+	u32 test_val;
+
+	if (evmcs_enabled)
+		nent += 1; /* 0x4000000A */
 
-	if (!evmcs_enabled)
-		TEST_ASSERT(hv_cpuid_entries->nent == 6,
-			    "KVM_GET_SUPPORTED_HV_CPUID should return 6 entries"
-			    " when Enlightened VMCS is disabled (returned %d)",
-			    hv_cpuid_entries->nent);
-	else
-		TEST_ASSERT(hv_cpuid_entries->nent == 7,
-			    "KVM_GET_SUPPORTED_HV_CPUID should return 7 entries"
-			    " when Enlightened VMCS is enabled (returned %d)",
-			    hv_cpuid_entries->nent);
+	if (syndbg_enabled)
+		nent += 3; /* 0x40000080 - 0x40000082 */
+
+	TEST_ASSERT(hv_cpuid_entries->nent == nent,
+		    "KVM_GET_SUPPORTED_HV_CPUID should return %d entries"
+		    " with evmcs=%d syndbg=%d (returned %d)",
+		    nent, evmcs_enabled, syndbg_enabled,
+		    hv_cpuid_entries->nent);
 
 	for (i = 0; i < hv_cpuid_entries->nent; i++) {
 		struct kvm_cpuid_entry2 *entry = &hv_cpuid_entries->entries[i];
 
 		TEST_ASSERT((entry->function >= 0x40000000) &&
-			    (entry->function <= 0x4000000A),
+			    (entry->function <= 0x40000082),
 			    "function %lx is our of supported range",
 			    entry->function);
 
+		TEST_ASSERT(evmcs_enabled || (entry->function != 0x4000000A),
+			    "0x4000000A leaf should not be reported");
+
+		TEST_ASSERT(syndbg_enabled || (entry->function <= 0x4000000A),
+			    "SYNDBG leaves should not be reported");
+
 		TEST_ASSERT(entry->index == 0,
 			    ".index field should be zero");
 
@@ -78,12 +96,27 @@  static void test_hv_cpuid(struct kvm_cpuid2 *hv_cpuid_entries,
 		TEST_ASSERT(!entry->padding[0] && !entry->padding[1] &&
 			    !entry->padding[2], "padding should be zero");
 
-		if (entry->function == 0x40000004) {
-			int nononarchcs = !!(entry->eax & (1UL << 18));
-
-			TEST_ASSERT(nononarchcs == !smt_possible(),
+		switch (entry->function) {
+		case 0x40000000:
+			test_val = 0x40000005;
+			if (evmcs_enabled)
+				test_val = 0x4000000A;
+			if (syndbg_enabled)
+				test_val = 0x40000082;
+
+			TEST_ASSERT(entry->eax == test_val,
+				    "Wrong max leaf report in 0x40000000.EAX: %x"
+				    " (evmcs=%d syndbg=%d)",
+				    entry->eax, evmcs_enabled, syndbg_enabled
+				);
+			break;
+		case 0x40000004:
+			test_val = entry->eax & (1UL << 18);
+
+			TEST_ASSERT(!!test_val == !smt_possible(),
 				    "NoNonArchitecturalCoreSharing bit"
 				    " doesn't reflect SMT setting");
+			break;
 		}
 
 		/*
@@ -133,8 +166,9 @@  struct kvm_cpuid2 *kvm_get_supported_hv_cpuid(struct kvm_vm *vm)
 int main(int argc, char *argv[])
 {
 	struct kvm_vm *vm;
-	int rv;
+	int rv, stage;
 	struct kvm_cpuid2 *hv_cpuid_entries;
+	bool evmcs_enabled, syndbg_enabled;
 
 	/* Tell stdout not to buffer its content */
 	setbuf(stdout, NULL);
@@ -151,32 +185,51 @@  int main(int argc, char *argv[])
 
 	test_hv_cpuid_e2big(vm);
 
-	hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
-	if (!hv_cpuid_entries)
-		return 1;
-
-	test_hv_cpuid(hv_cpuid_entries, 0);
+	kvm_vm_free(vm);
 
-	free(hv_cpuid_entries);
+	for (stage = 0; stage < 5; stage++) {
+		evmcs_enabled = false;
+		syndbg_enabled = false;
+
+		vm = vm_create_default(VCPU_ID, 0, guest_code);
+		switch (stage) {
+		case 0:
+			test_hv_cpuid_e2big(vm);
+			continue;
+		case 1:
+			break;
+		case 2:
+			if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
+				print_skip("Enlightened VMCS is unsupported");
+				continue;
+			}
+			vcpu_enable_evmcs(vm, VCPU_ID);
+			evmcs_enabled = true;
+			break;
+		case 3:
+			if (!kvm_check_cap(KVM_CAP_HYPERV_SYNDBG)) {
+				print_skip("Synthetic debugger is unsupported");
+				continue;
+			}
+			vcpu_enable_syndbg(vm, VCPU_ID);
+			syndbg_enabled = true;
+			break;
+		case 4:
+			if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS) ||
+			    !kvm_check_cap(KVM_CAP_HYPERV_SYNDBG))
+				continue;
+			vcpu_enable_evmcs(vm, VCPU_ID);
+			vcpu_enable_syndbg(vm, VCPU_ID);
+			evmcs_enabled = true;
+			syndbg_enabled = true;
+			break;
+		}
 
-	if (!kvm_check_cap(KVM_CAP_HYPERV_ENLIGHTENED_VMCS)) {
-		fprintf(stderr,
-			"Enlightened VMCS is unsupported, skip related test\n");
-		goto vm_free;
+		hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
+		test_hv_cpuid(hv_cpuid_entries, evmcs_enabled, syndbg_enabled);
+		free(hv_cpuid_entries);
+		kvm_vm_free(vm);
 	}
 
-	vcpu_enable_evmcs(vm, VCPU_ID);
-
-	hv_cpuid_entries = kvm_get_supported_hv_cpuid(vm);
-	if (!hv_cpuid_entries)
-		return 1;
-
-	test_hv_cpuid(hv_cpuid_entries, 1);
-
-	free(hv_cpuid_entries);
-
-vm_free:
-	kvm_vm_free(vm);
-
 	return 0;
 }