Skip to content

Commit ba97ed0

Browse files
huthsean-jc
authored andcommitted
KVM: selftests: x86: Use TAP interface in the sync_regs test
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 / kvm_test_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 new KVM_ONE_VCPU_TEST() 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 <[email protected]> Suggested-by: Sean Christopherson <[email protected]> Signed-off-by: Thomas Huth <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Sean Christopherson <[email protected]>
1 parent 55f2cf8 commit ba97ed0

File tree

1 file changed

+84
-26
lines changed

1 file changed

+84
-26
lines changed

tools/testing/selftests/kvm/x86_64/sync_regs_test.c

Lines changed: 84 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <sys/ioctl.h>
1818
#include <pthread.h>
1919

20+
#include "kvm_test_harness.h"
2021
#include "test_util.h"
2122
#include "kvm_util.h"
2223
#include "processor.h"
@@ -41,6 +42,8 @@ void guest_code(void)
4142
: "rax", "rbx");
4243
}
4344

45+
KVM_ONE_VCPU_TEST_SUITE(sync_regs_test);
46+
4447
static void compare_regs(struct kvm_regs *left, struct kvm_regs *right)
4548
{
4649
#define REG_COMPARE(reg) \
@@ -152,18 +155,15 @@ static noinline void *race_sregs_cr4(void *arg)
152155
return NULL;
153156
}
154157

155-
static void race_sync_regs(void *racer)
158+
static void race_sync_regs(struct kvm_vcpu *vcpu, void *racer)
156159
{
157160
const time_t TIMEOUT = 2; /* seconds, roughly */
158161
struct kvm_x86_state *state;
159162
struct kvm_translation tr;
160-
struct kvm_vcpu *vcpu;
161163
struct kvm_run *run;
162-
struct kvm_vm *vm;
163164
pthread_t thread;
164165
time_t t;
165166

166-
vm = vm_create_with_one_vcpu(&vcpu, guest_code);
167167
run = vcpu->run;
168168

169169
run->kvm_valid_regs = KVM_SYNC_X86_SREGS;
@@ -205,26 +205,12 @@ static void race_sync_regs(void *racer)
205205
TEST_ASSERT_EQ(pthread_join(thread, NULL), 0);
206206

207207
kvm_x86_state_cleanup(state);
208-
kvm_vm_free(vm);
209208
}
210209

211-
int main(int argc, char *argv[])
210+
KVM_ONE_VCPU_TEST(sync_regs_test, read_invalid, guest_code)
212211
{
213-
struct kvm_vcpu *vcpu;
214-
struct kvm_vm *vm;
215-
struct kvm_run *run;
216-
struct kvm_regs regs;
217-
struct kvm_sregs sregs;
218-
struct kvm_vcpu_events events;
219-
int rv, cap;
220-
221-
cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
222-
TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS);
223-
TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD));
224-
225-
vm = vm_create_with_one_vcpu(&vcpu, guest_code);
226-
227-
run = vcpu->run;
212+
struct kvm_run *run = vcpu->run;
213+
int rv;
228214

