Skip to content

Commit 5002b11

Browse files
committed
KVM: selftests: Reload "good" vCPU state if vCPU hits shutdown
Reload known good vCPU state if the vCPU triple faults in any of the race_sync_regs() subtests, e.g. if KVM successfully injects an exception (the vCPU isn't configured to handle exceptions). On Intel, the VMCS is preserved even after shutdown, but AMD's APM states that the VMCB is undefined after a shutdown and so KVM synthesizes an INIT to sanitize vCPU/VMCB state, e.g. to guard against running with a garbage VMCB. The synthetic INIT results in the vCPU never exiting to userspace, as it gets put into Real Mode at the reset vector, which is full of zeros (as is GPA 0 and beyond), and so executes ADD for a very, very long time. Fixes: 60c4063 ("KVM: selftests: Extend x86's sync_regs_test to check for event vector races") Cc: Michal Luczaj <mhal@rbox.co> Link: https://lore.kernel.org/r/20230817233430.1416463-2-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 740d087 commit 5002b11

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ static noinline void *race_sregs_cr4(void *arg)
152152
static void race_sync_regs(void *racer)
153153
{
154154
const time_t TIMEOUT = 2; /* seconds, roughly */
155+
struct kvm_x86_state *state;
155156
struct kvm_translation tr;
156157
struct kvm_vcpu *vcpu;
157158
struct kvm_run *run;
@@ -166,6 +167,9 @@ static void race_sync_regs(void *racer)
166167
vcpu_run(vcpu);
167168
run->kvm_valid_regs = 0;
168169

170+
/* Save state *before* spawning the thread that mucks with vCPU state. */
171+
state = vcpu_save_state(vcpu);
172+
169173
/*
170174
* Selftests run 64-bit guests by default, both EFER.LME and CR4.PAE
171175
* should already be set in guest state.
@@ -179,7 +183,14 @@ static void race_sync_regs(void *racer)
179183
TEST_ASSERT_EQ(pthread_create(&thread, NULL, racer, (void *)run), 0);
180184

181185
for (t = time(NULL) + TIMEOUT; time(NULL) < t;) {
182-
__vcpu_run(vcpu);
186+
/*
187+
* Reload known good state if the vCPU triple faults, e.g. due
188+
* to the unhandled #GPs being injected. VMX preserves state
189+
* on shutdown, but SVM synthesizes an INIT as the VMCB state
190+
* is architecturally undefined on triple fault.
191+
*/
192+
if (!__vcpu_run(vcpu) && run->exit_reason == KVM_EXIT_SHUTDOWN)
193+
vcpu_load_state(vcpu, state);
183194

184195
if (racer == race_sregs_cr4) {
185196
tr = (struct kvm_translation) { .linear_address = 0 };
@@ -190,6 +201,7 @@ static void race_sync_regs(void *racer)
190201
TEST_ASSERT_EQ(pthread_cancel(thread), 0);
191202
TEST_ASSERT_EQ(pthread_join(thread, NULL), 0);
192203

204+
kvm_x86_state_cleanup(state);
193205
kvm_vm_free(vm);
194206
}
195207

0 commit comments

Comments
 (0)