mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] ACPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead()
@ 2021-03-24 15:22 Vitaly Kuznetsov
  2021-03-24 15:37 ` Rafael J. Wysocki
  0 siblings, 1 reply; 3+ messages in thread
From: Vitaly Kuznetsov @ 2021-03-24 15:22 UTC (permalink / raw)
  To: linux-acpi, x86
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Rafael J. Wysocki, Len Brown, Peter Zijlstra (Intel),
	Al Stone, Zhang Rui, linux-kernel

Commit 496121c02127 ("ACPI: processor: idle: Allow probing on platforms
with one ACPI C-state") broke CPU0 hotplug on certain systems, e.g.
I'm observing the following on AWS Nitro (e.g r5b.xlarge but other
instance types are affected as well):

 # echo 0 > /sys/devices/system/cpu/cpu0/online
 # echo 1 > /sys/devices/system/cpu/cpu0/online
 <10 seconds delay>
 -bash: echo: write error: Input/output error

In fact, the above mentioned commit only revealed the problem and did
not introduce it. On x86, to wakeup CPU an NMI is being used and
hlt_play_dead()/mwait_play_dead() loops are prepared to handle it:

	/*
	 * If NMI wants to wake up CPU0, start CPU0.
	 */
	if (wakeup_cpu0())
		start_cpu0();

cpuidle_play_dead() -> acpi_idle_play_dead() (which is now being called on
systems where it wasn't called before the above mentioned commit) serves
the same purpose but it doesn't have a path for CPU0. What happens now on
wakeup is:
- NMI is sent to CPU0
- wakeup_cpu0_nmi() works as expected
- we get back to while (1) loop in acpi_idle_play_dead()
- safe_halt() puts CPU0 to sleep again.

The straightforward/minimal fix is add the special handling for CPU0 on x86
and that's what the patch is doing.

Fixes: 496121c02127 ("ACPI: processor: idle: Allow probing on platforms with one ACPI C-state")
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
---
 arch/x86/include/asm/smp.h    | 1 +
 arch/x86/kernel/smpboot.c     | 2 +-
 drivers/acpi/processor_idle.c | 7 +++++++
 3 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index c0538f82c9a2..57ef2094af93 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -132,6 +132,7 @@ void native_play_dead(void);
 void play_dead_common(void);
 void wbinvd_on_cpu(int cpu);
 int wbinvd_on_all_cpus(void);
+bool wakeup_cpu0(void);
 
 void native_smp_send_reschedule(int cpu);
 void native_send_call_func_ipi(const struct cpumask *mask);
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 02813a7f3a7c..f877150a91da 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -1659,7 +1659,7 @@ void play_dead_common(void)
 	local_irq_disable();
 }
 
-static bool wakeup_cpu0(void)
+bool wakeup_cpu0(void)
 {
 	if (smp_processor_id() == 0 && enable_start_cpu0)
 		return true;
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index d93e400940a3..eb1101b16c08 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -29,6 +29,7 @@
  */
 #ifdef CONFIG_X86
 #include <asm/apic.h>
+#include <asm/cpu.h>
 #endif
 
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
@@ -541,6 +542,12 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
 			wait_for_freeze();
 		} else
 			return -ENODEV;
+
+#ifdef CONFIG_X86
+		/* If NMI wants to wake up CPU0, start CPU0. */
+		if (wakeup_cpu0())
+			start_cpu0();
+#endif
 	}
 
 	/* Never reached */
-- 
2.30.2


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

* Re: [PATCH] ACPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead()
  2021-03-24 15:22 [PATCH] ACPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead() Vitaly Kuznetsov
@ 2021-03-24 15:37 ` Rafael J. Wysocki
  2021-03-29 17:37   ` Rafael J. Wysocki
  0 siblings, 1 reply; 3+ messages in thread
From: Rafael J. Wysocki @ 2021-03-24 15:37 UTC (permalink / raw)
  To: Vitaly Kuznetsov
  Cc: ACPI Devel Maling List, the arch/x86 maintainers,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, H. Peter Anvin,
	Rafael J. Wysocki, Len Brown, Peter Zijlstra (Intel),
	Al Stone, Zhang Rui, Linux Kernel Mailing List

On Wed, Mar 24, 2021 at 4:23 PM Vitaly Kuznetsov <vkuznets@redhat.com> wrote:
>
> Commit 496121c02127 ("ACPI: processor: idle: Allow probing on platforms
> with one ACPI C-state") broke CPU0 hotplug on certain systems, e.g.
> I'm observing the following on AWS Nitro (e.g r5b.xlarge but other
> instance types are affected as well):
>
>  # echo 0 > /sys/devices/system/cpu/cpu0/online
>  # echo 1 > /sys/devices/system/cpu/cpu0/online
>  <10 seconds delay>
>  -bash: echo: write error: Input/output error
>
> In fact, the above mentioned commit only revealed the problem and did
> not introduce it. On x86, to wakeup CPU an NMI is being used and
> hlt_play_dead()/mwait_play_dead() loops are prepared to handle it:
>
>         /*
>          * If NMI wants to wake up CPU0, start CPU0.
>          */
>         if (wakeup_cpu0())
>                 start_cpu0();
>
> cpuidle_play_dead() -> acpi_idle_play_dead() (which is now being called on
> systems where it wasn't called before the above mentioned commit) serves
> the same purpose but it doesn't have a path for CPU0. What happens now on
> wakeup is:
> - NMI is sent to CPU0
> - wakeup_cpu0_nmi() works as expected
> - we get back to while (1) loop in acpi_idle_play_dead()
> - safe_halt() puts CPU0 to sleep again.
>
> The straightforward/minimal fix is add the special handling for CPU0 on x86
> and that's what the patch is doing.
>
> Fixes: 496121c02127 ("ACPI: processor: idle: Allow probing on platforms with one ACPI C-state")
> Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>

This looks reasonable to me, but I'll give others some time to respond.

> ---
>  arch/x86/include/asm/smp.h    | 1 +
>  arch/x86/kernel/smpboot.c     | 2 +-
>  drivers/acpi/processor_idle.c | 7 +++++++
>  3 files changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
> index c0538f82c9a2..57ef2094af93 100644
> --- a/arch/x86/include/asm/smp.h
> +++ b/arch/x86/include/asm/smp.h
> @@ -132,6 +132,7 @@ void native_play_dead(void);
>  void play_dead_common(void);
>  void wbinvd_on_cpu(int cpu);
>  int wbinvd_on_all_cpus(void);
> +bool wakeup_cpu0(void);
>
>  void native_smp_send_reschedule(int cpu);
>  void native_send_call_func_ipi(const struct cpumask *mask);
> diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> index 02813a7f3a7c..f877150a91da 100644
> --- a/arch/x86/kernel/smpboot.c
> +++ b/arch/x86/kernel/smpboot.c
> @@ -1659,7 +1659,7 @@ void play_dead_common(void)
>         local_irq_disable();
>  }
>
> -static bool wakeup_cpu0(void)
> +bool wakeup_cpu0(void)
>  {
>         if (smp_processor_id() == 0 && enable_start_cpu0)
>                 return true;
> diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> index d93e400940a3..eb1101b16c08 100644
> --- a/drivers/acpi/processor_idle.c
> +++ b/drivers/acpi/processor_idle.c
> @@ -29,6 +29,7 @@
>   */
>  #ifdef CONFIG_X86
>  #include <asm/apic.h>
> +#include <asm/cpu.h>
>  #endif
>
>  #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
> @@ -541,6 +542,12 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
>                         wait_for_freeze();
>                 } else
>                         return -ENODEV;
> +
> +#ifdef CONFIG_X86
> +               /* If NMI wants to wake up CPU0, start CPU0. */
> +               if (wakeup_cpu0())
> +                       start_cpu0();
> +#endif
>         }
>
>         /* Never reached */
> --
> 2.30.2
>

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

* Re: [PATCH] ACPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead()
  2021-03-24 15:37 ` Rafael J. Wysocki
