Re: [PATCH v3 10/12] KVM: VMX: Set the TSC offset and multiplier on nested entry and exit

From: Sean Christopherson
Date: Tue May 25 2021 - 12:06:10 EST


"KVM: nVMX:" for the scope.

The shortlog is also a bit confusing. I usually think of "set == write", i.e.
I expected VMWRITEs in the diff. The nested_vmx_vmexit() case in particular is
gnarly because the actual VMWRITEs aren't captured in the diff's context.

What about combining this with the next patch that exposes the feature to L1?
E.g. "KVM: nVMX: Enable nested TSC scaling" or so.

That would avoid bikeshedding the meaning of "set", fix the goof in the next patch's
shortlog (KVM exposes the feature to L1, not L2), and eliminate an unnecessary
patch for bisection purposes. Bisecting to a patch that exposes the feature but
doesn't introduce any actual functionality isn't all that helpful, e.g. if there
is a bug in _this_ patch then bisection will arguably point at the wrong patch.

On Fri, May 21, 2021, Ilias Stamatis wrote:
> Calculate the nested TSC offset and multiplier on entering L2 using the
> corresponding functions. Restore the L1 values on L2's exit.
>
> Signed-off-by: Ilias Stamatis <ilstam@xxxxxxxxxx>
> ---
> arch/x86/kvm/vmx/nested.c | 18 ++++++++++++++----
> 1 file changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
> index 239154d3e4e7..f75c4174cbcf 100644
> --- a/arch/x86/kvm/vmx/nested.c
> +++ b/arch/x86/kvm/vmx/nested.c
> @@ -2532,6 +2532,15 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
> vmcs_write64(GUEST_IA32_PAT, vmx->vcpu.arch.pat);
> }
>
> + vcpu->arch.tsc_offset = kvm_calc_nested_tsc_offset(
> + vcpu->arch.l1_tsc_offset,
> + vmx_get_l2_tsc_offset(vcpu),
> + vmx_get_l2_tsc_multiplier(vcpu));
> +
> + vcpu->arch.tsc_scaling_ratio = kvm_calc_nested_tsc_multiplier(
> + vcpu->arch.l1_tsc_scaling_ratio,
> + vmx_get_l2_tsc_multiplier(vcpu));
> +
> vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);
> if (kvm_has_tsc_control)
> vmcs_write64(TSC_MULTIPLIER, vcpu->arch.tsc_scaling_ratio);
> @@ -3353,8 +3362,6 @@ enum nvmx_vmentry_status nested_vmx_enter_non_root_mode(struct kvm_vcpu *vcpu,
> }
>
> enter_guest_mode(vcpu);
> - if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING)
> - vcpu->arch.tsc_offset += vmcs12->tsc_offset;
>
> if (prepare_vmcs02(vcpu, vmcs12, &entry_failure_code)) {
> exit_reason.basic = EXIT_REASON_INVALID_STATE;
> @@ -4462,8 +4469,11 @@ void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
> if (nested_cpu_has_preemption_timer(vmcs12))
> hrtimer_cancel(&to_vmx(vcpu)->nested.preemption_timer);
>
> - if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETTING)
> - vcpu->arch.tsc_offset -= vmcs12->tsc_offset;
> + if (nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETTING)) {
> + vcpu->arch.tsc_offset = vcpu->arch.l1_tsc_offset;
> + if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_TSC_SCALING))
> + vcpu->arch.tsc_scaling_ratio = vcpu->arch.l1_tsc_scaling_ratio;
> + }
>
> if (likely(!vmx->fail)) {
> sync_vmcs02_to_vmcs12(vcpu, vmcs12);
> --
> 2.17.1
>