aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2009-12-18 03:48:47 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:35:40 -0500
commit4e47c7a6d714cf352b719db92a924b6ec487acc5 (patch)
treeb968765b85124e0b59f415bf8e4d499ef953236e /arch
parent0e85188049afacdfce9c026144142264981bbabb (diff)
KVM: VMX: Add instruction rdtscp support for guest
Before enabling, execution of "rdtscp" in guest would result in #UD. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/include/asm/vmx.h1
-rw-r--r--arch/x86/kvm/svm.c7
-rw-r--r--arch/x86/kvm/vmx.c60
-rw-r--r--arch/x86/kvm/x86.c3
5 files changed, 68 insertions, 4 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 7ff0ea371e3c..fe4df464fb39 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -521,6 +521,7 @@ struct kvm_x86_ops {
521 int (*get_tdp_level)(void); 521 int (*get_tdp_level)(void);
522 u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio); 522 u64 (*get_mt_mask)(struct kvm_vcpu *vcpu, gfn_t gfn, bool is_mmio);
523 bool (*gb_page_enable)(void); 523 bool (*gb_page_enable)(void);
524 bool (*rdtscp_supported)(void);
524 525
525 const struct trace_print_flags *exit_reasons_str; 526 const struct trace_print_flags *exit_reasons_str;
526}; 527};
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 8f6b0111446a..713ed9a5b1d3 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -53,6 +53,7 @@
53 */ 53 */
54#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 54#define SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001
55#define SECONDARY_EXEC_ENABLE_EPT 0x00000002 55#define SECONDARY_EXEC_ENABLE_EPT 0x00000002
56#define SECONDARY_EXEC_RDTSCP 0x00000008
56#define SECONDARY_EXEC_ENABLE_VPID 0x00000020 57#define SECONDARY_EXEC_ENABLE_VPID 0x00000020
57#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040 58#define SECONDARY_EXEC_WBINVD_EXITING 0x00000040
58#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 59#define SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 41777e6d9761..7f4e225feebf 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -2914,6 +2914,11 @@ static bool svm_gb_page_enable(void)
2914 return true; 2914 return true;
2915} 2915}
2916 2916
2917static bool svm_rdtscp_supported(void)
2918{
2919 return false;
2920}
2921
2917static struct kvm_x86_ops svm_x86_ops = { 2922static struct kvm_x86_ops svm_x86_ops = {
2918 .cpu_has_kvm_support = has_svm, 2923 .cpu_has_kvm_support = has_svm,
2919 .disabled_by_bios = is_disabled, 2924 .disabled_by_bios = is_disabled,
@@ -2982,6 +2987,8 @@ static struct kvm_x86_ops svm_x86_ops = {
2982 .gb_page_enable = svm_gb_page_enable, 2987 .gb_page_enable = svm_gb_page_enable,
2983 2988
2984 .cpuid_update = svm_cpuid_update, 2989 .cpuid_update = svm_cpuid_update,
2990
2991 .rdtscp_supported = svm_rdtscp_supported,
2985}; 2992};
2986 2993
2987static int __init svm_init(void) 2994static int __init svm_init(void)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 75e8931e96c7..74a66f0c00b4 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -151,6 +151,8 @@ struct vcpu_vmx {
151 ktime_t entry_time; 151 ktime_t entry_time;
152 s64 vnmi_blocked_time; 152 s64 vnmi_blocked_time;
153 u32 exit_reason; 153 u32 exit_reason;
154
155 bool rdtscp_enabled;
154}; 156};
155 157
156static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu) 158static inline struct vcpu_vmx *to_vmx(struct kvm_vcpu *vcpu)
@@ -225,7 +227,7 @@ static const u32 vmx_msr_index[] = {
225#ifdef CONFIG_X86_64 227#ifdef CONFIG_X86_64
226 MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, 228 MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR,
227#endif 229#endif
228 MSR_EFER, MSR_K6_STAR, 230 MSR_EFER, MSR_TSC_AUX, MSR_K6_STAR,
229}; 231};
230#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index) 232#define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index)
231 233
@@ -362,6 +364,12 @@ static inline int cpu_has_vmx_vpid(void)
362 SECONDARY_EXEC_ENABLE_VPID; 364 SECONDARY_EXEC_ENABLE_VPID;
363} 365}
364 366
367static inline int cpu_has_vmx_rdtscp(void)
368{
369 return vmcs_config.cpu_based_2nd_exec_ctrl &
370 SECONDARY_EXEC_RDTSCP;
371}
372
365static inline int cpu_has_virtual_nmis(void) 373static inline int cpu_has_virtual_nmis(void)
366{ 374{
367 return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS; 375 return vmcs_config.pin_based_exec_ctrl & PIN_BASED_VIRTUAL_NMIS;
@@ -893,6 +901,11 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
893 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info); 901 vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, intr_info);
894} 902}
895 903
904static bool vmx_rdtscp_supported(void)
905{
906 return cpu_has_vmx_rdtscp();
907}
908
896/* 909/*
897 * Swap MSR entry in host/guest MSR entry array. 910 * Swap MSR entry in host/guest MSR entry array.
898 */ 911 */
@@ -928,6 +941,9 @@ static void setup_msrs(struct vcpu_vmx *vmx)
928 index = __find_msr_index(vmx, MSR_CSTAR); 941 index = __find_msr_index(vmx, MSR_CSTAR);
929 if (index >= 0) 942 if (index >= 0)
930 move_msr_up(vmx, index, save_nmsrs++); 943 move_msr_up(vmx, index, save_nmsrs++);
944 index = __find_msr_index(vmx, MSR_TSC_AUX);
945 if (index >= 0 && vmx->rdtscp_enabled)
946 move_msr_up(vmx, index, save_nmsrs++);
931 /* 947 /*
932 * MSR_K6_STAR is only needed on long mode guests, and only 948 * MSR_K6_STAR is only needed on long mode guests, and only
933 * if efer.sce is enabled. 949 * if efer.sce is enabled.
@@ -1017,6 +1033,10 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
1017 case MSR_IA32_SYSENTER_ESP: 1033 case MSR_IA32_SYSENTER_ESP:
1018 data = vmcs_readl(GUEST_SYSENTER_ESP); 1034 data = vmcs_readl(GUEST_SYSENTER_ESP);
1019 break; 1035 break;
1036 case MSR_TSC_AUX:
1037 if (!to_vmx(vcpu)->rdtscp_enabled)
1038 return 1;
1039 /* Otherwise falls through */
1020 default: 1040 default:
1021 vmx_load_host_state(to_vmx(vcpu)); 1041 vmx_load_host_state(to_vmx(vcpu));
1022 msr = find_msr_entry(to_vmx(vcpu), msr_index); 1042 msr = find_msr_entry(to_vmx(vcpu), msr_index);
@@ -1080,7 +1100,15 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
1080 vcpu->arch.pat = data; 1100 vcpu->arch.pat = data;
1081 break; 1101 break;
1082 } 1102 }
1083 /* Otherwise falls through to kvm_set_msr_common */ 1103 ret = kvm_set_msr_common(vcpu, msr_index, data);
1104 break;
1105 case MSR_TSC_AUX:
1106 if (!vmx->rdtscp_enabled)
1107 return 1;
1108 /* Check reserved bit, higher 32 bits should be zero */
1109 if ((data >> 32) != 0)
1110 return 1;
1111 /* Otherwise falls through */
1084 default: 1112 default:
1085 msr = find_msr_entry(vmx, msr_index); 1113 msr = find_msr_entry(vmx, msr_index);
1086 if (msr) { 1114 if (msr) {
@@ -1260,7 +1288,8 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
1260 SECONDARY_EXEC_ENABLE_VPID | 1288 SECONDARY_EXEC_ENABLE_VPID |
1261 SECONDARY_EXEC_ENABLE_EPT | 1289 SECONDARY_EXEC_ENABLE_EPT |
1262 SECONDARY_EXEC_UNRESTRICTED_GUEST | 1290 SECONDARY_EXEC_UNRESTRICTED_GUEST |
1263 SECONDARY_EXEC_PAUSE_LOOP_EXITING; 1291 SECONDARY_EXEC_PAUSE_LOOP_EXITING |
1292 SECONDARY_EXEC_RDTSCP;
1264 if (adjust_vmx_controls(min2, opt2, 1293 if (adjust_vmx_controls(min2, opt2,
1265 MSR_IA32_VMX_PROCBASED_CTLS2, 1294 MSR_IA32_VMX_PROCBASED_CTLS2,
1266 &_cpu_based_2nd_exec_control) < 0) 1295 &_cpu_based_2nd_exec_control) < 0)
@@ -3988,8 +4017,31 @@ static bool vmx_gb_page_enable(void)
3988 return false; 4017 return false;
3989} 4018}
3990 4019
4020static inline u32 bit(int bitno)
4021{
4022 return 1 << (bitno & 31);
4023}
4024
3991static void vmx_cpuid_update(struct kvm_vcpu *vcpu) 4025static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
3992{ 4026{
4027 struct kvm_cpuid_entry2 *best;
4028 struct vcpu_vmx *vmx = to_vmx(vcpu);
4029 u32 exec_control;
4030
4031 vmx->rdtscp_enabled = false;
4032 if (vmx_rdtscp_supported()) {
4033 exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
4034 if (exec_control & SECONDARY_EXEC_RDTSCP) {
4035 best = kvm_find_cpuid_entry(vcpu, 0x80000001, 0);
4036 if (best && (best->edx & bit(X86_FEATURE_RDTSCP)))
4037 vmx->rdtscp_enabled = true;
4038 else {
4039 exec_control &= ~SECONDARY_EXEC_RDTSCP;
4040 vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
4041 exec_control);
4042 }
4043 }
4044 }
3993} 4045}
3994 4046
3995static struct kvm_x86_ops vmx_x86_ops = { 4047static struct kvm_x86_ops vmx_x86_ops = {
@@ -4058,6 +4110,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
4058 .gb_page_enable = vmx_gb_page_enable, 4110 .gb_page_enable = vmx_gb_page_enable,
4059 4111
4060 .cpuid_update = vmx_cpuid_update, 4112 .cpuid_update = vmx_cpuid_update,
4113
4114 .rdtscp_supported = vmx_rdtscp_supported,
4061}; 4115};
4062 4116
4063static int __init vmx_init(void) 4117static int __init vmx_init(void)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e5ac21f992f0..8798504ace11 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1646,6 +1646,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
1646#else 1646#else
1647 unsigned f_lm = 0; 1647 unsigned f_lm = 0;
1648#endif 1648#endif
1649 unsigned f_rdtscp = kvm_x86_ops->rdtscp_supported() ? F(RDTSCP) : 0;
1649 1650
1650 /* cpuid 1.edx */ 1651 /* cpuid 1.edx */
1651 const u32 kvm_supported_word0_x86_features = 1652 const u32 kvm_supported_word0_x86_features =
@@ -1665,7 +1666,7 @@ static void do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
1665 F(MTRR) | F(PGE) | F(MCA) | F(CMOV) | 1666 F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
1666 F(PAT) | F(PSE36) | 0 /* Reserved */ | 1667 F(PAT) | F(PSE36) | 0 /* Reserved */ |
1667 f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) | 1668 f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
1668 F(FXSR) | F(FXSR_OPT) | f_gbpages | 0 /* RDTSCP */ | 1669 F(FXSR) | F(FXSR_OPT) | f_gbpages | f_rdtscp |
1669 0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW); 1670 0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW);
1670 /* cpuid 1.ecx */ 1671 /* cpuid 1.ecx */
1671 const u32 kvm_supported_word4_x86_features = 1672 const u32 kvm_supported_word4_x86_features =