@ 2021-03-29 17:37   ` Rafael J. Wysocki
  0 siblings, 0 replies; 3+ messages in thread
From: Rafael J. Wysocki @ 2021-03-29 17:37 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Vitaly Kuznetsov, ACPI Devel Maling List,
	the arch/x86 maintainers, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, H. Peter Anvin, Rafael J. Wysocki, Len Brown,
	Peter Zijlstra (Intel),
	Al Stone, Zhang Rui, Linux Kernel Mailing List

On Wed, Mar 24, 2021 at 4:37 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Wed, Mar 24, 2021 at 4:23 PM Vitaly Kuznetsov <vkuznets@redhat.com> wrote:
> >
> > Commit 496121c02127 ("ACPI: processor: idle: Allow probing on platforms
> > with one ACPI C-state") broke CPU0 hotplug on certain systems, e.g.
> > I'm observing the following on AWS Nitro (e.g r5b.xlarge but other
> > instance types are affected as well):
> >
> >  # echo 0 > /sys/devices/system/cpu/cpu0/online
> >  # echo 1 > /sys/devices/system/cpu/cpu0/online
> >  <10 seconds delay>
> >  -bash: echo: write error: Input/output error
> >
> > In fact, the above mentioned commit only revealed the problem and did
> > not introduce it. On x86, to wakeup CPU an NMI is being used and
> > hlt_play_dead()/mwait_play_dead() loops are prepared to handle it:
> >
> >         /*
> >          * If NMI wants to wake up CPU0, start CPU0.
> >          */
> >         if (wakeup_cpu0())
> >                 start_cpu0();
> >
> > cpuidle_play_dead() -> acpi_idle_play_dead() (which is now being called on
> > systems where it wasn't called before the above mentioned commit) serves
> > the same purpose but it doesn't have a path for CPU0. What happens now on
> > wakeup is:
> > - NMI is sent to CPU0
> > - wakeup_cpu0_nmi() works as expected
> > - we get back to while (1) loop in acpi_idle_play_dead()
> > - safe_halt() puts CPU0 to sleep again.
> >
> > The straightforward/minimal fix is add the special handling for CPU0 on x86
> > and that's what the patch is doing.
> >
> > Fixes: 496121c02127 ("ACPI: processor: idle: Allow probing on platforms with one ACPI C-state")
> > Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
>
> This looks reasonable to me, but I'll give others some time to respond.

No comments, so applied as 5.12-rc material, thanks!

> > ---
> >  arch/x86/include/asm/smp.h    | 1 +
> >  arch/x86/kernel/smpboot.c     | 2 +-
> >  drivers/acpi/processor_idle.c | 7 +++++++
> >  3 files changed, 9 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
> > index c0538f82c9a2..57ef2094af93 100644
> > --- a/arch/x86/include/asm/smp.h
> > +++ b/arch/x86/include/asm/smp.h
> > @@ -132,6 +132,7 @@ void native_play_dead(void);
> >  void play_dead_common(void);
> >  void wbinvd_on_cpu(int cpu);
> >  int wbinvd_on_all_cpus(void);
> > +bool wakeup_cpu0(void);
> >
> >  void native_smp_send_reschedule(int cpu);
> >  void native_send_call_func_ipi(const struct cpumask *mask);
> > diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
> > index 02813a7f3a7c..f877150a91da 100644
> > --- a/arch/x86/kernel/smpboot.c
> > +++ b/arch/x86/kernel/smpboot.c
> > @@ -1659,7 +1659,7 @@ void play_dead_common(void)
> >         local_irq_disable();
> >  }
> >
> > -static bool wakeup_cpu0(void)
> > +bool wakeup_cpu0(void)
> >  {
> >         if (smp_processor_id() == 0 && enable_start_cpu0)
> >                 return true;
> > diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
> > index d93e400940a3..eb1101b16c08 100644
> > --- a/drivers/acpi/processor_idle.c
> > +++ b/drivers/acpi/processor_idle.c
> > @@ -29,6 +29,7 @@
> >   */
> >  #ifdef CONFIG_X86
> >  #include <asm/apic.h>
> > +#include <asm/cpu.h>
> >  #endif
> >
> >  #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
> > @@ -541,6 +542,12 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
> >                         wait_for_freeze();
> >                 } else
> >                         return -ENODEV;
> > +
> > +#ifdef CONFIG_X86
> > +               /* If NMI wants to wake up CPU0, start CPU0. */
> > +               if (wakeup_cpu0())
> > +                       start_cpu0();
> > +#endif
> >         }
> >
> >         /* Never reached */
> > --
> > 2.30.2
> >

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

end of thread, other threads:[~2021-03-29 17:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-24 15:22 [PATCH] ACPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead() Vitaly Kuznetsov
2021-03-24 15:37 ` Rafael J. Wysocki
2021-03-29 17:37   ` Rafael J. Wysocki

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

all inboxes | Powered by JetHome®