public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [bug report] KVM: x86: Unify TSC logic (sleeping in atomic?)
@ 2025-01-17  6:08 Dan Carpenter
  2025-01-17 17:51 ` Sean Christopherson
  0 siblings, 1 reply; 5+ messages in thread
From: Dan Carpenter @ 2025-01-17  6:08 UTC (permalink / raw)
  To: kvm

I don't know why I'm seeing this static checker warning only now.  All
this code looks to be about 15 years old...

Commit e48672fa25e8 ("KVM: x86: Unify TSC logic") from Aug 19, 2010
(linux-next), leads to the following Smatch static checker warning:

	arch/x86/kernel/tsc.c:1214 mark_tsc_unstable()
	warn: sleeping in atomic context

The code path is:

vcpu_load() <- disables preempt
-> kvm_arch_vcpu_load()
   -> mark_tsc_unstable() <- sleeps

virt/kvm/kvm_main.c
   166  void vcpu_load(struct kvm_vcpu *vcpu)
   167  {
   168          int cpu = get_cpu();
                          ^^^^^^^^^^
This get_cpu() disables preemption.

   169  
   170          __this_cpu_write(kvm_running_vcpu, vcpu);
   171          preempt_notifier_register(&vcpu->preempt_notifier);
   172          kvm_arch_vcpu_load(vcpu, cpu);
   173          put_cpu();
   174  }

arch/x86/kvm/x86.c
  4979          if (unlikely(vcpu->cpu != cpu) || kvm_check_tsc_unstable()) {
  4980                  s64 tsc_delta = !vcpu->arch.last_host_tsc ? 0 :
  4981                                  rdtsc() - vcpu->arch.last_host_tsc;
  4982                  if (tsc_delta < 0)
  4983                          mark_tsc_unstable("KVM discovered backwards TSC");
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It seems pretty unlikely that we'll get a backwards tsc.  I remember
dealing with some of these seeing this 20 years ago.

  4984  

arch/x86/kernel/tsc.c
    1206 void mark_tsc_unstable(char *reason)
    1207 {
    1208         if (tsc_unstable)
    1209                 return;
    1210 
    1211         tsc_unstable = 1;
    1212         if (using_native_sched_clock())
    1213                 clear_sched_clock_stable();
--> 1214         disable_sched_clock_irqtime();
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I'm on an allmodconfig on x86_64 so this expands to the
function below...

    1215         pr_info("Marking TSC unstable due to %s\n", reason);
    1216 
    1217         clocksource_mark_unstable(&clocksource_tsc_early);
    1218         clocksource_mark_unstable(&clocksource_tsc);
    1219 }

kernel/jump_label.c
   245  void static_key_disable(struct static_key *key)
   246  {
   247          cpus_read_lock();
                ^^^^^^^^^^^^^^^^
This lock has a might_sleep() in it which triggers the static checker
warning.

   248          static_key_disable_cpuslocked(key);
   249          cpus_read_unlock();
   250  }

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug report] KVM: x86: Unify TSC logic (sleeping in atomic?)
  2025-01-17  6:08 [bug report] KVM: x86: Unify TSC logic (sleeping in atomic?) Dan Carpenter
@ 2025-01-17 17:51 ` Sean Christopherson
  2025-01-24 10:34   ` Michal Koutný
  0 siblings, 1 reply; 5+ messages in thread
From: Sean Christopherson @ 2025-01-17 17:51 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: kvm, Yafang Shao, Peter Zijlstra, Michal Koutný,
	Vincent Guittot

+sched folks

On Fri, Jan 17, 2025, Dan Carpenter wrote:
> I don't know why I'm seeing this static checker warning only now.  All
> this code looks to be about 15 years old...
> 
> Commit e48672fa25e8 ("KVM: x86: Unify TSC logic") from Aug 19, 2010
> (linux-next), leads to the following Smatch static checker warning:

That's not the problematic commit.  This popped because commit 8722903cbb8f
("sched: Define sched_clock_irqtime as static key") in the tip tree turned
sched_clock_irqtime into a static key (it was a simple "int").

https://lore.kernel.org/all/20250103022409.2544-2-laoar.shao@gmail.com

> 	arch/x86/kernel/tsc.c:1214 mark_tsc_unstable()
> 	warn: sleeping in atomic context
> 
> The code path is:
> 
> vcpu_load() <- disables preempt
> -> kvm_arch_vcpu_load()
>    -> mark_tsc_unstable() <- sleeps
> 
> virt/kvm/kvm_main.c
>    166  void vcpu_load(struct kvm_vcpu *vcpu)
>    167  {
>    168          int cpu = get_cpu();
>                           ^^^^^^^^^^
> This get_cpu() disables preemption.
> 
>    169  
>    170          __this_cpu_write(kvm_running_vcpu, vcpu);
>    171          preempt_notifier_register(&vcpu->preempt_notifier);
>    172          kvm_arch_vcpu_load(vcpu, cpu);
>    173          put_cpu();
>    174  }
> 
> arch/x86/kvm/x86.c
>   4979          if (unlikely(vcpu->cpu != cpu) || kvm_check_tsc_unstable()) {
>   4980                  s64 tsc_delta = !vcpu->arch.last_host_tsc ? 0 :
>   4981                                  rdtsc() - vcpu->arch.last_host_tsc;
>   4982                  if (tsc_delta < 0)
>   4983                          mark_tsc_unstable("KVM discovered backwards TSC");
>                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> It seems pretty unlikely that we'll get a backwards tsc.

TSC will go "backwards" if the host is suspended, in which case host TSC gets
reset to 0.

>     1215         pr_info("Marking TSC unstable due to %s\n", reason);
>     1216 
>     1217         clocksource_mark_unstable(&clocksource_tsc_early);
>     1218         clocksource_mark_unstable(&clocksource_tsc);
>     1219 }
> 
> kernel/jump_label.c
>    245  void static_key_disable(struct static_key *key)
>    246  {
>    247          cpus_read_lock();
>                 ^^^^^^^^^^^^^^^^
> This lock has a might_sleep() in it which triggers the static checker
> warning.
> 
>    248          static_key_disable_cpuslocked(key);
>    249          cpus_read_unlock();
>    250  }
> 
> regards,
> dan carpenter

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug report] KVM: x86: Unify TSC logic (sleeping in atomic?)
  2025-01-17 17:51 ` Sean Christopherson
