diff options
Diffstat (limited to 'tools/testing/selftests/kvm')
-rw-r--r-- | tools/testing/selftests/kvm/x86_64/sync_regs_test.c | 14 |
1 files changed, 13 insertions, 1 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 93fac74ca0a7..21e99dae2ff2 100644 --- a/tools/testing/selftests/kvm/x86_64/sync_regs_test.c +++ b/tools/testing/selftests/kvm/x86_64/sync_regs_test.c @@ -152,6 +152,7 @@ static noinline void *race_sregs_cr4(void *arg) static void race_sync_regs(void *racer) { const time_t TIMEOUT = 2; /* seconds, roughly */ + struct kvm_x86_state *state; struct kvm_translation tr; struct kvm_vcpu *vcpu; struct kvm_run *run; @@ -166,6 +167,9 @@ static void race_sync_regs(void *racer) vcpu_run(vcpu); run->kvm_valid_regs = 0; + /* Save state *before* spawning the thread that mucks with vCPU state. */ + state = vcpu_save_state(vcpu); + /* * Selftests run 64-bit guests by default, both EFER.LME and CR4.PAE * should already be set in guest state. @@ -179,7 +183,14 @@ static void race_sync_regs(void *racer) TEST_ASSERT_EQ(pthread_create(&thread, NULL, racer, (void *)run), 0); for (t = time(NULL) + TIMEOUT; time(NULL) < t;) { - __vcpu_run(vcpu); + /* + * Reload known good state if the vCPU triple faults, e.g. due + * to the unhandled #GPs being injected. VMX preserves state + * on shutdown, but SVM synthesizes an INIT as the VMCB state + * is architecturally undefined on triple fault. + */ + if (!__vcpu_run(vcpu) && run->exit_reason == KVM_EXIT_SHUTDOWN) + vcpu_load_state(vcpu, state); if (racer == race_sregs_cr4) { tr = (struct kvm_translation) { .linear_address = 0 }; @@ -190,6 +201,7 @@ static void race_sync_regs(void *racer) TEST_ASSERT_EQ(pthread_cancel(thread), 0); TEST_ASSERT_EQ(pthread_join(thread, NULL), 0); + kvm_x86_state_cleanup(state); kvm_vm_free(vm); } |