aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorKarimAllah Ahmed <karahmed@amazon.de>2018-04-13 23:10:52 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2018-04-16 11:50:11 -0400
commite79f245ddec17bbd89d73cd0169dba4be46c9b55 (patch)
tree0cf1274bfc8df0b80aeb1908a052e707fe9082c0 /arch/x86/kvm/svm.c
parent4e1acd7b31a03f24cc6108d37d005e6b1d48c5d3 (diff)
X86/KVM: Properly update 'tsc_offset' to represent the running guest
Update 'tsc_offset' on vmentry/vmexit of L2 guests to ensure that it always captures the TSC_OFFSET of the running guest whether it is the L1 or L2 guest. Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: Radim Krčmář <rkrcmar@redhat.com> Cc: kvm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Reviewed-by: Jim Mattson <jmattson@google.com> Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: KarimAllah Ahmed <karahmed@amazon.de> [AMD changes, fix update_ia32_tsc_adjust_msr. - Paolo] Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r--arch/x86/kvm/svm.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index b3ebc8ad6891..e77a536d0b7c 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1424,12 +1424,23 @@ static void init_sys_seg(struct vmcb_seg *seg, uint32_t type)
1424 seg->base = 0; 1424 seg->base = 0;
1425} 1425}
1426 1426
1427static u64 svm_read_l1_tsc_offset(struct kvm_vcpu *vcpu)
1428{
1429 struct vcpu_svm *svm = to_svm(vcpu);
1430
1431 if (is_guest_mode(vcpu))
1432 return svm->nested.hsave->control.tsc_offset;
1433
1434 return vcpu->arch.tsc_offset;
1435}
1436
1427static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) 1437static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
1428{ 1438{
1429 struct vcpu_svm *svm = to_svm(vcpu); 1439 struct vcpu_svm *svm = to_svm(vcpu);
1430 u64 g_tsc_offset = 0; 1440 u64 g_tsc_offset = 0;
1431 1441
1432 if (is_guest_mode(vcpu)) { 1442 if (is_guest_mode(vcpu)) {
1443 /* Write L1's TSC offset. */
1433 g_tsc_offset = svm->vmcb->control.tsc_offset - 1444 g_tsc_offset = svm->vmcb->control.tsc_offset -
1434 svm->nested.hsave->control.tsc_offset; 1445 svm->nested.hsave->control.tsc_offset;
1435 svm->nested.hsave->control.tsc_offset = offset; 1446 svm->nested.hsave->control.tsc_offset = offset;
@@ -3323,6 +3334,7 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
3323 /* Restore the original control entries */ 3334 /* Restore the original control entries */
3324 copy_vmcb_control_area(vmcb, hsave); 3335 copy_vmcb_control_area(vmcb, hsave);
3325 3336
3337 svm->vcpu.arch.tsc_offset = svm->vmcb->control.tsc_offset;
3326 kvm_clear_exception_queue(&svm->vcpu); 3338 kvm_clear_exception_queue(&svm->vcpu);
3327 kvm_clear_interrupt_queue(&svm->vcpu); 3339 kvm_clear_interrupt_queue(&svm->vcpu);
3328 3340
@@ -3483,10 +3495,12 @@ static void enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb_gpa,
3483 /* We don't want to see VMMCALLs from a nested guest */ 3495 /* We don't want to see VMMCALLs from a nested guest */
3484 clr_intercept(svm, INTERCEPT_VMMCALL); 3496 clr_intercept(svm, INTERCEPT_VMMCALL);
3485 3497
3498 svm->vcpu.arch.tsc_offset += nested_vmcb->control.tsc_offset;
3499 svm->vmcb->control.tsc_offset = svm->vcpu.arch.tsc_offset;
3500
3486 svm->vmcb->control.virt_ext = nested_vmcb->control.virt_ext; 3501 svm->vmcb->control.virt_ext = nested_vmcb->control.virt_ext;
3487 svm->vmcb->control.int_vector = nested_vmcb->control.int_vector; 3502 svm->vmcb->control.int_vector = nested_vmcb->control.int_vector;
3488 svm->vmcb->control.int_state = nested_vmcb->control.int_state; 3503 svm->vmcb->control.int_state = nested_vmcb->control.int_state;
3489 svm->vmcb->control.tsc_offset += nested_vmcb->control.tsc_offset;
3490 svm->vmcb->control.event_inj = nested_vmcb->control.event_inj; 3504 svm->vmcb->control.event_inj = nested_vmcb->control.event_inj;
3491 svm->vmcb->control.event_inj_err = nested_vmcb->control.event_inj_err; 3505 svm->vmcb->control.event_inj_err = nested_vmcb->control.event_inj_err;
3492 3506
@@ -7102,6 +7116,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
7102 7116
7103 .has_wbinvd_exit = svm_has_wbinvd_exit, 7117 .has_wbinvd_exit = svm_has_wbinvd_exit,
7104 7118
7119 .read_l1_tsc_offset = svm_read_l1_tsc_offset,
7105 .write_tsc_offset = svm_write_tsc_offset, 7120 .write_tsc_offset = svm_write_tsc_offset,
7106 7121
7107 .set_tdp_cr3 = set_tdp_cr3, 7122 .set_tdp_cr3 = set_tdp_cr3,