@ 2025-01-24 10:34   ` Michal Koutný
  2025-01-24 15:36     ` Sean Christopherson
  0 siblings, 1 reply; 5+ messages in thread
From: Michal Koutný @ 2025-01-24 10:34 UTC (permalink / raw)
  To: Sean Christopherson, Yafang Shao
  Cc: Dan Carpenter, kvm, Peter Zijlstra, Vincent Guittot

[-- Attachment #1: Type: text/plain, Size: 1136 bytes --]

On Fri, Jan 17, 2025 at 09:51:41AM -0800, Sean Christopherson <seanjc@google.com> wrote:
> That's not the problematic commit.  This popped because commit 8722903cbb8f
> ("sched: Define sched_clock_irqtime as static key") in the tip tree turned
> sched_clock_irqtime into a static key (it was a simple "int").
> 
> https://lore.kernel.org/all/20250103022409.2544-2-laoar.shao@gmail.com

Thanks for the analysis, it's spot on. What a bad luck.

Is there a precedent for static key switching in non-preemptible
contexts?

More generally, why does KVM do this tsc check in vcpu_load? Shouldn't
possible unstability for that cpu be already checked and decided at boot
(regardless of KVM)? (Unless unstability itself is not stable property.
Which means any previously measured IRQ times are skewed.)

(Or a third option to revert the static-keyness if Yafang doesn't have
some backing data that it improves generic performance. The robot [1]
didn't like the fourth patch but that one actually adds back the
complexity guarded previously.)

Michal

[1] https://lore.kernel.org/all/202501101033.b66070d2-lkp@intel.com/

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug report] KVM: x86: Unify TSC logic (sleeping in atomic?)
  2025-01-24 10:34   ` Michal Koutný
@ 2025-01-24 15:36     ` Sean Christopherson
  2025-01-26  2:16       ` Yafang Shao
  0 siblings, 1 reply; 5+ messages in thread
From: Sean Christopherson @ 2025-01-24 15:36 UTC (permalink / raw)
  To: Michal Koutný
  Cc: Yafang Shao, Dan Carpenter, kvm, Peter Zijlstra, Vincent Guittot

On Fri, Jan 24, 2025, Michal Koutný wrote:
> On Fri, Jan 17, 2025 at 09:51:41AM -0800, Sean Christopherson <seanjc@google.com> wrote:
> > That's not the problematic commit.  This popped because commit 8722903cbb8f
> > ("sched: Define sched_clock_irqtime as static key") in the tip tree turned
> > sched_clock_irqtime into a static key (it was a simple "int").
> > 
> > https://lore.kernel.org/all/20250103022409.2544-2-laoar.shao@gmail.com
> 
> Thanks for the analysis, it's spot on. What a bad luck.
> 
> Is there a precedent for static key switching in non-preemptible
> contexts?

Abuse static_key_deferred to push the patching to a workqueue?

> More generally, why does KVM do this tsc check in vcpu_load? 

The logic triggers when a vCPU migrates to a different pCPU.  The code detects
that the case where TSC is inconsistent between pCPUs, and would cause time to go
backwards from the guest's perspective.  E.g. TSC = X on CPU0, migrate to CPU1
where TSC = X - Y.

> Shouldn't possible unstability for that cpu be already checked and decided at
> boot (regardless of KVM)? (Unless unstability itself is not stable property.
> Which means any previously measured IRQ times are skewed.)

This isn't a problem that's unique to KVM.  The clocksource watchdog also marks
TSC unstable from non-preemptible context (presumably from IRQ context?)

  clocksource_watchdog()
  |
  -> spin_lock(&watchdog_lock);
     |
     -> __clocksource_unstable()
        |
        -> clocksource.mark_unstable() == tsc_cs_mark_unstable()
           |
           -> disable_sched_clock_irqtime()

Uh, and sched_clock_register() toggles the static key on with IRQs disabled...

	/* Cannot register a sched_clock with interrupts on */
	local_irq_save(flags);

	...

	/* Enable IRQ time accounting if we have a fast enough sched_clock() */
	if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
		enable_sched_clock_irqtime();

	local_irq_restore(flags);

> (Or a third option to revert the static-keyness if Yafang doesn't have

Given there are issues all over the place, either a revert or a generic fix.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [bug report] KVM: x86: Unify TSC logic (sleeping in atomic?)
  2025-01-24 15:36     ` Sean Christopherson