229215
/* Request reading invalid register set from VCPU. */
230216
run->kvm_valid_regs = INVALID_SYNC_FIELD;
@@ -240,6 +226,12 @@ int main(int argc, char *argv[])
240226
"Invalid kvm_valid_regs did not cause expected KVM_RUN error: %d\n",
241227
rv);
242228
run->kvm_valid_regs = 0;
229+
}
230+
231+
KVM_ONE_VCPU_TEST(sync_regs_test, set_invalid, guest_code)
232+
{
233+
struct kvm_run *run = vcpu->run;
234+
int rv;
243235

244236
/* Request setting invalid register set into VCPU. */
245237
run->kvm_dirty_regs = INVALID_SYNC_FIELD;
@@ -255,6 +247,14 @@ int main(int argc, char *argv[])
255247
"Invalid kvm_dirty_regs did not cause expected KVM_RUN error: %d\n",
256248
rv);
257249
run->kvm_dirty_regs = 0;
250+
}
251+
252+
KVM_ONE_VCPU_TEST(sync_regs_test, req_and_verify_all_valid, guest_code)
253+
{
254+
struct kvm_run *run = vcpu->run;
255+
struct kvm_vcpu_events events;
256+
struct kvm_sregs sregs;
257+
struct kvm_regs regs;
258258

259259
/* Request and verify all valid register sets. */
260260
/* TODO: BUILD TIME CHECK: TEST_ASSERT(KVM_SYNC_X86_NUM_FIELDS != 3); */
@@ -270,6 +270,19 @@ int main(int argc, char *argv[])
270270

271271
vcpu_events_get(vcpu, &events);
272272
compare_vcpu_events(&events, &run->s.regs.events);
273+
}
274+
275+
KVM_ONE_VCPU_TEST(sync_regs_test, set_and_verify_various, guest_code)
276+
{
277+
struct kvm_run *run = vcpu->run;
278+
struct kvm_vcpu_events events;
279+
struct kvm_sregs sregs;
280+
struct kvm_regs regs;
281+
282+
/* Run once to get register set */
283+
run->kvm_valid_regs = TEST_SYNC_FIELDS;
284+
vcpu_run(vcpu);
285+
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
273286

274287
/* Set and verify various register values. */
275288
run->s.regs.regs.rbx = 0xBAD1DEA;
@@ -295,6 +308,11 @@ int main(int argc, char *argv[])
295308

296309
vcpu_events_get(vcpu, &events);
297310
compare_vcpu_events(&events, &run->s.regs.events);
311+
}
312+
313+
KVM_ONE_VCPU_TEST(sync_regs_test, clear_kvm_dirty_regs_bits, guest_code)
314+
{
315+
struct kvm_run *run = vcpu->run;
298316

299317
/* Clear kvm_dirty_regs bits, verify new s.regs values are
300318
* overwritten with existing guest values.
@@ -307,6 +325,17 @@ int main(int argc, char *argv[])
307325
TEST_ASSERT(run->s.regs.regs.rbx != 0xDEADBEEF,
308326
"rbx sync regs value incorrect 0x%llx.",
309327
run->s.regs.regs.rbx);
328+
}
329+
330+
KVM_ONE_VCPU_TEST(sync_regs_test, clear_kvm_valid_and_dirty_regs, guest_code)
331+
{
332+
struct kvm_run *run = vcpu->run;
333+
struct kvm_regs regs;
334+
335+
/* Run once to get register set */
336+
run->kvm_valid_regs = TEST_SYNC_FIELDS;
337+
vcpu_run(vcpu);
338+
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
310339

311340
/* Clear kvm_valid_regs bits and kvm_dirty_bits.
312341
* Verify s.regs values are not overwritten with existing guest values
@@ -327,6 +356,17 @@ int main(int argc, char *argv[])
327356
TEST_ASSERT(regs.rbx == 0xBAC0 + 1,
328357
"rbx guest value incorrect 0x%llx.",
329358
regs.rbx);
359+
}
360+
361+
KVM_ONE_VCPU_TEST(sync_regs_test, clear_kvm_valid_regs_bits, guest_code)
362+
{
363+
struct kvm_run *run = vcpu->run;
364+
struct kvm_regs regs;
365+
366+
/* Run once to get register set */
367+
run->kvm_valid_regs = TEST_SYNC_FIELDS;
368+
vcpu_run(vcpu);
369+
TEST_ASSERT_KVM_EXIT_REASON(vcpu, KVM_EXIT_IO);
330370

331371
/* Clear kvm_valid_regs bits. Verify s.regs values are not overwritten
332372
* with existing guest values but that guest values are overwritten
@@ -344,12 +384,30 @@ int main(int argc, char *argv[])
344384
TEST_ASSERT(regs.rbx == 0xBBBB + 1,
345385
"rbx guest value incorrect 0x%llx.",
346386
regs.rbx);
387+
}
388+
389+
KVM_ONE_VCPU_TEST(sync_regs_test, race_cr4, guest_code)
390+
{
391+
race_sync_regs(vcpu, race_sregs_cr4);
392+
}
393+
394+
KVM_ONE_VCPU_TEST(sync_regs_test, race_exc, guest_code)
395+
{
396+
race_sync_regs(vcpu, race_events_exc);
397+
}
347398

348-
kvm_vm_free(vm);
399+
KVM_ONE_VCPU_TEST(sync_regs_test, race_inj_pen, guest_code)
400+
{
401+
race_sync_regs(vcpu, race_events_inj_pen);
402+
}
403+
404+
int main(int argc, char *argv[])
405+
{
406+
int cap;
349407

350-
race_sync_regs(race_sregs_cr4);
351-
race_sync_regs(race_events_exc);
352-
race_sync_regs(race_events_inj_pen);
408+
cap = kvm_check_cap(KVM_CAP_SYNC_REGS);
409+
TEST_REQUIRE((cap & TEST_SYNC_FIELDS) == TEST_SYNC_FIELDS);
410+
TEST_REQUIRE(!(cap & INVALID_SYNC_FIELD));
353411

354-
return 0;
412+
return test_harness_run(argc, argv);
355413
}

0 commit comments

Comments
 (0)