selftests: kvm/evmcs_test: complete I/O before migrating guest state
Starting state migration after an IO exit without first completing IO
may result in test failures. We already have two tests that need this
(this patch in fact fixes evmcs_test, similar to what was fixed for
state_test in commit 0f73bbc851
, "KVM: selftests: complete IO before
migrating guest state", 2019-03-13) and a third is coming. So, move the
code to vcpu_save_state, and while at it do not access register state
until after I/O is complete.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
b68f3cc7d9
commit
c68c21ca92
|
@ -91,6 +91,11 @@ static void vm_open(struct kvm_vm *vm, int perm, unsigned long type)
|
|||
if (vm->kvm_fd < 0)
|
||||
exit(KSFT_SKIP);
|
||||
|
||||
if (!kvm_check_cap(KVM_CAP_IMMEDIATE_EXIT)) {
|
||||
fprintf(stderr, "immediate_exit not available, skipping test\n");
|
||||
exit(KSFT_SKIP);
|
||||
}
|
||||
|
||||
vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, type);
|
||||
TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, "
|
||||
"rc: %i errno: %i", vm->fd, errno);
|
||||
|
|
|
@ -1030,6 +1030,14 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
|
|||
nested_size, sizeof(state->nested_));
|
||||
}
|
||||
|
||||
/*
|
||||
* When KVM exits to userspace with KVM_EXIT_IO, KVM guarantees
|
||||
* guest state is consistent only after userspace re-enters the
|
||||
* kernel with KVM_RUN. Complete IO prior to migrating state
|
||||
* to a new VM.
|
||||
*/
|
||||
vcpu_run_complete_io(vm, vcpuid);
|
||||
|
||||
nmsrs = kvm_get_num_msrs(vm);
|
||||
list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
|
||||
list->nmsrs = nmsrs;
|
||||
|
|
|
@ -123,8 +123,6 @@ int main(int argc, char *argv[])
|
|||
stage, run->exit_reason,
|
||||
exit_reason_str(run->exit_reason));
|
||||
|
||||
memset(®s1, 0, sizeof(regs1));
|
||||
vcpu_regs_get(vm, VCPU_ID, ®s1);
|
||||
switch (get_ucall(vm, VCPU_ID, &uc)) {
|
||||
case UCALL_ABORT:
|
||||
TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0],
|
||||
|
@ -144,6 +142,9 @@ int main(int argc, char *argv[])
|
|||
stage, (ulong)uc.args[1]);
|
||||
|
||||
state = vcpu_save_state(vm, VCPU_ID);
|
||||
memset(®s1, 0, sizeof(regs1));
|
||||
vcpu_regs_get(vm, VCPU_ID, ®s1);
|
||||
|
||||
kvm_vm_release(vm);
|
||||
|
||||
/* Restore state in a new VM. */
|
||||
|
|
|
@ -134,11 +134,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1);
|
||||
|
||||
if (!kvm_check_cap(KVM_CAP_IMMEDIATE_EXIT)) {
|
||||
fprintf(stderr, "immediate_exit not available, skipping test\n");
|
||||
exit(KSFT_SKIP);
|
||||
}
|
||||
|
||||
/* Create VM */
|
||||
vm = vm_create_default(VCPU_ID, 0, guest_code);
|
||||
vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
|
||||
|
@ -179,18 +174,10 @@ int main(int argc, char *argv[])
|
|||
uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx",
|
||||
stage, (ulong)uc.args[1]);
|
||||
|
||||
/*
|
||||
* When KVM exits to userspace with KVM_EXIT_IO, KVM guarantees
|
||||
* guest state is consistent only after userspace re-enters the
|
||||
* kernel with KVM_RUN. Complete IO prior to migrating state
|
||||
* to a new VM.
|
||||
*/
|
||||
vcpu_run_complete_io(vm, VCPU_ID);
|
||||
|
||||
state = vcpu_save_state(vm, VCPU_ID);
|
||||
memset(®s1, 0, sizeof(regs1));
|
||||
vcpu_regs_get(vm, VCPU_ID, ®s1);
|
||||
|
||||
state = vcpu_save_state(vm, VCPU_ID);
|
||||
kvm_vm_release(vm);
|
||||
|
||||
/* Restore state in a new VM. */
|
||||
|
|
Loading…
Reference in New Issue