aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
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/x86/kvm/vmx.c
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/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c60
1 files changed, 57 insertions, 3 deletions
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)