diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 107 |
1 files changed, 96 insertions, 11 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index c8a0b545ac20..18b5ca7a3197 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1049,6 +1049,45 @@ static u32 emulated_msrs[] = { | |||
1049 | 1049 | ||
1050 | static unsigned num_emulated_msrs; | 1050 | static unsigned num_emulated_msrs; |
1051 | 1051 | ||
1052 | /* | ||
1053 | * List of msr numbers which are used to expose MSR-based features that | ||
1054 | * can be used by a hypervisor to validate requested CPU features. | ||
1055 | */ | ||
1056 | static u32 msr_based_features[] = { | ||
1057 | MSR_F10H_DECFG, | ||
1058 | MSR_IA32_UCODE_REV, | ||
1059 | }; | ||
1060 | |||
1061 | static unsigned int num_msr_based_features; | ||
1062 | |||
1063 | static int kvm_get_msr_feature(struct kvm_msr_entry *msr) | ||
1064 | { | ||
1065 | switch (msr->index) { | ||
1066 | case MSR_IA32_UCODE_REV: | ||
1067 | rdmsrl(msr->index, msr->data); | ||
1068 | break; | ||
1069 | default: | ||
1070 | if (kvm_x86_ops->get_msr_feature(msr)) | ||
1071 | return 1; | ||
1072 | } | ||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data) | ||
1077 | { | ||
1078 | struct kvm_msr_entry msr; | ||
1079 | int r; | ||
1080 | |||
1081 | msr.index = index; | ||
1082 | r = kvm_get_msr_feature(&msr); | ||
1083 | if (r) | ||
1084 | return r; | ||
1085 | |||
1086 | *data = msr.data; | ||
1087 | |||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1052 | bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer) | 1091 | bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer) |
1053 | { | 1092 | { |
1054 | if (efer & efer_reserved_bits) | 1093 | if (efer & efer_reserved_bits) |
@@ -2222,7 +2261,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
2222 | 2261 | ||
2223 | switch (msr) { | 2262 | switch (msr) { |
2224 | case MSR_AMD64_NB_CFG: | 2263 | case MSR_AMD64_NB_CFG: |
2225 | case MSR_IA32_UCODE_REV: | ||
2226 | case MSR_IA32_UCODE_WRITE: | 2264 | case MSR_IA32_UCODE_WRITE: |
2227 | case MSR_VM_HSAVE_PA: | 2265 | case MSR_VM_HSAVE_PA: |
2228 | case MSR_AMD64_PATCH_LOADER: | 2266 | case MSR_AMD64_PATCH_LOADER: |
@@ -2230,6 +2268,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
2230 | case MSR_AMD64_DC_CFG: | 2268 | case MSR_AMD64_DC_CFG: |
2231 | break; | 2269 | break; |
2232 | 2270 | ||
2271 | case MSR_IA32_UCODE_REV: | ||
2272 | if (msr_info->host_initiated) | ||
2273 | vcpu->arch.microcode_version = data; | ||
2274 | break; | ||
2233 | case MSR_EFER: | 2275 | case MSR_EFER: |
2234 | return set_efer(vcpu, data); | 2276 | return set_efer(vcpu, data); |
2235 | case MSR_K7_HWCR: | 2277 | case MSR_K7_HWCR: |
@@ -2525,7 +2567,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) | |||
2525 | msr_info->data = 0; | 2567 | msr_info->data = 0; |
2526 | break; | 2568 | break; |
2527 | case MSR_IA32_UCODE_REV: | 2569 | case MSR_IA32_UCODE_REV: |
2528 | msr_info->data = 0x100000000ULL; | 2570 | msr_info->data = vcpu->arch.microcode_version; |
2529 | break; | 2571 | break; |
2530 | case MSR_MTRRcap: | 2572 | case MSR_MTRRcap: |
2531 | case 0x200 ... 0x2ff: | 2573 | case 0x200 ... 0x2ff: |
@@ -2680,13 +2722,11 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs, | |||
2680 | int (*do_msr)(struct kvm_vcpu *vcpu, | 2722 | int (*do_msr)(struct kvm_vcpu *vcpu, |
2681 | unsigned index, u64 *data)) | 2723 | unsigned index, u64 *data)) |
2682 | { | 2724 | { |
2683 | int i, idx; | 2725 | int i; |
2684 | 2726 | ||
2685 | idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
2686 | for (i = 0; i < msrs->nmsrs; ++i) | 2727 | for (i = 0; i < msrs->nmsrs; ++i) |
2687 | if (do_msr(vcpu, entries[i].index, &entries[i].data)) | 2728 | if (do_msr(vcpu, entries[i].index, &entries[i].data)) |
2688 | break; | 2729 | break; |
2689 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
2690 | 2730 | ||
2691 | return i; | 2731 | return i; |
2692 | } | 2732 | } |
@@ -2785,6 +2825,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) | |||
2785 | case KVM_CAP_SET_BOOT_CPU_ID: | 2825 | case KVM_CAP_SET_BOOT_CPU_ID: |
2786 | case KVM_CAP_SPLIT_IRQCHIP: | 2826 | case KVM_CAP_SPLIT_IRQCHIP: |
2787 | case KVM_CAP_IMMEDIATE_EXIT: | 2827 | case KVM_CAP_IMMEDIATE_EXIT: |
2828 | case KVM_CAP_GET_MSR_FEATURES: | ||
2788 | r = 1; | 2829 | r = 1; |
2789 | break; | 2830 | break; |
2790 | case KVM_CAP_ADJUST_CLOCK: | 2831 | case KVM_CAP_ADJUST_CLOCK: |
@@ -2899,6 +2940,31 @@ long kvm_arch_dev_ioctl(struct file *filp, | |||
2899 | goto out; | 2940 | goto out; |
2900 | r = 0; | 2941 | r = 0; |
2901 | break; | 2942 | break; |
2943 | case KVM_GET_MSR_FEATURE_INDEX_LIST: { | ||
2944 | struct kvm_msr_list __user *user_msr_list = argp; | ||
2945 | struct kvm_msr_list msr_list; | ||
2946 | unsigned int n; | ||
2947 | |||
2948 | r = -EFAULT; | ||
2949 | if (copy_from_user(&msr_list, user_msr_list, sizeof(msr_list))) | ||
2950 | goto out; | ||
2951 | n = msr_list.nmsrs; | ||
2952 | msr_list.nmsrs = num_msr_based_features; | ||
2953 | if (copy_to_user(user_msr_list, &msr_list, sizeof(msr_list))) | ||
2954 | goto out; | ||
2955 | r = -E2BIG; | ||
2956 | if (n < msr_list.nmsrs) | ||
2957 | goto out; | ||
2958 | r = -EFAULT; | ||
2959 | if (copy_to_user(user_msr_list->indices, &msr_based_features, | ||
2960 | num_msr_based_features * sizeof(u32))) | ||
2961 | goto out; | ||
2962 | r = 0; | ||
2963 | break; | ||
2964 | } | ||
2965 | case KVM_GET_MSRS: | ||
2966 | r = msr_io(NULL, argp, do_get_msr_feature, 1); | ||
2967 | break; | ||
2902 | } | 2968 | } |
2903 | default: | 2969 | default: |
2904 | r = -EINVAL; | 2970 | r = -EINVAL; |
@@ -3636,12 +3702,18 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
3636 | r = 0; | 3702 | r = 0; |
3637 | break; | 3703 | break; |
3638 | } | 3704 | } |
3639 | case KVM_GET_MSRS: | 3705 | case KVM_GET_MSRS: { |
3706 | int idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
3640 | r = msr_io(vcpu, argp, do_get_msr, 1); | 3707 | r = msr_io(vcpu, argp, do_get_msr, 1); |
3708 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
3641 | break; | 3709 | break; |
3642 | case KVM_SET_MSRS: | 3710 | } |
3711 | case KVM_SET_MSRS: { | ||
3712 | int idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
3643 | r = msr_io(vcpu, argp, do_set_msr, 0); | 3713 | r = msr_io(vcpu, argp, do_set_msr, 0); |
3714 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
3644 | break; | 3715 | break; |
3716 | } | ||
3645 | case KVM_TPR_ACCESS_REPORTING: { | 3717 | case KVM_TPR_ACCESS_REPORTING: { |
3646 | struct kvm_tpr_access_ctl tac; | 3718 | struct kvm_tpr_access_ctl tac; |
3647 | 3719 | ||
@@ -4464,6 +4536,19 @@ static void kvm_init_msr_list(void) | |||
4464 | j++; | 4536 | j++; |
4465 | } | 4537 | } |
4466 | num_emulated_msrs = j; | 4538 | num_emulated_msrs = j; |
4539 | |||
4540 | for (i = j = 0; i < ARRAY_SIZE(msr_based_features); i++) { | ||
4541 | struct kvm_msr_entry msr; | ||
4542 | |||
4543 | msr.index = msr_based_features[i]; | ||
4544 | if (kvm_get_msr_feature(&msr)) | ||
4545 | continue; | ||
4546 | |||
4547 | if (j < i) | ||
4548 | msr_based_features[j] = msr_based_features[i]; | ||
4549 | j++; | ||
4550 | } | ||
4551 | num_msr_based_features = j; | ||
4467 | } | 4552 | } |
4468 | 4553 | ||
4469 | static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, | 4554 | static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, |
@@ -8017,6 +8102,8 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) | |||
8017 | 8102 | ||
8018 | void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) | 8103 | void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) |
8019 | { | 8104 | { |
8105 | kvm_lapic_reset(vcpu, init_event); | ||
8106 | |||
8020 | vcpu->arch.hflags = 0; | 8107 | vcpu->arch.hflags = 0; |
8021 | 8108 | ||
8022 | vcpu->arch.smi_pending = 0; | 8109 | vcpu->arch.smi_pending = 0; |
@@ -8460,10 +8547,8 @@ int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size) | |||
8460 | return r; | 8547 | return r; |
8461 | } | 8548 | } |
8462 | 8549 | ||
8463 | if (!size) { | 8550 | if (!size) |
8464 | r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); | 8551 | vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE); |
8465 | WARN_ON(r < 0); | ||
8466 | } | ||
8467 | 8552 | ||
8468 | return 0; | 8553 | return 0; |
8469 | } | 8554 | } |