Commit 6ebfef83 authored by Sean Christopherson's avatar Sean Christopherson Committed by Paolo Bonzini

KVM: selftest: Add proper helpers for x86-specific save/restore ioctls

Add helpers for the various one-off helpers used by x86's vCPU state
save/restore helpers, and convert the other open coded ioctl()s to use
existing helpers.
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 877bd399
...@@ -432,6 +432,60 @@ const struct kvm_msr_list *kvm_get_feature_msr_index_list(void); ...@@ -432,6 +432,60 @@ const struct kvm_msr_list *kvm_get_feature_msr_index_list(void);
bool kvm_msr_is_in_save_restore_list(uint32_t msr_index); bool kvm_msr_is_in_save_restore_list(uint32_t msr_index);
uint64_t kvm_get_feature_msr(uint64_t msr_index); uint64_t kvm_get_feature_msr(uint64_t msr_index);
static inline void vcpu_msrs_get(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_msrs *msrs)
{
int r = __vcpu_ioctl(vm, vcpuid, KVM_GET_MSRS, msrs);
TEST_ASSERT(r == msrs->nmsrs,
"KVM_GET_MSRS failed, r: %i (failed on MSR %x)",
r, r < 0 || r >= msrs->nmsrs ? -1 : msrs->entries[r].index);
}
static inline void vcpu_msrs_set(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_msrs *msrs)
{
int r = __vcpu_ioctl(vm, vcpuid, KVM_SET_MSRS, msrs);
TEST_ASSERT(r == msrs->nmsrs,
"KVM_GET_MSRS failed, r: %i (failed on MSR %x)",
r, r < 0 || r >= msrs->nmsrs ? -1 : msrs->entries[r].index);
}
static inline void vcpu_debugregs_get(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_debugregs *debugregs)
{
vcpu_ioctl(vm, vcpuid, KVM_GET_DEBUGREGS, debugregs);
}
static inline void vcpu_debugregs_set(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_debugregs *debugregs)
{
vcpu_ioctl(vm, vcpuid, KVM_SET_DEBUGREGS, debugregs);
}
static inline void vcpu_xsave_get(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_xsave *xsave)
{
vcpu_ioctl(vm, vcpuid, KVM_GET_XSAVE, xsave);
}
static inline void vcpu_xsave2_get(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_xsave *xsave)
{
vcpu_ioctl(vm, vcpuid, KVM_GET_XSAVE2, xsave);
}
static inline void vcpu_xsave_set(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_xsave *xsave)
{
vcpu_ioctl(vm, vcpuid, KVM_SET_XSAVE, xsave);
}
static inline void vcpu_xcrs_get(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_xcrs *xcrs)
{
vcpu_ioctl(vm, vcpuid, KVM_GET_XCRS, xcrs);
}
static inline void vcpu_xcrs_set(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_xcrs *xcrs)
{
vcpu_ioctl(vm, vcpuid, KVM_SET_XCRS, xcrs);
}
struct kvm_cpuid2 *kvm_get_supported_cpuid(void); struct kvm_cpuid2 *kvm_get_supported_cpuid(void);
struct kvm_cpuid2 *vcpu_get_cpuid(struct kvm_vm *vm, uint32_t vcpuid); struct kvm_cpuid2 *vcpu_get_cpuid(struct kvm_vm *vm, uint32_t vcpuid);
......
...@@ -814,13 +814,11 @@ uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index) ...@@ -814,13 +814,11 @@ uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
struct kvm_msrs header; struct kvm_msrs header;
struct kvm_msr_entry entry; struct kvm_msr_entry entry;
} buffer = {}; } buffer = {};
int r;
buffer.header.nmsrs = 1; buffer.header.nmsrs = 1;
buffer.entry.index = msr_index; buffer.entry.index = msr_index;
r = __vcpu_ioctl(vm, vcpuid, KVM_GET_MSRS, &buffer.header); vcpu_msrs_get(vm, vcpuid, &buffer.header);
TEST_ASSERT(r == 1, KVM_IOCTL_ERROR(KVM_GET_MSRS, r));
return buffer.entry.data; return buffer.entry.data;
} }
...@@ -957,28 +955,26 @@ bool kvm_msr_is_in_save_restore_list(uint32_t msr_index) ...@@ -957,28 +955,26 @@ bool kvm_msr_is_in_save_restore_list(uint32_t msr_index)
return false; return false;
} }
static int vcpu_save_xsave_state(struct kvm_vm *vm, struct vcpu *vcpu, static void vcpu_save_xsave_state(struct kvm_vm *vm, uint32_t vcpuid,
struct kvm_x86_state *state) struct kvm_x86_state *state)
{ {
int size; int size = vm_check_cap(vm, KVM_CAP_XSAVE2);
size = vm_check_cap(vm, KVM_CAP_XSAVE2);
if (!size)
size = sizeof(struct kvm_xsave);
state->xsave = malloc(size); if (size) {
if (size == sizeof(struct kvm_xsave)) state->xsave = malloc(size);
return ioctl(vcpu->fd, KVM_GET_XSAVE, state->xsave); vcpu_xsave2_get(vm, vcpuid, state->xsave);
else } else {
return ioctl(vcpu->fd, KVM_GET_XSAVE2, state->xsave); state->xsave = malloc(sizeof(struct kvm_xsave));
vcpu_xsave_get(vm, vcpuid, state->xsave);
}
} }
struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid) struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
{ {
const struct kvm_msr_list *msr_list = kvm_get_msr_index_list(); const struct kvm_msr_list *msr_list = kvm_get_msr_index_list();
struct vcpu *vcpu = vcpu_get(vm, vcpuid);
struct kvm_x86_state *state; struct kvm_x86_state *state;
int r, i; int i;
static int nested_size = -1; static int nested_size = -1;
if (nested_size == -1) { if (nested_size == -1) {
...@@ -997,102 +993,54 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid) ...@@ -997,102 +993,54 @@ struct kvm_x86_state *vcpu_save_state(struct kvm_vm *vm, uint32_t vcpuid)
vcpu_run_complete_io(vm, vcpuid); vcpu_run_complete_io(vm, vcpuid);
state = malloc(sizeof(*state) + msr_list->nmsrs * sizeof(state->msrs.entries[0])); state = malloc(sizeof(*state) + msr_list->nmsrs * sizeof(state->msrs.entries[0]));
r = ioctl(vcpu->fd, KVM_GET_VCPU_EVENTS, &state->events);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_VCPU_EVENTS, r: %i",
r);
r = ioctl(vcpu->fd, KVM_GET_MP_STATE, &state->mp_state);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_MP_STATE, r: %i",
r);
r = ioctl(vcpu->fd, KVM_GET_REGS, &state->regs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_REGS, r: %i",
r);
r = vcpu_save_xsave_state(vm, vcpu, state);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XSAVE, r: %i",
r);
if (kvm_check_cap(KVM_CAP_XCRS)) {
r = ioctl(vcpu->fd, KVM_GET_XCRS, &state->xcrs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_XCRS, r: %i",
r);
}
r = ioctl(vcpu->fd, KVM_GET_SREGS, &state->sregs); vcpu_events_get(vm, vcpuid, &state->events);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_SREGS, r: %i", vcpu_mp_state_get(vm, vcpuid, &state->mp_state);
r); vcpu_regs_get(vm, vcpuid, &state->regs);
vcpu_save_xsave_state(vm, vcpuid, state);
if (kvm_check_cap(KVM_CAP_XCRS))
vcpu_xcrs_get(vm, vcpuid, &state->xcrs);
vcpu_sregs_get(vm, vcpuid, &state->sregs);
if (nested_size) { if (nested_size) {
state->nested.size = sizeof(state->nested_); state->nested.size = sizeof(state->nested_);
r = ioctl(vcpu->fd, KVM_GET_NESTED_STATE, &state->nested);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_NESTED_STATE, r: %i", vcpu_nested_state_get(vm, vcpuid, &state->nested);
r);
TEST_ASSERT(state->nested.size <= nested_size, TEST_ASSERT(state->nested.size <= nested_size,
"Nested state size too big, %i (KVM_CHECK_CAP gave %i)", "Nested state size too big, %i (KVM_CHECK_CAP gave %i)",
state->nested.size, nested_size); state->nested.size, nested_size);
} else } else {
state->nested.size = 0; state->nested.size = 0;
}
state->msrs.nmsrs = msr_list->nmsrs; state->msrs.nmsrs = msr_list->nmsrs;
for (i = 0; i < msr_list->nmsrs; i++) for (i = 0; i < msr_list->nmsrs; i++)
state->msrs.entries[i].index = msr_list->indices[i]; state->msrs.entries[i].index = msr_list->indices[i];
r = ioctl(vcpu->fd, KVM_GET_MSRS, &state->msrs); vcpu_msrs_get(vm, vcpuid, &state->msrs);
TEST_ASSERT(r == msr_list->nmsrs, "Unexpected result from KVM_GET_MSRS, r: %i (failed MSR was 0x%x)",
r, r == msr_list->nmsrs ? -1 : msr_list->indices[r]);
r = ioctl(vcpu->fd, KVM_GET_DEBUGREGS, &state->debugregs); vcpu_debugregs_get(vm, vcpuid, &state->debugregs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_GET_DEBUGREGS, r: %i",
r);
return state; return state;
} }
void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state) void vcpu_load_state(struct kvm_vm *vm, uint32_t vcpuid, struct kvm_x86_state *state)
{ {
struct vcpu *vcpu = vcpu_get(vm, vcpuid); vcpu_sregs_set(vm, vcpuid, &state->sregs);
int r; vcpu_msrs_set(vm, vcpuid, &state->msrs);
r = ioctl(vcpu->fd, KVM_SET_SREGS, &state->sregs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_SREGS, r: %i",
r);
r = ioctl(vcpu->fd, KVM_SET_MSRS, &state->msrs);
TEST_ASSERT(r == state->msrs.nmsrs,
"Unexpected result from KVM_SET_MSRS, r: %i (failed at %x)",
r, r == state->msrs.nmsrs ? -1 : state->msrs.entries[r].index);
if (kvm_check_cap(KVM_CAP_XCRS)) {
r = ioctl(vcpu->fd, KVM_SET_XCRS, &state->xcrs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XCRS, r: %i",
r);
}
r = ioctl(vcpu->fd, KVM_SET_XSAVE, state->xsave); if (kvm_check_cap(KVM_CAP_XCRS))
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_XSAVE, r: %i", vcpu_xcrs_set(vm, vcpuid, &state->xcrs);
r);
r = ioctl(vcpu->fd, KVM_SET_VCPU_EVENTS, &state->events); vcpu_xsave_set(vm, vcpuid, state->xsave);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_VCPU_EVENTS, r: %i", vcpu_events_set(vm, vcpuid, &state->events);
r); vcpu_mp_state_set(vm, vcpuid, &state->mp_state);
vcpu_debugregs_set(vm, vcpuid, &state->debugregs);
vcpu_regs_set(vm, vcpuid, &state->regs);
r = ioctl(vcpu->fd, KVM_SET_MP_STATE, &state->mp_state); if (state->nested.size)
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_MP_STATE, r: %i", vcpu_nested_state_set(vm, vcpuid, &state->nested);
r);
r = ioctl(vcpu->fd, KVM_SET_DEBUGREGS, &state->debugregs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_DEBUGREGS, r: %i",
r);
r = ioctl(vcpu->fd, KVM_SET_REGS, &state->regs);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_REGS, r: %i",
r);
if (state->nested.size) {
r = ioctl(vcpu->fd, KVM_SET_NESTED_STATE, &state->nested);
TEST_ASSERT(r == 0, "Unexpected result from KVM_SET_NESTED_STATE, r: %i",
r);
}
} }
void kvm_x86_state_cleanup(struct kvm_x86_state *state) void kvm_x86_state_cleanup(struct kvm_x86_state *state)
......
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