aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/vmx.c
diff options
context:
space:
mode:
authorWill Auld <will.auld.intel@gmail.com>2012-11-29 15:42:50 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2012-11-30 15:29:30 -0500
commitba904635d498fea43fc3610983f9dc430ac324e4 (patch)
treedcfcf9817a3a907950520d72b677077ecced7e01 /arch/x86/kvm/vmx.c
parent8fe8ab46be06fcd9abfe6fe9928fd95b54ab079a (diff)
KVM: x86: Emulate IA32_TSC_ADJUST MSR
CPUID.7.0.EBX[1]=1 indicates IA32_TSC_ADJUST MSR 0x3b is supported Basic design is to emulate the MSR by allowing reads and writes to a guest vcpu specific location to store the value of the emulated MSR while adding the value to the vmcs tsc_offset. In this way the IA32_TSC_ADJUST value will be included in all reads to the TSC MSR whether through rdmsr or rdtsc. This is of course as long as the "use TSC counter offsetting" VM-execution control is enabled as well as the IA32_TSC_ADJUST control. However, because hardware will only return the TSC + IA32_TSC_ADJUST + vmsc tsc_offset for a guest process when it does and rdtsc (with the correct settings) the value of our virtualized IA32_TSC_ADJUST must be stored in one of these three locations. The argument against storing it in the actual MSR is performance. This is likely to be seldom used while the save/restore is required on every transition. IA32_TSC_ADJUST was created as a way to solve some issues with writing TSC itself so that is not an option either. The remaining option, defined above as our solution has the problem of returning incorrect vmcs tsc_offset values (unless we intercept and fix, not done here) as mentioned above. However, more problematic is that storing the data in vmcs tsc_offset will have a different semantic effect on the system than does using the actual MSR. This is illustrated in the following example: The hypervisor set the IA32_TSC_ADJUST, then the guest sets it and a guest process performs a rdtsc. In this case the guest process will get TSC + IA32_TSC_ADJUST_hyperviser + vmsc tsc_offset including IA32_TSC_ADJUST_guest. While the total system semantics changed the semantics as seen by the guest do not and hence this will not cause a problem. Signed-off-by: Will Auld <will.auld@intel.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r--arch/x86/kvm/vmx.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 45ffa32352f1..2fd2046dc94c 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -1884,6 +1884,11 @@ static void vmx_set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale)
1884 WARN(1, "user requested TSC rate below hardware speed\n"); 1884 WARN(1, "user requested TSC rate below hardware speed\n");
1885} 1885}
1886 1886
1887static u64 vmx_read_tsc_offset(struct kvm_vcpu *vcpu)
1888{
1889 return vmcs_read64(TSC_OFFSET);
1890}
1891
1887/* 1892/*
1888 * writes 'offset' into guest's timestamp counter offset register 1893 * writes 'offset' into guest's timestamp counter offset register
1889 */ 1894 */
@@ -2266,6 +2271,9 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
2266 } 2271 }
2267 ret = kvm_set_msr_common(vcpu, msr_info); 2272 ret = kvm_set_msr_common(vcpu, msr_info);
2268 break; 2273 break;
2274 case MSR_IA32_TSC_ADJUST:
2275 ret = kvm_set_msr_common(vcpu, msr_info);
2276 break;
2269 case MSR_TSC_AUX: 2277 case MSR_TSC_AUX:
2270 if (!vmx->rdtscp_enabled) 2278 if (!vmx->rdtscp_enabled)
2271 return 1; 2279 return 1;
@@ -7345,6 +7353,7 @@ static struct kvm_x86_ops vmx_x86_ops = {
7345 .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit, 7353 .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
7346 7354
7347 .set_tsc_khz = vmx_set_tsc_khz, 7355 .set_tsc_khz = vmx_set_tsc_khz,
7356 .read_tsc_offset = vmx_read_tsc_offset,
7348 .write_tsc_offset = vmx_write_tsc_offset, 7357 .write_tsc_offset = vmx_write_tsc_offset,
7349 .adjust_tsc_offset = vmx_adjust_tsc_offset, 7358 .adjust_tsc_offset = vmx_adjust_tsc_offset,
7350 .compute_tsc_offset = vmx_compute_tsc_offset, 7359 .compute_tsc_offset = vmx_compute_tsc_offset,