Re: [PATCHv2 04/13] x86/kvm: Do not try to disable kvmclock if it was not enabled

From: Sean Christopherson
Date: Fri Oct 20 2023 - 13:07:41 EST


On Fri, Oct 20, 2023, Vitaly Kuznetsov wrote:
> > ---
> > arch/x86/kernel/kvmclock.c | 12 ++++++++----
> > 1 file changed, 8 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
> > index fb8f52149be9..f2fff625576d 100644
> > --- a/arch/x86/kernel/kvmclock.c
> > +++ b/arch/x86/kernel/kvmclock.c
> > @@ -24,8 +24,8 @@
> >
> > static int kvmclock __initdata = 1;
> > static int kvmclock_vsyscall __initdata = 1;
> > -static int msr_kvm_system_time __ro_after_init = MSR_KVM_SYSTEM_TIME;
> > -static int msr_kvm_wall_clock __ro_after_init = MSR_KVM_WALL_CLOCK;
> > +static int msr_kvm_system_time __ro_after_init;
> > +static int msr_kvm_wall_clock __ro_after_init;
> > static u64 kvm_sched_clock_offset __ro_after_init;
> >
> > static int __init parse_no_kvmclock(char *arg)
> > @@ -195,7 +195,8 @@ static void kvm_setup_secondary_clock(void)
> >
> > void kvmclock_disable(void)
> > {
> > - native_write_msr(msr_kvm_system_time, 0, 0);
> > + if (msr_kvm_system_time)
> > + native_write_msr(msr_kvm_system_time, 0, 0);
> > }
> >
> > static void __init kvmclock_init_mem(void)
> > @@ -294,7 +295,10 @@ void __init kvmclock_init(void)
> > if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE2)) {
> > msr_kvm_system_time = MSR_KVM_SYSTEM_TIME_NEW;
> > msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK_NEW;
> > - } else if (!kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {
> > + } else if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE)) {
> > + msr_kvm_system_time = MSR_KVM_SYSTEM_TIME;
> > + msr_kvm_wall_clock = MSR_KVM_WALL_CLOCK;
> > + } else {
> > return;
> > }
>
> This should work, so
>
> Reviewed-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx>
>
> but my personal preference would be to change kvm_guest_cpu_offline()
> to check KVM features explicitly instead of checking MSRs against '0'
> at least becase it already does so for other features. Completely
> untested:
>
> diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> index b8ab9ee5896c..1ee49c98e70a 100644
> --- a/arch/x86/kernel/kvm.c
> +++ b/arch/x86/kernel/kvm.c
> @@ -454,7 +454,9 @@ static void kvm_guest_cpu_offline(bool shutdown)
> kvm_pv_disable_apf();
> if (!shutdown)
> apf_task_wake_all();
> - kvmclock_disable();
> + if (kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE2) ||
> + kvm_para_has_feature(KVM_FEATURE_CLOCKSOURCE))
> + kvmclock_disable();
> }

That would result in an unnecessray WRMSR in the case where kvmclock is disabled
on the command line. It _should_ be benign given how the code is written, but
it's not impossible to imagine a scenario where someone disabled kvmclock in the
guest because of a hypervisor bug. And the WRMSR would become a bogus write to
MSR 0x0 if someone made a "cleanup" to set msr_kvm_system_time if and only if
kvmclock is actually used, e.g. if someone made Kirill's change sans the check in
kvmclock_disable().