On Thu, 2021-05-06 at 10:32 +0000, ilstam@xxxxxxxxxxx wrote: > From: Ilias Stamatis <ilstam@xxxxxxxxxx> > > Calculating the current TSC offset is done differently when nested TSC > scaling is used. > > Signed-off-by: Ilias Stamatis <ilstam@xxxxxxxxxx> > --- > arch/x86/kvm/vmx/vmx.c | 26 ++++++++++++++++++++------ > 1 file changed, 20 insertions(+), 6 deletions(-) > > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index 49241423b854..df7dc0e4c903 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -1797,10 +1797,16 @@ static void setup_msrs(struct vcpu_vmx *vmx) > vmx_update_msr_bitmap(&vmx->vcpu); > } > > -static u64 vmx_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) > +/* > + * This function receives the requested offset for L1 as an argument but it > + * actually writes the "current" tsc offset to the VMCS and returns it. The > + * current offset might be different in case an L2 guest is currently running > + * and its VMCS02 is loaded. > + */ (Not related to this patch) It might be a good idea to rename this callback instead of this comment, but I am not sure about it. > +static u64 vmx_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 l1_offset) > { > struct vmcs12 *vmcs12 = get_vmcs12(vcpu); > - u64 g_tsc_offset = 0; > + u64 cur_offset = l1_offset; > > /* > * We're here if L1 chose not to trap WRMSR to TSC. According > @@ -1809,11 +1815,19 @@ static u64 vmx_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) > * to the newly set TSC to get L2's TSC. > */ > if (is_guest_mode(vcpu) && > - (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING)) > - g_tsc_offset = vmcs12->tsc_offset; > + (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING)) { > + if (vmcs12->secondary_vm_exec_control & SECONDARY_EXEC_TSC_SCALING) { > + cur_offset = kvm_compute_02_tsc_offset( > + l1_offset, > + vmcs12->tsc_multiplier, > + vmcs12->tsc_offset); > + } else { > + cur_offset = l1_offset + vmcs12->tsc_offset; > + } > + } > > - vmcs_write64(TSC_OFFSET, offset + g_tsc_offset); > - return offset + g_tsc_offset; > + vmcs_write64(TSC_OFFSET, cur_offset); > + return cur_offset; > } > > /* This code would be ideal to move to common code as SVM will do basically the same thing. Doesn't have to be done now though. Best regards, Maxim Levitsky