Commit c68c21ca authored by Paolo Bonzini's avatar Paolo Bonzini

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 0f73bbc8, "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: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent b68f3cc7
...@@ -91,6 +91,11 @@ static void vm_open(struct kvm_vm *vm, int perm, unsigned long type) ...@@ -91,6 +91,11 @@ static void vm_open(struct kvm_vm *vm, int perm, unsigned long type)
if (vm->kvm_fd < 0) if (vm->kvm_fd < 0)
exit(KSFT_SKIP); 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); vm->fd = ioctl(vm->kvm_fd, KVM_CREATE_VM, type);
TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, " TEST_ASSERT(vm->fd >= 0, "KVM_CREATE_VM ioctl failed, "
"rc: %i errno: %i", vm->fd, errno); "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) ...@@ -1030,6 +1030,14 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
nested_size, sizeof(state->nested_)); 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); nmsrs = kvm_get_num_msrs(vm);
list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0])); list = malloc(sizeof(*list) + nmsrs * sizeof(list->indices[0]));
list->nmsrs = nmsrs; list->nmsrs = nmsrs;
......
...@@ -123,8 +123,6 @@ int main(int argc, char *argv[]) ...@@ -123,8 +123,6 @@ int main(int argc, char *argv[])
stage, run->exit_reason, stage, run->exit_reason,
exit_reason_str(run->exit_reason)); exit_reason_str(run->exit_reason));
memset(&regs1, 0, sizeof(regs1));
vcpu_regs_get(vm, VCPU_ID, &regs1);
switch (get_ucall(vm, VCPU_ID, &uc)) { switch (get_ucall(vm, VCPU_ID, &uc)) {
case UCALL_ABORT: case UCALL_ABORT:
TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0], TEST_ASSERT(false, "%s at %s:%d", (const char *)uc.args[0],
...@@ -144,6 +142,9 @@ int main(int argc, char *argv[]) ...@@ -144,6 +142,9 @@ int main(int argc, char *argv[])
stage, (ulong)uc.args[1]); stage, (ulong)uc.args[1]);
state = vcpu_save_state(vm, VCPU_ID); state = vcpu_save_state(vm, VCPU_ID);
memset(&regs1, 0, sizeof(regs1));
vcpu_regs_get(vm, VCPU_ID, &regs1);
kvm_vm_release(vm); kvm_vm_release(vm);
/* Restore state in a new VM. */ /* Restore state in a new VM. */
......
...@@ -134,11 +134,6 @@ int main(int argc, char *argv[]) ...@@ -134,11 +134,6 @@ int main(int argc, char *argv[])
struct kvm_cpuid_entry2 *entry = kvm_get_supported_cpuid_entry(1); 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 */ /* Create VM */
vm = vm_create_default(VCPU_ID, 0, guest_code); vm = vm_create_default(VCPU_ID, 0, guest_code);
vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid()); vcpu_set_cpuid(vm, VCPU_ID, kvm_get_supported_cpuid());
...@@ -179,18 +174,10 @@ int main(int argc, char *argv[]) ...@@ -179,18 +174,10 @@ int main(int argc, char *argv[])
uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx", uc.args[1] == stage, "Unexpected register values vmexit #%lx, got %lx",
stage, (ulong)uc.args[1]); stage, (ulong)uc.args[1]);
/* state = vcpu_save_state(vm, VCPU_ID);
* 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);
memset(&regs1, 0, sizeof(regs1)); memset(&regs1, 0, sizeof(regs1));
vcpu_regs_get(vm, VCPU_ID, &regs1); vcpu_regs_get(vm, VCPU_ID, &regs1);
state = vcpu_save_state(vm, VCPU_ID);
kvm_vm_release(vm); kvm_vm_release(vm);
/* Restore state in a new VM. */ /* Restore state in a new VM. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment