Since there is an ioctl that tells us which msrs are available, use it. This saves us from the need of functions like has_star(), lm_capable(), etc.
Signed-off-by: Glauber Costa <glom...@redhat.com> CC: Marcelo Tosatti <mtosa...@redhat.com> CC: Avi Kivity <a...@redhat.com> --- target-i386/kvm.c | 200 ++++++++++++++++++++++++++--------------------------- 1 files changed, 98 insertions(+), 102 deletions(-) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 7010999..488a3f5 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -221,49 +221,41 @@ int kvm_arch_init_vcpu(CPUState *env) return kvm_vcpu_ioctl(env, KVM_SET_CPUID2, &cpuid_data); } -static int kvm_has_msr_star(CPUState *env) +static struct kvm_msr_list *kvm_get_msr_list(CPUState *env) { - static int has_msr_star; + struct kvm_msr_list msr_list; + static struct kvm_msr_list *kvm_msr_list; int ret; - /* first time */ - if (has_msr_star == 0) { - struct kvm_msr_list msr_list, *kvm_msr_list; + if (kvm_msr_list) + return kvm_msr_list; - has_msr_star = -1; + /* Obtain MSR list from KVM. These are the MSRs that we must + * save/restore */ + msr_list.nmsrs = 0; + ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list); + if ((ret < 0) && (ret != -E2BIG)) { + printf("FAIL1 %d\n", ret); + return NULL; + } - /* Obtain MSR list from KVM. These are the MSRs that we must - * save/restore */ - msr_list.nmsrs = 0; - ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list); - if (ret < 0) - return 0; - - /* Old kernel modules had a bug and could write beyond the provided - memory. Allocate at least a safe amount of 1K. */ - kvm_msr_list = qemu_mallocz(MAX(1024, sizeof(msr_list) + - msr_list.nmsrs * - sizeof(msr_list.indices[0]))); - - kvm_msr_list->nmsrs = msr_list.nmsrs; - ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); - if (ret >= 0) { - int i; - - for (i = 0; i < kvm_msr_list->nmsrs; i++) { - if (kvm_msr_list->indices[i] == MSR_STAR) { - has_msr_star = 1; - break; - } - } - } + /* Old kernel modules had a bug and could write beyond the provided + memory. Allocate at least a safe amount of 1K. */ + kvm_msr_list = qemu_mallocz(MAX(1024, sizeof(msr_list) + + msr_list.nmsrs * + sizeof(msr_list.indices[0]))); + + kvm_msr_list->nmsrs = msr_list.nmsrs; + ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); - free(kvm_msr_list); + if (ret < 0) { + printf("FAIL2\n"); + qemu_free(kvm_msr_list); + return NULL; } - if (has_msr_star == 1) - return 1; - return 0; + return kvm_msr_list; + } int kvm_arch_init(KVMState *s, int smp_cpus) @@ -455,13 +447,47 @@ static int kvm_put_sregs(CPUState *env) return kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); } -static void kvm_msr_entry_set(struct kvm_msr_entry *entry, - uint32_t index, uint64_t value) +static uint64_t *kvm_get_msr_data_addr(CPUState *env, int index) { - entry->index = index; - entry->data = value; + uint64_t *addr; + + switch (index) { + case MSR_IA32_SYSENTER_CS: + addr = (uint64_t *)&env->sysenter_cs; + break; + case MSR_IA32_SYSENTER_ESP: + addr = (uint64_t *)&env->sysenter_esp; + break; + case MSR_IA32_SYSENTER_EIP: + addr = (uint64_t *)&env->sysenter_eip; + break; + case MSR_STAR: + addr = &env->star; + break; +#ifdef TARGET_X86_64 + case MSR_CSTAR: + addr = &env->cstar; + break; + case MSR_KERNELGSBASE: + addr = &env->kernelgsbase; + break; + case MSR_FMASK: + addr = &env->fmask; + break; + case MSR_LSTAR: + addr = &env->lstar; + break; +#endif + case MSR_IA32_TSC: + addr = &env->tsc; + break; + default: + addr = NULL; + } + return addr; } + static int kvm_put_msrs(CPUState *env) { struct { @@ -469,22 +495,24 @@ static int kvm_put_msrs(CPUState *env) struct kvm_msr_entry entries[100]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; - int n = 0; - - kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs); - kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp); - kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip); - if (kvm_has_msr_star(env)) - kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star); - kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc); -#ifdef TARGET_X86_64 - /* FIXME if lm capable */ - kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar); - kvm_msr_entry_set(&msrs[n++], MSR_KERNELGSBASE, env->kernelgsbase); - kvm_msr_entry_set(&msrs[n++], MSR_FMASK, env->fmask); - kvm_msr_entry_set(&msrs[n++], MSR_LSTAR, env->lstar); -#endif - msr_data.info.nmsrs = n; + struct kvm_msr_list *kvm_msr_list; + int i; + + kvm_msr_list = kvm_get_msr_list(env); + if (!kvm_msr_list) { + printf("FAILED\n"); + return -1; + } + + msr_data.info.nmsrs = kvm_msr_list->nmsrs; + + for (i = 0; i < kvm_msr_list->nmsrs; i++) { + uint64_t *data = kvm_get_msr_data_addr(env, kvm_msr_list->indices[i]); + msrs[i].index = kvm_msr_list->indices[i]; + if (data != NULL) { + msrs[i].data = *data; + } + } return kvm_vcpu_ioctl(env, KVM_SET_MSRS, &msr_data); @@ -601,58 +629,26 @@ static int kvm_get_msrs(CPUState *env) struct kvm_msr_entry entries[100]; } msr_data; struct kvm_msr_entry *msrs = msr_data.entries; - int ret, i, n; - - n = 0; - msrs[n++].index = MSR_IA32_SYSENTER_CS; - msrs[n++].index = MSR_IA32_SYSENTER_ESP; - msrs[n++].index = MSR_IA32_SYSENTER_EIP; - if (kvm_has_msr_star(env)) - msrs[n++].index = MSR_STAR; - msrs[n++].index = MSR_IA32_TSC; -#ifdef TARGET_X86_64 - /* FIXME lm_capable_kernel */ - msrs[n++].index = MSR_CSTAR; - msrs[n++].index = MSR_KERNELGSBASE; - msrs[n++].index = MSR_FMASK; - msrs[n++].index = MSR_LSTAR; -#endif - msr_data.info.nmsrs = n; + int ret, i; + struct kvm_msr_list *kvm_msr_list; + + kvm_msr_list = kvm_get_msr_list(env); + if (!kvm_msr_list) + return -1; + + msr_data.info.nmsrs = kvm_msr_list->nmsrs; + for (i = 0; i < kvm_msr_list->nmsrs; i++) { + msrs[i].index = kvm_msr_list->indices[i]; + } + ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data); if (ret < 0) return ret; for (i = 0; i < ret; i++) { - switch (msrs[i].index) { - case MSR_IA32_SYSENTER_CS: - env->sysenter_cs = msrs[i].data; - break; - case MSR_IA32_SYSENTER_ESP: - env->sysenter_esp = msrs[i].data; - break; - case MSR_IA32_SYSENTER_EIP: - env->sysenter_eip = msrs[i].data; - break; - case MSR_STAR: - env->star = msrs[i].data; - break; -#ifdef TARGET_X86_64 - case MSR_CSTAR: - env->cstar = msrs[i].data; - break; - case MSR_KERNELGSBASE: - env->kernelgsbase = msrs[i].data; - break; - case MSR_FMASK: - env->fmask = msrs[i].data; - break; - case MSR_LSTAR: - env->lstar = msrs[i].data; - break; -#endif - case MSR_IA32_TSC: - env->tsc = msrs[i].data; - break; + uint64_t *data = kvm_get_msr_data_addr(env, msrs[i].index); + if (data) { + *data = msrs[i].data; } } -- 1.6.2.5