From: Thomas Huth <thuth@redhat.com>
To: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Paolo Bonzini <pbonzini@redhat.com>,
Sean Christopherson <seanjc@google.com>
Cc: linux-kselftest@vger.kernel.org, David Matlack <dmatlack@google.com>
Subject: [PATCH 2/4] KVM: selftests: x86: Use TAP interface in the sync_regs test
Date: Wed, 12 Jul 2023 09:59:08 +0200 [thread overview]
Message-ID: <20230712075910.22480-3-thuth@redhat.com> (raw)
In-Reply-To: <20230712075910.22480-1-thuth@redhat.com>
The sync_regs test currently does not have any output (unless one
of the TEST_ASSERT statement fails), so it's hard to say for a user
whether a certain new sub-test has been included in the binary or
not. Let's make this a little bit more user-friendly and include
some TAP output via the kselftest_harness.h interface.
To be able to use the interface, we have to break up the huge main()
function here in more fine grained parts - then we can use the
TEST_F() macro to define the individual tests. Since these are run
with a separate VM now, we have also to make sure to create the
expected state at the beginning of each test, so some parts grow
a little bit - which should be OK considering that the individual
tests are more self-contained now.
Suggested-by: David Matlack <dmatlack@google.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
---
.../selftests/kvm/x86_64/sync_regs_test.c | 113 +++++++++++++++---
1 file changed, 98 insertions(+), 15 deletions(-)
diff --git a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c
index 2da89fdc2471a..e1359a4a07fea 100644
--- a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c
+++ b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c
@@ -16,6 +16,7 @@
#include <string.h>
#include <sys/ioctl.h>
+#include "kselftest_harness.h"
#include "test_util.h"
#include "kvm_util.h"
#include "processor.h"
@@ -80,23 +81,24 @@ static void compare_vcpu_events(struct kvm_vcpu_events *left,
#define TEST_SYNC_FIELDS (KVM_SYNC_X86_REGS|KVM_SYNC_X86_SREGS|KVM_SYNC_X86_EVENTS)
#define INVALID_SYNC_FIELD 0x80000000
-int main(int argc, char *argv[])
-{
- struct kvm_vcpu *vcpu;
+FIXTURE(sync_regs_test) {
struct kvm_vm *vm;
- struct kvm_run *run;
- struct kvm_regs regs;
- struct kvm_sregs sregs;
- struct kvm_vcpu_events events;
- int rv, cap;
+ struct kvm_vcpu *vcpu;
+};
- cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
- TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS);
- TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD));
+FIXTURE_SETUP(sync_regs_test) {
+ self->vm = vm_create_with_one_vcpu(&self->vcpu, guest_code);
+}
- vm = vm_create_with_one_vcpu(&vcpu, guest_code);
+FIXTURE_TEARDOWN(sync_regs_test) {
+ kvm_vm_free(self->vm);
+}
- run = vcpu->run;
+TEST_F(sync_regs_test, read_invalid)
+{
+ struct kvm_vcpu *vcpu = self->vcpu;
+ struct kvm_run *run = vcpu->run;
+ int rv;
/* Request reading invalid register set from VCPU. */
run->kvm_valid_regs = INVALID_SYNC_FIELD;
@@ -112,6 +114,13 @@ int main(int argc, char *argv[])
"Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
rv);
run->kvm_valid_regs = 0;
+}
+
+TEST_F(sync_regs_test, set_invalid)
+{
+ struct kvm_vcpu *vcpu = self->vcpu;
+ struct kvm_run *run = vcpu->run;
+ int rv;
/* Request setting invalid register set into VCPU. */
run->kvm_dirty_regs = INVALID_SYNC_FIELD;
@@ -127,11 +136,22 @@ int main(int argc, char *argv[])
"Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
rv);
run->kvm_dirty_regs = 0;
+}
+
+TEST_F(sync_regs_test, req_and_verify_all_valid)
+{
+ struct kvm_vcpu *vcpu = self->vcpu;
+ struct kvm_run *run = vcpu->run;
+ struct kvm_vcpu_events events;
+ struct kvm_sregs sregs;
+ struct kvm_regs regs;
+ int rv;
/* Request and verify all valid register sets. */
/* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */
run->kvm_valid_regs = TEST_SYNC_FIELDS;
rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
vcpu_regs_get(vcpu, ®s);
@@ -142,6 +162,22 @@ int main(int argc, char *argv[])
vcpu_events_get(vcpu, &events);
compare_vcpu_events(&events, &run->s.regs.events);
+}
+
+TEST_F(sync_regs_test, set_and_verify_various)
+{
+ struct kvm_vcpu *vcpu = self->vcpu;
+ struct kvm_run *run = vcpu->run;
+ struct kvm_vcpu_events events;
+ struct kvm_sregs sregs;
+ struct kvm_regs regs;
+ int rv;
+
+ /* Run once to get register set */
+ run->kvm_valid_regs = TEST_SYNC_FIELDS;
+ rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
+ TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Set and verify various register values. */
run->s.regs.regs.rbx = 0xBAD1DEA;
@@ -151,6 +187,7 @@ int main(int argc, char *argv[])
run->kvm_valid_regs = TEST_SYNC_FIELDS;
run->kvm_dirty_regs = KVM_SYNC_X86_REGS | KVM_SYNC_X86_SREGS;
rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
TEST_ASSERT(run->s.regs.regs.rbx == 0xBAD1DEA + 1,
"rbx sync regs value incorrect 0x%llx.",
@@ -167,6 +204,13 @@ int main(int argc, char *argv[])
vcpu_events_get(vcpu, &events);
compare_vcpu_events(&events, &run->s.regs.events);
+}
+
+TEST_F(sync_regs_test, clear_kvm_dirty_regs_bits)
+{
+ struct kvm_vcpu *vcpu = self->vcpu;
+ struct kvm_run *run = vcpu->run;
+ int rv;
/* Clear kvm_dirty_regs bits, verify new s.regs values are
* overwritten with existing guest values.
@@ -175,10 +219,25 @@ int main(int argc, char *argv[])
run->kvm_dirty_regs = 0;
run->s.regs.regs.rbx = 0xDEADBEEF;
rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
TEST_ASSERT(run->s.regs.regs.rbx != 0xDEADBEEF,
"rbx sync regs value incorrect 0x%llx.",
run->s.regs.regs.rbx);
+}
+
+TEST_F(sync_regs_test, clear_kvm_valid_and_dirty_regs)
+{
+ struct kvm_vcpu *vcpu = self->vcpu;
+ struct kvm_run *run = vcpu->run;
+ struct kvm_regs regs;
+ int rv;
+
+ /* Run once to get register set */
+ run->kvm_valid_regs = TEST_SYNC_FIELDS;
+ rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
+ TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Clear kvm_valid_regs bits and kvm_dirty_bits.
* Verify s.regs values are not overwritten with existing guest values
@@ -187,9 +246,11 @@ int main(int argc, char *argv[])
run->kvm_valid_regs = 0;
run->kvm_dirty_regs = 0;
run->s.regs.regs.rbx = 0xAAAA;
+ vcpu_regs_get(vcpu, ®s);
regs.rbx = 0xBAC0;
vcpu_regs_set(vcpu, ®s);
rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
TEST_ASSERT(run->s.regs.regs.rbx == 0xAAAA,
"rbx sync regs value incorrect 0x%llx.",
@@ -198,6 +259,20 @@ int main(int argc, char *argv[])
TEST_ASSERT(regs.rbx == 0xBAC0 + 1,
"rbx guest value incorrect 0x%llx.",
regs.rbx);
+}
+
+TEST_F(sync_regs_test, clear_kvm_valid_regs_bits)
+{
+ struct kvm_vcpu *vcpu = self->vcpu;
+ struct kvm_run *run = vcpu->run;
+ struct kvm_regs regs;
+ int rv;
+
+ /* Run once to get register set */
+ run->kvm_valid_regs = TEST_SYNC_FIELDS;
+ rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
+ TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
/* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten
* with existing guest values but that guest values are overwritten
@@ -207,6 +282,7 @@ int main(int argc, char *argv[])
run->kvm_dirty_regs = TEST_SYNC_FIELDS;
run->s.regs.regs.rbx = 0xBBBB;
rv = _vcpu_run(vcpu);
+ TEST_ASSERT(rv == 0, "vcpu_run failed: %d\n", rv);
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
TEST_ASSERT(run->s.regs.regs.rbx == 0xBBBB,
"rbx sync regs value incorrect 0x%llx.",
@@ -215,8 +291,15 @@ int main(int argc, char *argv[])
TEST_ASSERT(regs.rbx == 0xBBBB + 1,
"rbx guest value incorrect 0x%llx.",
regs.rbx);
+}
+
+int main(int argc, char *argv[])
+{
+ int cap;
- kvm_vm_free(vm);
+ cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
+ TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS);
+ TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD));
- return 0;
+ return test_harness_run(argc, argv);
}
--
2.39.3
next prev parent reply other threads:[~2023-07-12 8:00 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-12 7:59 [PATCH 0/4] Use TAP in some more x86 KVM selftests Thomas Huth
2023-07-12 7:59 ` [PATCH 1/4] KVM: selftests: Rename the ASSERT_EQ macro Thomas Huth
2023-07-18 12:26 ` Philippe Mathieu-Daudé
2023-07-12 7:59 ` Thomas Huth [this message]
2023-08-02 19:55 ` [PATCH 2/4] KVM: selftests: x86: Use TAP interface in the sync_regs test Sean Christopherson
2023-08-02 21:31 ` Sean Christopherson
2023-08-03 5:23 ` Thomas Huth
2023-08-03 5:17 ` Thomas Huth
2023-07-12 7:59 ` [PATCH 3/4] KVM: selftests: x86: Use TAP interface in the fix_hypercall test Thomas Huth
2023-07-12 7:59 ` [PATCH 4/4] KVM: selftests: x86: Use TAP interface in the userspace_msr_exit test Thomas Huth
2023-07-18 12:26 ` Philippe Mathieu-Daudé
2023-08-02 22:01 ` [PATCH 0/4] Use TAP in some more x86 KVM selftests Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230712075910.22480-3-thuth@redhat.com \
--to=thuth@redhat.com \
--cc=dmatlack@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.