On Sun, Dec 24, 2017 at 02:49:23AM +1000, Nicholas Piggin wrote:
> Platforms with a panic handler that halts the system can have problems
> getting kernel messages out, because the panic notifiers are called
> before kernel/panic.c does its flushing of printk buffers an console
> etc.
> 
> This was attempted to be solved with commit a3b2cb30f252 ("powerpc: Do
> not call ppc_md.panic in fadump panic notifier"), but that wasn't the
> right approach and caused other problems, and was reverted by commit
> ab9dbf771ff9.
> 
> Instead, the powernv shutdown paths have already had a similar
> problem, fixed by taking the message flushing sequence from
> kernel/panic.c. That's a little bit ugly, but while we have the code
> duplicated, it will work for this case as well. So have ppc panic
> handlers do the same flushing before they terminate.
> 
> Without this patch, a qemu pseries_le_defconfig guest stops silently
> when issued the nmi command when xmon is off and no crash dumpers
> enabled. Afterwards, an oops is printed by each CPU as expected.
> 
> Fixes: ab9dbf771ff9 ("Revert "powerpc: Do not call ppc_md.panic in fadump 
> panic notifier"")
> Signed-off-by: Nicholas Piggin <npig...@gmail.com>

Reviewed-by: David Gibson <da...@gibson.dropbear.id.au>

> ---
>  arch/powerpc/include/asm/bug.h         |  3 ++-
>  arch/powerpc/kernel/traps.c            | 24 ++++++++++++++++++++++++
>  arch/powerpc/platforms/powernv/opal.c  | 18 ++++--------------
>  arch/powerpc/platforms/ps3/setup.c     |  1 +
>  arch/powerpc/platforms/pseries/setup.c |  8 +++++++-
>  5 files changed, 38 insertions(+), 16 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/bug.h b/arch/powerpc/include/asm/bug.h
> index 3c04249bcf39..bca101ee1f32 100644
> --- a/arch/powerpc/include/asm/bug.h
> +++ b/arch/powerpc/include/asm/bug.h
> @@ -135,7 +135,8 @@ extern void bad_page_fault(struct pt_regs *, unsigned 
> long, int);
>  extern void _exception(int, struct pt_regs *, int, unsigned long);
>  extern void die(const char *, struct pt_regs *, long);
>  extern bool die_will_crash(void);
> -
> +extern void panic_flush_kmsg_start(void);
> +extern void panic_flush_kmsg_end(void);
>  #endif /* !__ASSEMBLY__ */
>  
>  #endif /* __KERNEL__ */
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index 109989676776..37c1ea9b0642 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -38,6 +38,8 @@
>  #include <linux/ratelimit.h>
>  #include <linux/context_tracking.h>
>  #include <linux/smp.h>
> +#include <linux/console.h>
> +#include <linux/kmsg_dump.h>
>  
>  #include <asm/emulated_ops.h>
>  #include <asm/pgtable.h>
> @@ -142,6 +144,28 @@ static int die_owner = -1;
>  static unsigned int die_nest_count;
>  static int die_counter;
>  
> +extern void panic_flush_kmsg_start(void)
> +{
> +     /*
> +      * These are mostly taken from kernel/panic.c, but tries to do
> +      * relatively minimal work. Don't use delay functions (TB may
> +      * be broken), don't crash dump (need to set a firmware log),
> +      * don't run notifiers. We do want to get some information to
> +      * Linux console.
> +      */
> +     console_verbose();
> +     bust_spinlocks(1);
> +}
> +
> +extern void panic_flush_kmsg_end(void)
> +{
> +     printk_safe_flush_on_panic();
> +     kmsg_dump(KMSG_DUMP_PANIC);
> +     bust_spinlocks(0);
> +     debug_locks_off();
> +     console_flush_on_panic();
> +}
> +
>  static unsigned long oops_begin(struct pt_regs *regs)
>  {
>       int cpu;
> diff --git a/arch/powerpc/platforms/powernv/opal.c 
> b/arch/powerpc/platforms/powernv/opal.c
> index 69b5263fc9e3..c15182765ff5 100644
> --- a/arch/powerpc/platforms/powernv/opal.c
> +++ b/arch/powerpc/platforms/powernv/opal.c
> @@ -461,24 +461,14 @@ static int opal_recover_mce(struct pt_regs *regs,
>  
>  void pnv_platform_error_reboot(struct pt_regs *regs, const char *msg)
>  {
> -     /*
> -      * This is mostly taken from kernel/panic.c, but tries to do
> -      * relatively minimal work. Don't use delay functions (TB may
> -      * be broken), don't crash dump (need to set a firmware log),
> -      * don't run notifiers. We do want to get some information to
> -      * Linux console.
> -      */
> -     console_verbose();
> -     bust_spinlocks(1);
> +     panic_flush_kmsg_start();
> +
>       pr_emerg("Hardware platform error: %s\n", msg);
>       if (regs)
>               show_regs(regs);
>       smp_send_stop();
> -     printk_safe_flush_on_panic();
> -     kmsg_dump(KMSG_DUMP_PANIC);
> -     bust_spinlocks(0);
> -     debug_locks_off();
> -     console_flush_on_panic();
> +
> +     panic_flush_kmsg_end();
>  
>       /*
>        * Don't bother to shut things down because this will
> diff --git a/arch/powerpc/platforms/ps3/setup.c 
> b/arch/powerpc/platforms/ps3/setup.c
> index 6244bc849469..77a37520068d 100644
> --- a/arch/powerpc/platforms/ps3/setup.c
> +++ b/arch/powerpc/platforms/ps3/setup.c
> @@ -113,6 +113,7 @@ static void ps3_panic(char *str)
>       printk("   System does not reboot automatically.\n");
>       printk("   Please press POWER button.\n");
>       printk("\n");
> +     panic_flush_kmsg_end();
>  
>       while(1)
>               lv1_pause(1);
> diff --git a/arch/powerpc/platforms/pseries/setup.c 
> b/arch/powerpc/platforms/pseries/setup.c
> index 28b286df0e91..a65843059c38 100644
> --- a/arch/powerpc/platforms/pseries/setup.c
> +++ b/arch/powerpc/platforms/pseries/setup.c
> @@ -498,6 +498,12 @@ static void __init pSeries_setup_arch(void)
>       ppc_md.pcibios_root_bridge_prepare = pseries_root_bridge_prepare;
>  }
>  
> +static void pSeries_panic(char *str)
> +{
> +     panic_flush_kmsg_end();
> +     rtas_os_term(str);
> +}
> +
>  static int __init pSeries_init_panel(void)
>  {
>       /* Manually leave the kernel version on the panel. */
> @@ -726,7 +732,7 @@ define_machine(pseries) {
>       .pcibios_fixup          = pSeries_final_fixup,
>       .restart                = rtas_restart,
>       .halt                   = rtas_halt,
> -     .panic                  = rtas_os_term,
> +     .panic                  = pSeries_panic,
>       .get_boot_time          = rtas_get_boot_time,
>       .get_rtc_time           = rtas_get_rtc_time,
>       .set_rtc_time           = rtas_set_rtc_time,

-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
                                | _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature

Reply via email to