aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Lendacky <thomas.lendacky@amd.com>2018-02-21 14:39:51 -0500
committerRadim Krčmář <rkrcmar@redhat.com>2018-03-01 13:00:28 -0500
commit801e459a6f3a63af9d447e6249088c76ae16efc4 (patch)
treeb23a56566b4ace273ae07cd150acec275e3cd669
parentd4858aaf6bd8a90e2dacc0dfec2077e334dcedbf (diff)
KVM: x86: Add a framework for supporting MSR-based features
Provide a new KVM capability that allows bits within MSRs to be recognized as features. Two new ioctls are added to the /dev/kvm ioctl routine to retrieve the list of these MSRs and then retrieve their values. A kvm_x86_ops callback is used to determine support for the listed MSR-based features. Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> [Tweaked documentation. - Radim] Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
-rw-r--r--Documentation/virtual/kvm/api.txt40
-rw-r--r--arch/x86/include/asm/kvm_host.h2
-rw-r--r--arch/x86/kvm/svm.c6
-rw-r--r--arch/x86/kvm/vmx.c6
-rw-r--r--arch/x86/kvm/x86.c75
-rw-r--r--include/uapi/linux/kvm.h2
6 files changed, 114 insertions, 17 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 792fa8717d13..d6b3ff51a14f 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -123,14 +123,15 @@ memory layout to fit in user mode), check KVM_CAP_MIPS_VZ and use the
123flag KVM_VM_MIPS_VZ. 123flag KVM_VM_MIPS_VZ.
124 124
125 125
1264.3 KVM_GET_MSR_INDEX_LIST 1264.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
127 127
128Capability: basic 128Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
129Architectures: x86 129Architectures: x86
130Type: system 130Type: system ioctl
131Parameters: struct kvm_msr_list (in/out) 131Parameters: struct kvm_msr_list (in/out)
132Returns: 0 on success; -1 on error 132Returns: 0 on success; -1 on error
133Errors: 133Errors:
134 EFAULT: the msr index list cannot be read from or written to
134 E2BIG: the msr index list is to be to fit in the array specified by 135 E2BIG: the msr index list is to be to fit in the array specified by
135 the user. 136 the user.
136 137
@@ -139,16 +140,23 @@ struct kvm_msr_list {
139 __u32 indices[0]; 140 __u32 indices[0];
140}; 141};
141 142
142This ioctl returns the guest msrs that are supported. The list varies 143The user fills in the size of the indices array in nmsrs, and in return
143by kvm version and host processor, but does not change otherwise. The 144kvm adjusts nmsrs to reflect the actual number of msrs and fills in the
144user fills in the size of the indices array in nmsrs, and in return 145indices array with their numbers.
145kvm adjusts nmsrs to reflect the actual number of msrs and fills in 146
146the indices array with their numbers. 147KVM_GET_MSR_INDEX_LIST returns the guest msrs that are supported. The list
148varies by kvm version and host processor, but does not change otherwise.
147 149
148Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are 150Note: if kvm indicates supports MCE (KVM_CAP_MCE), then the MCE bank MSRs are
149not returned in the MSR list, as different vcpus can have a different number 151not returned in the MSR list, as different vcpus can have a different number
150of banks, as set via the KVM_X86_SETUP_MCE ioctl. 152of banks, as set via the KVM_X86_SETUP_MCE ioctl.
151 153
154KVM_GET_MSR_FEATURE_INDEX_LIST returns the list of MSRs that can be passed
155to the KVM_GET_MSRS system ioctl. This lets userspace probe host capabilities
156and processor features that are exposed via MSRs (e.g., VMX capabilities).
157This list also varies by kvm version and host processor, but does not change
158otherwise.
159
152 160
1534.4 KVM_CHECK_EXTENSION 1614.4 KVM_CHECK_EXTENSION
154 162
@@ -475,14 +483,22 @@ Support for this has been removed. Use KVM_SET_GUEST_DEBUG instead.
475 483
4764.18 KVM_GET_MSRS 4844.18 KVM_GET_MSRS
477 485
478Capability: basic 486Capability: basic (vcpu), KVM_CAP_GET_MSR_FEATURES (system)
479Architectures: x86 487Architectures: x86
480Type: vcpu ioctl 488Type: system ioctl, vcpu ioctl
481Parameters: struct kvm_msrs (in/out) 489Parameters: struct kvm_msrs (in/out)
482Returns: 0 on success, -1 on error 490Returns: number of msrs successfully returned;
491 -1 on error
492
493When used as a system ioctl:
494Reads the values of MSR-based features that are available for the VM. This
495is similar to KVM_GET_SUPPORTED_CPUID, but it returns MSR indices and values.
496The list of msr-based features can be obtained using KVM_GET_MSR_FEATURE_INDEX_LIST
497in a system ioctl.
483 498
499When used as a vcpu ioctl:
484Reads model-specific registers from the vcpu. Supported msr indices can 500Reads model-specific registers from the vcpu. Supported msr indices can
485be obtained using KVM_GET_MSR_INDEX_LIST. 501be obtained using KVM_GET_MSR_INDEX_LIST in a system ioctl.
486 502
487struct kvm_msrs { 503struct kvm_msrs {
488 __u32 nmsrs; /* number of msrs in entries */ 504 __u32 nmsrs; /* number of msrs in entries */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 0a9e330b34f0..bab0694b35c3 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1095,6 +1095,8 @@ struct kvm_x86_ops {
1095 int (*mem_enc_op)(struct kvm *kvm, void __user *argp); 1095 int (*mem_enc_op)(struct kvm *kvm, void __user *argp);
1096 int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp); 1096 int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
1097 int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp); 1097 int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
1098
1099 int (*get_msr_feature)(struct kvm_msr_entry *entry);
1098}; 1100};
1099 1101
1100struct kvm_arch_async_pf { 1102struct kvm_arch_async_pf {
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 3d8377f75eda..d8db947acf70 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -3869,6 +3869,11 @@ static int cr8_write_interception(struct vcpu_svm *svm)
3869 return 0; 3869 return 0;
3870} 3870}
3871 3871
3872static int svm_get_msr_feature(struct kvm_msr_entry *msr)
3873{
3874 return 1;
3875}
3876
3872static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) 3877static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
3873{ 3878{
3874 struct vcpu_svm *svm = to_svm(vcpu); 3879 struct vcpu_svm *svm = to_svm(vcpu);
@@ -6832,6 +6837,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
6832 .vcpu_unblocking = svm_vcpu_unblocking, 6837 .vcpu_unblocking = svm_vcpu_unblocking,
6833 6838
6834 .update_bp_intercept = update_bp_intercept, 6839 .update_bp_intercept = update_bp_intercept,
6840 .get_msr_feature = svm_get_msr_feature,
6835 .get_msr = svm_get_msr, 6841 .get_msr = svm_get_msr,
6836 .set_msr = svm_set_msr, 6842 .set_msr = svm_set_msr,
6837 .get_segment_base = svm_get_segment_base, 6843 .get_segment_base = svm_get_segment_base,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index ec14f2319a87..fafc1f6d8987 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -3226,6 +3226,11 @@ static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
3226 return !(val & ~valid_bits); 3226 return !(val & ~valid_bits);
3227} 3227}
3228 3228
3229static int vmx_get_msr_feature(struct kvm_msr_entry *msr)
3230{
3231 return 1;
3232}
3233
3229/* 3234/*
3230 * Reads an msr value (of 'msr_index') into 'pdata'. 3235 * Reads an msr value (of 'msr_index') into 'pdata'.
3231 * Returns 0 on success, non-0 otherwise. 3236 * Returns 0 on success, non-0 otherwise.
@@ -12296,6 +12301,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
12296 .vcpu_put = vmx_vcpu_put, 12301 .vcpu_put = vmx_vcpu_put,
12297 12302
12298 .update_bp_intercept = update_exception_bitmap, 12303 .update_bp_intercept = update_exception_bitmap,
12304 .get_msr_feature = vmx_get_msr_feature,
12299 .get_msr = vmx_get_msr, 12305 .get_msr = vmx_get_msr,
12300 .set_msr = vmx_set_msr, 12306 .set_msr = vmx_set_msr,
12301 .get_segment_base = vmx_get_segment_base, 12307 .get_segment_base = vmx_get_segment_base,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 96edda878dbf..239fc1fd7845 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1049,6 +1049,28 @@ static u32 emulated_msrs[] = {
1049 1049
1050static unsigned num_emulated_msrs; 1050static 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 */
1056static u32 msr_based_features[] = {
1057};
1058
1059static unsigned int num_msr_based_features;
1060
1061static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
1062{
1063 struct kvm_msr_entry msr;
1064
1065 msr.index = index;
1066 if (kvm_x86_ops->get_msr_feature(&msr))
1067 return 1;
1068
1069 *data = msr.data;
1070
1071 return 0;
1072}
1073
1052bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer) 1074bool kvm_valid_efer(struct kvm_vcpu *vcpu, u64 efer)
1053{ 1075{
1054 if (efer & efer_reserved_bits) 1076 if (efer & efer_reserved_bits)
@@ -2680,13 +2702,11 @@ static int __msr_io(struct kvm_vcpu *vcpu, struct kvm_msrs *msrs,
2680 int (*do_msr)(struct kvm_vcpu *vcpu, 2702 int (*do_msr)(struct kvm_vcpu *vcpu,
2681 unsigned index, u64 *data)) 2703 unsigned index, u64 *data))
2682{ 2704{
2683 int i, idx; 2705 int i;
2684 2706
2685 idx = srcu_read_lock(&vcpu->kvm->srcu);
2686 for (i = 0; i < msrs->nmsrs; ++i) 2707 for (i = 0; i < msrs->nmsrs; ++i)
2687 if (do_msr(vcpu, entries[i].index, &entries[i].data)) 2708 if (do_msr(vcpu, entries[i].index, &entries[i].data))
2688 break; 2709 break;
2689 srcu_read_unlock(&vcpu->kvm->srcu, idx);
2690 2710
2691 return i; 2711 return i;
2692} 2712}
@@ -2785,6 +2805,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
2785 case KVM_CAP_SET_BOOT_CPU_ID: 2805 case KVM_CAP_SET_BOOT_CPU_ID:
2786 case KVM_CAP_SPLIT_IRQCHIP: 2806 case KVM_CAP_SPLIT_IRQCHIP:
2787 case KVM_CAP_IMMEDIATE_EXIT: 2807 case KVM_CAP_IMMEDIATE_EXIT:
2808 case KVM_CAP_GET_MSR_FEATURES:
2788 r = 1; 2809 r = 1;
2789 break; 2810 break;
2790 case KVM_CAP_ADJUST_CLOCK: 2811 case KVM_CAP_ADJUST_CLOCK:
@@ -2899,6 +2920,31 @@ long kvm_arch_dev_ioctl(struct file *filp,
2899 goto out; 2920 goto out;
2900 r = 0; 2921 r = 0;
2901 break; 2922 break;
2923 case KVM_GET_MSR_FEATURE_INDEX_LIST: {
2924 struct kvm_msr_list __user *user_msr_list = argp;
2925 struct kvm_msr_list msr_list;
2926 unsigned int n;
2927
2928 r = -EFAULT;
2929 if (copy_from_user(&msr_list, user_msr_list, sizeof(msr_list)))
2930 goto out;
2931 n = msr_list.nmsrs;
2932 msr_list.nmsrs = num_msr_based_features;
2933 if (copy_to_user(user_msr_list, &msr_list, sizeof(msr_list)))
2934 goto out;
2935 r = -E2BIG;
2936 if (n < msr_list.nmsrs)
2937 goto out;
2938 r = -EFAULT;
2939 if (copy_to_user(user_msr_list->indices, &msr_based_features,
2940 num_msr_based_features * sizeof(u32)))
2941 goto out;
2942 r = 0;
2943 break;
2944 }
2945 case KVM_GET_MSRS:
2946 r = msr_io(NULL, argp, do_get_msr_feature, 1);
2947 break;
2902 } 2948 }
2903 default: 2949 default:
2904 r = -EINVAL; 2950 r = -EINVAL;
@@ -3636,12 +3682,18 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
3636 r = 0; 3682 r = 0;
3637 break; 3683 break;
3638 } 3684 }
3639 case KVM_GET_MSRS: 3685 case KVM_GET_MSRS: {
3686 int idx = srcu_read_lock(&vcpu->kvm->srcu);
3640 r = msr_io(vcpu, argp, do_get_msr, 1); 3687 r = msr_io(vcpu, argp, do_get_msr, 1);
3688 srcu_read_unlock(&vcpu->kvm->srcu, idx);
3641 break; 3689 break;
3642 case KVM_SET_MSRS: 3690 }
3691 case KVM_SET_MSRS: {
3692 int idx = srcu_read_lock(&vcpu->kvm->srcu);
3643 r = msr_io(vcpu, argp, do_set_msr, 0); 3693 r = msr_io(vcpu, argp, do_set_msr, 0);
3694 srcu_read_unlock(&vcpu->kvm->srcu, idx);
3644 break; 3695 break;
3696 }
3645 case KVM_TPR_ACCESS_REPORTING: { 3697 case KVM_TPR_ACCESS_REPORTING: {
3646 struct kvm_tpr_access_ctl tac; 3698 struct kvm_tpr_access_ctl tac;
3647 3699
@@ -4464,6 +4516,19 @@ static void kvm_init_msr_list(void)
4464 j++; 4516 j++;
4465 } 4517 }
4466 num_emulated_msrs = j; 4518 num_emulated_msrs = j;
4519
4520 for (i = j = 0; i < ARRAY_SIZE(msr_based_features); i++) {
4521 struct kvm_msr_entry msr;
4522
4523 msr.index = msr_based_features[i];
4524 if (kvm_x86_ops->get_msr_feature(&msr))
4525 continue;
4526
4527 if (j < i)
4528 msr_based_features[j] = msr_based_features[i];
4529 j++;
4530 }
4531 num_msr_based_features = j;
4467} 4532}
4468 4533
4469static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, 4534static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 0fb5ef939732..7b26d4b0b052 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -761,6 +761,7 @@ struct kvm_ppc_resize_hpt {
761#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07 761#define KVM_TRACE_PAUSE __KVM_DEPRECATED_MAIN_0x07
762#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08 762#define KVM_TRACE_DISABLE __KVM_DEPRECATED_MAIN_0x08
763#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2) 763#define KVM_GET_EMULATED_CPUID _IOWR(KVMIO, 0x09, struct kvm_cpuid2)
764#define KVM_GET_MSR_FEATURE_INDEX_LIST _IOWR(KVMIO, 0x0a, struct kvm_msr_list)
764 765
765/* 766/*
766 * Extension capability list. 767 * Extension capability list.
@@ -934,6 +935,7 @@ struct kvm_ppc_resize_hpt {
934#define KVM_CAP_S390_AIS_MIGRATION 150 935#define KVM_CAP_S390_AIS_MIGRATION 150
935#define KVM_CAP_PPC_GET_CPU_CHAR 151 936#define KVM_CAP_PPC_GET_CPU_CHAR 151
936#define KVM_CAP_S390_BPB 152 937#define KVM_CAP_S390_BPB 152
938#define KVM_CAP_GET_MSR_FEATURES 153
937 939
938#ifdef KVM_CAP_IRQ_ROUTING 940#ifdef KVM_CAP_IRQ_ROUTING
939 941