Message ID | 20210521102449.21505-5-ilstam@amazon.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: Implement nested TSC scaling | expand |
On 21/05/21 12:24, Ilias Stamatis wrote: > @@ -3537,10 +3539,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > * return L1's TSC value to ensure backwards-compatible > * behavior for migration. > */ > - u64 tsc_offset = msr_info->host_initiated ? vcpu->arch.l1_tsc_offset : > - vcpu->arch.tsc_offset; > - > - msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + tsc_offset; > + if (msr_info->host_initiated) > + msr_info->data = kvm_scale_tsc( > + vcpu, rdtsc(), vcpu->arch.l1_tsc_scaling_ratio > + ) + vcpu->arch.l1_tsc_offset; Better indentation: msr_info->data = vcpu->arch.l1_tsc_offset + kvm_scale_tsc(vcpu, rdtsc(), vcpu->arch.tsc_scaling_ratio); Same below. Paolo > + else > + msr_info->data = kvm_scale_tsc( > + vcpu, rdtsc(), vcpu->arch.tsc_scaling_ratio > + ) + vcpu->arch.tsc_offset; > break; > } > case MSR_MTRRcap: >
On Mon, May 24, 2021, Paolo Bonzini wrote: > On 21/05/21 12:24, Ilias Stamatis wrote: > > @@ -3537,10 +3539,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > > * return L1's TSC value to ensure backwards-compatible > > * behavior for migration. > > */ > > - u64 tsc_offset = msr_info->host_initiated ? vcpu->arch.l1_tsc_offset : > > - vcpu->arch.tsc_offset; > > - > > - msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + tsc_offset; > > + if (msr_info->host_initiated) > > + msr_info->data = kvm_scale_tsc( > > + vcpu, rdtsc(), vcpu->arch.l1_tsc_scaling_ratio > > + ) + vcpu->arch.l1_tsc_offset; > > Better indentation: > > msr_info->data = vcpu->arch.l1_tsc_offset + > kvm_scale_tsc(vcpu, rdtsc(), I like this more, but it's still a bit ugly. > vcpu->arch.tsc_scaling_ratio); Wrong pairing of ratio and offset (not necessarily what you queued, obviously). > > Same below. Alternatively, what about something like this? u64 offset, ratio; if (msr_info->host_initiated) { offset = vcpu->arch.l1_tsc_offset; ratio = vcpu->arch.l1_tsc_scaling_ratio; } else { offset = vcpu->arch.tsc_offset; ratio = vcpu->arch.tsc_scaling_ratio; } msr_info->data = kvm_scale_tsc(vcpu, rdtsc(), ratio) + offset; or an option that would require additional refactoring: struct kvm_guest_tsc *tsc; tsc = msr_info->host_initiated ? &vcpu->arch.l1_tsc : &vcpu->arch.current_tsc; msr_info->data = tsc->offset + kvm_scale_tsc(vcpu, rdtsc(), tsc->scaling_ratio); > > Paolo > > > + else > > + msr_info->data = kvm_scale_tsc( > > + vcpu, rdtsc(), vcpu->arch.tsc_scaling_ratio > > + ) + vcpu->arch.tsc_offset; > > break; > > } > > case MSR_MTRRcap: > > >
On 24/05/21 17:48, Sean Christopherson wrote: > > if (msr_info->host_initiated) { > offset = vcpu->arch.l1_tsc_offset; > ratio = vcpu->arch.l1_tsc_scaling_ratio; > } else { > offset = vcpu->arch.tsc_offset; > ratio = vcpu->arch.tsc_scaling_ratio; > } > msr_info->data = kvm_scale_tsc(vcpu, rdtsc(), ratio) + offset; Looks good, indeed I didn't do this just out of laziness really (and instead got a typo). Paolo
On Mon, 2021-05-24 at 16:23 +0200, Paolo Bonzini wrote: > On 21/05/21 12:24, Ilias Stamatis wrote: > > @@ -3537,10 +3539,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > > * return L1's TSC value to ensure backwards-compatible > > * behavior for migration. > > */ > > - u64 tsc_offset = msr_info->host_initiated ? vcpu->arch.l1_tsc_offset : > > - vcpu->arch.tsc_offset; > > - > > - msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + tsc_offset; > > + if (msr_info->host_initiated) > > + msr_info->data = kvm_scale_tsc( > > + vcpu, rdtsc(), vcpu->arch.l1_tsc_scaling_ratio > > + ) + vcpu->arch.l1_tsc_offset; > > Better indentation: > > msr_info->data = vcpu->arch.l1_tsc_offset + > kvm_scale_tsc(vcpu, rdtsc(), > vcpu->arch.tsc_scaling_ratio); Good idea IMHO. Other than that: Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> > > Same below. > > Paolo > > > + else > > + msr_info->data = kvm_scale_tsc( > > + vcpu, rdtsc(), vcpu->arch.tsc_scaling_ratio > > + ) + vcpu->arch.tsc_offset; > > break; > > } > > case MSR_MTRRcap: > >
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 7dfc609eacd6..b14c2b2b2e21 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1788,7 +1788,7 @@ static inline bool kvm_is_supported_user_return_msr(u32 msr) return kvm_find_user_return_msr(msr) >= 0; } -u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc); +u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc, u64 ratio); u64 kvm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc); unsigned long kvm_get_linear_rip(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ac644a1c3285..fdcb4f46a003 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2307,10 +2307,9 @@ static inline u64 __scale_tsc(u64 ratio, u64 tsc) return mul_u64_u64_shr(tsc, ratio, kvm_tsc_scaling_ratio_frac_bits); } -u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc) +u64 kvm_scale_tsc(struct kvm_vcpu *vcpu, u64 tsc, u64 ratio) { u64 _tsc = tsc; - u64 ratio = vcpu->arch.tsc_scaling_ratio; if (ratio != kvm_default_tsc_scaling_ratio) _tsc = __scale_tsc(ratio, tsc); @@ -2323,14 +2322,15 @@ static u64 kvm_compute_tsc_offset_l1(struct kvm_vcpu *vcpu, u64 target_tsc) { u64 tsc; - tsc = kvm_scale_tsc(vcpu, rdtsc()); + tsc = kvm_scale_tsc(vcpu, rdtsc(), vcpu->arch.l1_tsc_scaling_ratio); return target_tsc - tsc; } u64 kvm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc) { - return vcpu->arch.l1_tsc_offset + kvm_scale_tsc(vcpu, host_tsc); + return vcpu->arch.l1_tsc_offset + + kvm_scale_tsc(vcpu, host_tsc, vcpu->arch.l1_tsc_scaling_ratio); } EXPORT_SYMBOL_GPL(kvm_read_l1_tsc); @@ -2463,7 +2463,8 @@ static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment) { if (vcpu->arch.l1_tsc_scaling_ratio != kvm_default_tsc_scaling_ratio) WARN_ON(adjustment < 0); - adjustment = kvm_scale_tsc(vcpu, (u64) adjustment); + adjustment = kvm_scale_tsc(vcpu, (u64) adjustment, + vcpu->arch.l1_tsc_scaling_ratio); adjust_tsc_offset_guest(vcpu, adjustment); } @@ -2846,7 +2847,8 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) /* With all the info we got, fill in the values */ if (kvm_has_tsc_control) - tgt_tsc_khz = kvm_scale_tsc(v, tgt_tsc_khz); + tgt_tsc_khz = kvm_scale_tsc(v, tgt_tsc_khz, + v->arch.l1_tsc_scaling_ratio); if (unlikely(vcpu->hw_tsc_khz != tgt_tsc_khz)) { kvm_get_time_scale(NSEC_PER_SEC, tgt_tsc_khz * 1000LL, @@ -3537,10 +3539,14 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) * return L1's TSC value to ensure backwards-compatible * behavior for migration. */ - u64 tsc_offset = msr_info->host_initiated ? vcpu->arch.l1_tsc_offset : - vcpu->arch.tsc_offset; - - msr_info->data = kvm_scale_tsc(vcpu, rdtsc()) + tsc_offset; + if (msr_info->host_initiated) + msr_info->data = kvm_scale_tsc( + vcpu, rdtsc(), vcpu->arch.l1_tsc_scaling_ratio + ) + vcpu->arch.l1_tsc_offset; + else + msr_info->data = kvm_scale_tsc( + vcpu, rdtsc(), vcpu->arch.tsc_scaling_ratio + ) + vcpu->arch.tsc_offset; break; } case MSR_MTRRcap:
Sometimes kvm_scale_tsc() needs to use the current scaling ratio and other times (like when reading the TSC from user space) it needs to use L1's scaling ratio. Have the caller specify this by passing the ratio as a parameter. Signed-off-by: Ilias Stamatis <ilstam@amazon.com> --- arch/x86/include/asm/kvm_host.h | 2 +- arch/x86/kvm/x86.c | 26 ++++++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-)