@ 2025-01-26  2:16       ` Yafang Shao
  0 siblings, 0 replies; 5+ messages in thread
From: Yafang Shao @ 2025-01-26  2:16 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Michal Koutný, Dan Carpenter, kvm, Peter Zijlstra,
	Vincent Guittot

On Fri, Jan 24, 2025 at 11:36 PM Sean Christopherson <seanjc@google.com> wrote:
>
> On Fri, Jan 24, 2025, Michal Koutný wrote:
> > On Fri, Jan 17, 2025 at 09:51:41AM -0800, Sean Christopherson <seanjc@google.com> wrote:
> > > That's not the problematic commit.  This popped because commit 8722903cbb8f
> > > ("sched: Define sched_clock_irqtime as static key") in the tip tree turned
> > > sched_clock_irqtime into a static key (it was a simple "int").
> > >
> > > https://lore.kernel.org/all/20250103022409.2544-2-laoar.shao@gmail.com
> >
> > Thanks for the analysis, it's spot on. What a bad luck.
> >
> > Is there a precedent for static key switching in non-preemptible
> > contexts?
>
> Abuse static_key_deferred to push the patching to a workqueue?
>
> > More generally, why does KVM do this tsc check in vcpu_load?
>
> The logic triggers when a vCPU migrates to a different pCPU.  The code detects
> that the case where TSC is inconsistent between pCPUs, and would cause time to go
> backwards from the guest's perspective.  E.g. TSC = X on CPU0, migrate to CPU1
> where TSC = X - Y.
>
> > Shouldn't possible unstability for that cpu be already checked and decided at
> > boot (regardless of KVM)? (Unless unstability itself is not stable property.
> > Which means any previously measured IRQ times are skewed.)
>
> This isn't a problem that's unique to KVM.  The clocksource watchdog also marks
> TSC unstable from non-preemptible context (presumably from IRQ context?)
>
>   clocksource_watchdog()
>   |
>   -> spin_lock(&watchdog_lock);
>      |
>      -> __clocksource_unstable()
>         |
>         -> clocksource.mark_unstable() == tsc_cs_mark_unstable()
>            |
>            -> disable_sched_clock_irqtime()
>
> Uh, and sched_clock_register() toggles the static key on with IRQs disabled...
>
>         /* Cannot register a sched_clock with interrupts on */
>         local_irq_save(flags);
>
>         ...
>
>         /* Enable IRQ time accounting if we have a fast enough sched_clock() */
>         if (irqtime > 0 || (irqtime == -1 && rate >= 1000000))
>                 enable_sched_clock_irqtime();
>
>         local_irq_restore(flags);
>
> > (Or a third option to revert the static-keyness if Yafang doesn't have
>
> Given there are issues all over the place, either a revert or a generic fix.

It seems that introducing a generic fix for this static key change
might not be worth it. I’ll proceed with sending a revert.


--
Regards
Yafang

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2025-01-26  2:17 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-17  6:08 [bug report] KVM: x86: Unify TSC logic (sleeping in atomic?) Dan Carpenter
2025-01-17 17:51 ` Sean Christopherson
2025-01-24 10:34   ` Michal Koutný
2025-01-24 15:36     ` Sean Christopherson
2025-01-26  2:16       ` Yafang Shao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox