From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:50:43
Hey folks, this is an attempt to improve/refactor the dated panic notifiers
infrastructure. This is strongly based in a suggestion made by Pter Mladek [0]
some time ago, and it's finally ready. Below I'll detail the patch ordering,
testing made, etc.
First, a bit about the reason behind this.
The panic notifiers list is an infrastructure that allows callbacks to execute
during panic time. Happens that anybody can add functions there, no ordering
is enforced (by default) and the decision to execute or not such notifiers
before kdump may lead to high risk of failure in crash scenarios - default is
not to execute any of them. There is a parameter acting as a switch for that.
But some architectures require some notifiers, so..it's messy.
The suggestion from Petr came after a patch submission to add a notifiers
filter, allowing the notifiers selection by function name, which was welcomed
by some people, but not by Petr, which claimed the code should indeed have a
refactor - and it made a lot of sense, his suggestion makes code more clear
and reliable.
So, this series might be split in 3 portions:
Part 1: the first 18 patches are mostly fixes (one or two might be considered
improvements), mostly replacing spinlocks/mutexes with safer alternatives for
atomic contexts, like spin_trylock, etc. We also focused on commenting
everything that is possible and clean-up code.
Part 2, the core: patches 19-25 are the main refactor, which splits the panic
notifiers list in three, introduce the concept of panic notifier level and
clean-up and highly comment the code, effectively leading to a more reliable
and clear, yet highly customizable panic path.
Part 3: The remaining 5 patches are fixes that _require the main refactor_
patches, they don't make sense without the core changes - but again, these are
small fixes and not part of the main goal of refactoring the panic code.
I've tried my best to make the patches the more "bisectable" as possible, so
they tend to be self-contained and easy to backport (specially patches from
part 1). Notice that the series is *based on 5.18-rc4* - usually a refactor
like this would be based on linux-next, but since we have many fixes in the
series, I kept it based on mainline tree. Of course I could change that in a
subsequent iteration, if desired.
Since this touches multiple architectures and drivers, it's very difficult to
test it really (by executing all touched code). So, my tests split in two
approaches: build tests and real tests, that involves panic triggering with
and without kdump, changing panic notifiers level, etc.
Build tests (using cross-compilers): alpha, arm, arm64, mips (sgi 22 and 32),
parisc, s390, sparc, um, x86_64 (couldn't get a functional xtensa cross
compiler).
Real/full tests: x86_64 (Hyper-V and QEMU guests) + PowerPC (pseries guest).
Here is the link with the .config files used: https://people.igalia.com/gpiccoli/panic_notifiers_configs/
(tried my best to build all the affected code).
Finally, a bit about my CCing strategy: I've included everybody present in the
original thread [0] plus some maintainers and other interested parties as CC
in the full series. But the patches have individual CC lists, for people that
are definitely related to them but might not care much for the whole series;
nevertheless, _everybody_ mentioned at least once in some patch is CCed in this
cover-letter. Hopefully I didn't forget to include anybody - all the mailing
lists were CCed in the whole series. Apologies in advance if (a) you received
emails you didn't want to or, (b) I forgot to include you but it was something
considered interesting by you.
Thanks in advance for reviews / comments / suggestions!
Cheers,
Guilherme
[0] https://lore.kernel.org/lkml/YfPxvzSzDLjO5ldp@alley/
Guilherme G. Piccoli (30):
x86/crash,reboot: Avoid re-disabling VMX in all CPUs on crash/restart
ARM: kexec: Disable IRQs/FIQs also on crash CPUs shutdown path
notifier: Add panic notifiers info and purge trailing whitespaces
firmware: google: Convert regular spinlock into trylock on panic path
misc/pvpanic: Convert regular spinlock into trylock on panic path
soc: bcm: brcmstb: Document panic notifier action and remove useless header
mips: ip22: Reword PANICED to PANICKED and remove useless header
powerpc/setup: Refactor/untangle panic notifiers
coresight: cpu-debug: Replace mutex with mutex_trylock on panic notifier
alpha: Clean-up the panic notifier code
um: Improve panic notifiers consistency and ordering
parisc: Replace regular spinlock with spin_trylock on panic path
s390/consoles: Improve panic notifiers reliability
panic: Properly identify the panic event to the notifiers' callbacks
bus: brcmstb_gisb: Clean-up panic/die notifiers
drivers/hv/vmbus, video/hyperv_fb: Untangle and refactor Hyper-V panic notifiers
tracing: Improve panic/die notifiers
notifier: Show function names on notifier routines if DEBUG_NOTIFIERS is set
panic: Add the panic hypervisor notifier list
panic: Add the panic informational notifier list
panic: Introduce the panic pre-reboot notifier list
panic: Introduce the panic post-reboot notifier list
printk: kmsg_dump: Introduce helper to inform number of dumpers
panic: Refactor the panic path
panic, printk: Add console flush parameter and convert panic_print to a notifier
Drivers: hv: Do not force all panic notifiers to execute before kdump
powerpc: Do not force all panic notifiers to execute before kdump
panic: Unexport crash_kexec_post_notifiers
powerpc: ps3, pseries: Avoid duplicate call to kmsg_dump() on panic
um: Avoid duplicate call to kmsg_dump()
.../admin-guide/kernel-parameters.txt | 54 ++-
Documentation/admin-guide/sysctl/kernel.rst | 5 +-
arch/alpha/kernel/setup.c | 40 +--
arch/arm/kernel/machine_kexec.c | 3 +
arch/arm64/kernel/setup.c | 2 +-
arch/mips/kernel/relocate.c | 2 +-
arch/mips/sgi-ip22/ip22-reset.c | 13 +-
arch/mips/sgi-ip32/ip32-reset.c | 3 +-
arch/parisc/include/asm/pdc.h | 1 +
arch/parisc/kernel/firmware.c | 27 +-
arch/parisc/kernel/pdc_chassis.c | 3 +-
arch/powerpc/include/asm/bug.h | 2 +-
arch/powerpc/kernel/fadump.c | 8 -
arch/powerpc/kernel/setup-common.c | 76 ++--
arch/powerpc/kernel/traps.c | 6 +-
arch/powerpc/platforms/powernv/opal.c | 2 +-
arch/powerpc/platforms/ps3/setup.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 2 +-
arch/s390/kernel/ipl.c | 4 +-
arch/s390/kernel/setup.c | 19 +-
arch/sparc/kernel/setup_32.c | 27 +-
arch/sparc/kernel/setup_64.c | 29 +-
arch/sparc/kernel/sstate.c | 3 +-
arch/um/drivers/mconsole_kern.c | 10 +-
arch/um/kernel/um_arch.c | 11 +-
arch/x86/include/asm/cpu.h | 1 +
arch/x86/kernel/crash.c | 8 +-
arch/x86/kernel/reboot.c | 14 +-
arch/x86/kernel/setup.c | 2 +-
arch/x86/xen/enlighten.c | 2 +-
arch/xtensa/platforms/iss/setup.c | 4 +-
drivers/bus/brcmstb_gisb.c | 28 +-
drivers/char/ipmi/ipmi_msghandler.c | 12 +-
drivers/edac/altera_edac.c | 3 +-
drivers/firmware/google/gsmi.c | 10 +-
drivers/hv/hv_common.c | 12 -
drivers/hv/vmbus_drv.c | 113 +++---
.../hwtracing/coresight/coresight-cpu-debug.c | 11 +-
drivers/leds/trigger/ledtrig-activity.c | 4 +-
drivers/leds/trigger/ledtrig-heartbeat.c | 4 +-
drivers/leds/trigger/ledtrig-panic.c | 3 +-
drivers/misc/bcm-vk/bcm_vk_dev.c | 6 +-
drivers/misc/ibmasm/heartbeat.c | 16 +-
drivers/misc/pvpanic/pvpanic.c | 14 +-
drivers/net/ipa/ipa_smp2p.c | 5 +-
drivers/parisc/power.c | 21 +-
drivers/power/reset/ltc2952-poweroff.c | 4 +-
drivers/remoteproc/remoteproc_core.c | 6 +-
drivers/s390/char/con3215.c | 38 +-
drivers/s390/char/con3270.c | 36 +-
drivers/s390/char/raw3270.c | 18 +
drivers/s390/char/raw3270.h | 1 +
drivers/s390/char/sclp_con.c | 30 +-
drivers/s390/char/sclp_vt220.c | 44 +--
drivers/s390/char/zcore.c | 5 +-
drivers/soc/bcm/brcmstb/pm/pm-arm.c | 18 +-
drivers/soc/tegra/ari-tegra186.c | 3 +-
drivers/staging/olpc_dcon/olpc_dcon.c | 6 +-
drivers/video/fbdev/hyperv_fb.c | 12 +-
include/linux/console.h | 2 +
include/linux/kmsg_dump.h | 7 +
include/linux/notifier.h | 8 +-
include/linux/panic.h | 3 -
include/linux/panic_notifier.h | 12 +-
include/linux/printk.h | 1 +
kernel/hung_task.c | 3 +-
kernel/kexec_core.c | 8 +-
kernel/notifier.c | 48 ++-
kernel/panic.c | 335 +++++++++++-------
kernel/printk/printk.c | 76 ++++
kernel/rcu/tree.c | 1 -
kernel/rcu/tree_stall.h | 3 +-
kernel/trace/trace.c | 59 +--
.../selftests/pstore/pstore_crash_test | 5 +-
74 files changed, 953 insertions(+), 486 deletions(-)
--
2.36.0
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:51:30
Although many notifiers are mentioned in the comments, the panic
notifiers infrastructure is not. Also, the file contains some
trailing whitespaces. This commit fix both issues.
Cc: Arjan van de Ven <redacted>
Cc: Cong Wang <redacted>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Valentin Schneider <redacted>
Cc: Xiaoming Ni <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
include/linux/notifier.h | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
@@ -201,12 +201,12 @@ static inline int notifier_to_errno(int ret)/**Declarednotifierssofar.Icanimaginequiteafewmorechains-*overtime(eglaptoppowerresetchains,rebootchain(toclean+*overtime(eglaptoppowerresetchains,rebootchain(toclean*deviceunitsup),device[un]mountchain,moduleload/unloadchain,-*lowmemorychain,screenblankchain(forpluginmodularscreenblankers)+*lowmemorychain,screenblankchain(forpluginmodularscreenblankers)*VCswitchchains(forloadablekernelsvgalibVCswitchhelpers)etc...*/-+/* CPU notfiers are defined in include/linux/cpu.h. *//* netdevice notifiers are defined in include/linux/netdevice.h */
@@ -217,6 +217,8 @@ static inline int notifier_to_errno(int ret)/* Virtual Terminal events are defined in include/linux/vt.h. */+/* Panic notifiers are defined in include/linux/panic_notifier.h. */+#define NETLINK_URELEASE 0x0001 /* Unicast netlink socket released *//* Console keyboard events.
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:51:35
Currently the gsmi driver registers a panic notifier as well as
reboot and die notifiers. The callbacks registered are called in
atomic and very limited context - for instance, panic disables
preemption, local IRQs and all other CPUs that aren't running the
current panic function.
With that said, taking a spinlock in this scenario is a
dangerous invitation for a deadlock scenario. So, we fix
that in this commit by changing the regular spinlock with
a trylock, which is a safer approach.
Fixes: 74c5b31c6618 ("driver: Google EFI SMI")
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: David Gow <redacted>
Cc: Evan Green <redacted>
Cc: Julius Werner <jwerner@chromium.org>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
drivers/firmware/google/gsmi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:51:45
The panic notifier of this driver is very simple code-wise, just a memory
write to a special position with some numeric code. But this is not clear
from the semantic point-of-view, and there is no public documentation
about that either.
After discussing this in the mailing-lists [0] and having Florian explained
it very well, this patch just document that in the code for the future
generations asking the same questions. Also, it removes a useless header.
[0] https://lore.kernel.org/lkml/781cafb0-8d06-8b56-907a-5175c2da196a@gmail.com
Fixes: 0b741b8234c8 ("soc: bcm: brcmstb: Add support for S2/S3/S5 suspend states (ARM)")
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Doug Berger <opendmb@gmail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Justin Chen <redacted>
Cc: Lee Jones <redacted>
Cc: Markus Mayer <mmayer@broadcom.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
drivers/soc/bcm/brcmstb/pm/pm-arm.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:51:58
The pvpanic driver relies on panic notifiers to execute a callback
on panic event. Such function is executed in atomic context - the
panic function disables local IRQs, preemption and all other CPUs
that aren't running the panic code.
With that said, it's dangerous to use regular spinlocks in such path,
as introduced by commit b3c0f8774668 ("misc/pvpanic: probe multiple instances").
This patch fixes that by replacing regular spinlocks with the trylock
safer approach.
It also fixes an old comment (about a long gone framebuffer code) and
the notifier priority - we should execute hypervisor notifiers early,
deferring this way the panic action to the hypervisor, as expected by
the users that are setting up pvpanic.
Fixes: b3c0f8774668 ("misc/pvpanic: probe multiple instances")
Cc: Christophe JAILLET <redacted>
Cc: Mihai Carabas <redacted>
Cc: Shile Zhang <redacted>
Cc: Wang ShaoBo <redacted>
Cc: zhenwei pi <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
drivers/misc/pvpanic/pvpanic.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
@@ -34,7 +34,9 @@ pvpanic_send_event(unsigned int event){structpvpanic_instance*pi_cur;-spin_lock(&pvpanic_lock);+if(!spin_trylock(&pvpanic_lock))+return;+list_for_each_entry(pi_cur,&pvpanic_list,list){if(event&pi_cur->capability&pi_cur->events)iowrite8(event,pi_cur->base);
@@ -55,9 +57,13 @@ pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, void *unusedreturnNOTIFY_DONE;}+/*+*Callournotifierveryearlyonpanic,deferringthe+*actiontakentothehypervisor.+*/staticstructnotifier_blockpvpanic_panic_nb={.notifier_call=pvpanic_panic_notify,-.priority=1,/* let this called before broken drm_fb_helper() */+.priority=INT_MAX,};staticvoidpvpanic_remove(void*param)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:52:34
In the panic path we have a list of functions to be called, the panic
notifiers - such callbacks perform various actions in the machine's
last breath, and sometimes users want them to run before kdump. We
have the parameter "crash_kexec_post_notifiers" for that. When such
parameter is used, the function "crash_smp_send_stop()" is executed
to poweroff all secondary CPUs through the NMI-shootdown mechanism;
part of this process involves disabling virtualization features in
all CPUs (except the main one).
Now, in the emergency restart procedure we have also a way of
disabling VMX in all CPUs, using the same NMI-shootdown mechanism;
what happens though is that in case we already NMI-disabled all CPUs,
the emergency restart fails due to a second addition of the same items
in the NMI list, as per the following log output:
sysrq: Trigger a crash
Kernel panic - not syncing: sysrq triggered crash
[...]
Rebooting in 2 seconds..
list_add double add: new=<addr1>, prev=<addr2>, next=<addr1>.
------------[ cut here ]------------
kernel BUG at lib/list_debug.c:29!
invalid opcode: 0000 [#1] PREEMPT SMP PTI
In order to reproduce the problem, users just need to set the kernel
parameter "crash_kexec_post_notifiers" *without* kdump set in any
system with the VMX feature present.
Since there is no benefit in re-disabling VMX in all CPUs in case
it was already done, this patch prevents that by guarding the restart
routine against doubly issuing NMIs unnecessarily. Notice we still
need to disable VMX locally in the emergency restart.
Fixes: ed72736183c4 ("x86/reboot: Force all cpus to exit VMX root if VMX is supported)
Fixes: 0ee59413c967 ("x86/panic: replace smp_send_stop() with kdump friendly version in panic path")
Cc: David P. Reed <redacted>
Cc: Hidehiro Kawai <redacted>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Sean Christopherson <seanjc@google.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/x86/include/asm/cpu.h | 1 +
arch/x86/kernel/crash.c | 8 ++++----
arch/x86/kernel/reboot.c | 14 ++++++++++++--
3 files changed, 17 insertions(+), 6 deletions(-)
@@ -36,6 +36,7 @@ extern int _debug_hotplug_cpu(int cpu, int action);#endif#endif+externboolcrash_cpus_stopped;intmwait_usable(conststructcpuinfo_x86*);unsignedintx86_family(unsignedintsig);
@@ -42,6 +42,8 @@#include<asm/crash.h>#include<asm/cmdline.h>+boolcrash_cpus_stopped;+/* Used while preparing memory map entries for second kernel */structcrash_memmap_data{structboot_params*params;
@@ -108,9 +110,7 @@ void kdump_nmi_shootdown_cpus(void)/* Override the weak function in kernel/panic.c */voidcrash_smp_send_stop(void){-staticintcpus_stopped;--if(cpus_stopped)+if(crash_cpus_stopped)return;if(smp_ops.crash_stop_other_cpus)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:52:41
Currently the regular CPU shutdown path for ARM disables IRQs/FIQs
in the secondary CPUs - smp_send_stop() calls ipi_cpu_stop(), which
is responsible for that. This makes sense, since we're turning off
such CPUs, putting them in an endless busy-wait loop.
Problem is that there is an alternative path for disabling CPUs,
in the form of function crash_smp_send_stop(), used for kexec/panic
paths. This functions relies in a SMP call that also triggers a
busy-wait loop [at machine_crash_nonpanic_core()], but *without*
disabling interrupts. This might lead to odd scenarios, like early
interrupts in the boot of kexec'd kernel or even interrupts in
other CPUs while the main one still works in the panic path and
assumes all secondary CPUs are (really!) off.
This patch mimics the ipi_cpu_stop() interrupt disable mechanism
in the crash CPU shutdown path, hence disabling IRQs/FIQs in all
secondary CPUs in the kexec/panic path as well.
Cc: Marc Zyngier <maz@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/arm/kernel/machine_kexec.c | 3 +++
1 file changed, 3 insertions(+)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:53:32
Many other place in the kernel prefer the latter, so let's keep
it consistent in MIPS code as well. Also, removes a useless header.
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/mips/sgi-ip22/ip22-reset.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:54:03
The panic notifiers infrastructure is a bit limited in the scope of
the callbacks - basically every kind of functionality is dropped
in a list that runs in the same point during the kernel panic path.
This is not really on par with the complexities and particularities
of architecture / hypervisors' needs, and a refactor is ongoing.
As part of this refactor, it was observed that powerpc has 2 notifiers,
with mixed goals: one is just a KASLR offset dumper, whereas the other
aims to hard-disable IRQs (necessary on panic path), warn firmware of
the panic event (fadump) and run low-level platform-specific machinery
that might stop kernel execution and never come back.
Clearly, the 2nd notifier has opposed goals: disable IRQs / fadump
should run earlier while low-level platform actions should
run late since it might not even return. Hence, this patch decouples
the notifiers splitting them in three:
- First one is responsible for hard-disable IRQs and fadump,
should run early;
- The kernel KASLR offset dumper is really an informative notifier,
harmless and may run at any moment in the panic path;
- The last notifier should run last, since it aims to perform
low-level actions for specific platforms, and might never return.
It is also only registered for 2 platforms, pseries and ps3.
The patch better documents the notifiers and clears the code too,
also removing a useless header.
Currently no functionality change should be observed, but after
the planned panic refactor we should expect more panic reliability
with this patch.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
We'd like to thanks specially the MiniCloud infrastructure [0] maintainers,
that allow us to test PowerPC code in a very complete, functional and FREE
environment (there's no need even for adding a credit card, like many "free"
clouds require ¬¬ ).
[0] https://openpower.ic.unicamp.br/minicloud
arch/powerpc/kernel/setup-common.c | 74 ++++++++++++++++++++++--------
1 file changed, 54 insertions(+), 20 deletions(-)
@@ -680,8 +679,25 @@ int check_legacy_ioport(unsigned long base_port)}EXPORT_SYMBOL(check_legacy_ioport);-staticintppc_panic_event(structnotifier_block*this,-unsignedlongevent,void*ptr)+/*+*Panicnotifierssetup+*+*Wehave3notifiersforpowerpc,eachonefromadifferent"nature":+*+*-ppc_panic_fadump_handler()isahypervisornotifier,whichhard-disables+*IRQsanddealwiththeFirmware-Assisteddump,whenitisconfigured;+*shouldrunearlyinthepanicpath.+*+*-dump_kernel_offset()isaninformativenotifier,justshowingtheKASLR+*offsetifwehaveRANDOMIZE_BASEset.+*+*-ppc_panic_platform_handler()isalow-levelhandlerthat'sregistered+*onlyiftheplatformwishestoperformfinalactionsinthepanicpath,+*henceitshouldrunlateandmightnotevenreturn.Currently,only+*pseriesandps3platformsregistercallbacks.+*/+staticintppc_panic_fadump_handler(structnotifier_block*this,+unsignedlongevent,void*ptr){/**panicdoesalocal_irq_disable,butwereally
@@ -691,45 +707,63 @@ static int ppc_panic_event(struct notifier_block *this,/**Iffirmware-assisteddumphasbeenregisteredthentrigger-*firmware-assisteddumpandletfirmwarehandleeverythingelse.+*itscallbackandletthefirmwarehandleseverythingelse.*/crash_fadump(NULL,ptr);-if(ppc_md.panic)-ppc_md.panic(ptr);/* May not return */+returnNOTIFY_DONE;}-staticstructnotifier_blockppc_panic_block={-.notifier_call=ppc_panic_event,-.priority=INT_MIN/* may not return; must be done last */-};--/*-*Dumpoutkerneloffsetinformationonpanic.-*/staticintdump_kernel_offset(structnotifier_block*self,unsignedlongv,void*p){pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",kaslr_offset(),KERNELBASE);-return0;+returnNOTIFY_DONE;}+staticintppc_panic_platform_handler(structnotifier_block*this,+unsignedlongevent,void*ptr)+{+/*+*Thishandlerisonlyregisteredifwehaveapaniccallback+*onppc_md,henceNULLcheckisnotneeded.+*Also,itmaynotreturn,soitrunsreallylateonpanicpath.+*/+ppc_md.panic(ptr);++returnNOTIFY_DONE;+}++staticstructnotifier_blockppc_fadump_block={+.notifier_call=ppc_panic_fadump_handler,+.priority=INT_MAX,/* run early, to notify the firmware ASAP */+};+staticstructnotifier_blockkernel_offset_notifier={-.notifier_call=dump_kernel_offset+.notifier_call=dump_kernel_offset,+};++staticstructnotifier_blockppc_panic_block={+.notifier_call=ppc_panic_platform_handler,+.priority=INT_MIN,/* may not return; must be done last */};void__initsetup_panic(void){+/* Hard-disables IRQs + deal with FW-assisted dump (fadump) */+atomic_notifier_chain_register(&panic_notifier_list,+&ppc_fadump_block);+if(IS_ENABLED(CONFIG_RANDOMIZE_BASE)&&kaslr_offset()>0)atomic_notifier_chain_register(&panic_notifier_list,&kernel_offset_notifier);-/* PPC64 always does a hard irq disable in its panic handler */-if(!IS_ENABLED(CONFIG_PPC64)&&!ppc_md.panic)-return;-atomic_notifier_chain_register(&panic_notifier_list,&ppc_panic_block);+/* Low-level platform-specific routines that should run on panic */+if(ppc_md.panic)+atomic_notifier_chain_register(&panic_notifier_list,+&ppc_panic_block);}#ifdef CONFIG_CHECK_CACHE_COHERENCY
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:54:41
The panic notifier infrastructure executes registered callbacks when
a panic event happens - such callbacks are executed in atomic context,
with interrupts and preemption disabled in the running CPU and all other
CPUs disabled. That said, mutexes in such context are not a good idea.
This patch replaces a regular mutex with a mutex_trylock safer approach;
given the nature of the mutex used in the driver, it should be pretty
uncommon being unable to acquire such mutex in the panic path, hence
no functional change should be observed (and if it is, that would be
likely a deadlock with the regular mutex).
Fixes: 2227b7c74634 ("coresight: add support for CPU debug module")
Cc: Leo Yan <redacted>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Mike Leach <redacted>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
drivers/hwtracing/coresight/coresight-cpu-debug.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
@@ -380,9 +380,10 @@ static int debug_notifier_call(struct notifier_block *self,intcpu;structdebug_drvdata*drvdata;-mutex_lock(&debug_lock);+/* Bail out if we can't acquire the mutex or the functionality is off */+if(!mutex_trylock(&debug_lock))+returnNOTIFY_DONE;-/* Bail out if the functionality is disabled */if(!debug_enable)gotoskip_dump;
@@ -401,7 +402,7 @@ static int debug_notifier_call(struct notifier_block *self,skip_dump:mutex_unlock(&debug_lock);-return0;+returnNOTIFY_DONE;}staticstructnotifier_blockdebug_notifier={
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:54:50
The alpha panic notifier has some code issues, not following
the conventions of other notifiers. Also, it might halt the
machine but still it is set to run as early as possible, which
doesn't seem to be a good idea.
This patch cleans the code, and set the notifier to run as the
latest, following the same approach other architectures are doing.
Also, we remove the unnecessary include of a header already
included indirectly.
Cc: Ivan Kokshaysky <redacted>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Richard Henderson <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/alpha/kernel/setup.c | 36 +++++++++++++++---------------------
1 file changed, 15 insertions(+), 21 deletions(-)
@@ -41,19 +41,11 @@#include<linux/sysrq.h>#include<linux/reboot.h>#endif-#include<linux/notifier.h>#include<asm/setup.h>#include<asm/io.h>#include<linux/log2.h>#include<linux/export.h>-staticintalpha_panic_event(structnotifier_block*,unsignedlong,void*);-staticstructnotifier_blockalpha_panic_block={-alpha_panic_event,-NULL,-INT_MAX/* try to do it first */-};-#include<linux/uaccess.h>#include<asm/hwrpb.h>#include<asm/dma.h>
@@ -435,6 +427,21 @@ static const struct sysrq_key_op srm_sysrq_reboot_op = {};#endif+staticintalpha_panic_event(structnotifier_block*this,+unsignedlongevent,void*ptr)+{+/* If we are using SRM and serial console, just hard halt here. */+if(alpha_using_srm&&srmcons_output)+__halt();++returnNOTIFY_DONE;+}++staticstructnotifier_blockalpha_panic_block={+.notifier_call=alpha_panic_event,+.priority=INT_MIN,/* may not return, do it last */+};+void__initsetup_arch(char**cmdline_p){
@@ -1427,19 +1434,6 @@ const struct seq_operations cpuinfo_op = {.show=show_cpuinfo,};--staticint-alpha_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr)-{-#if 1-/* FIXME FIXME FIXME */-/* If we are using SRM and serial console, just hard halt here. */-if(alpha_using_srm&&srmcons_output)-__halt();-#endif-returnNOTIFY_DONE;-}-static__initintadd_pcspkr(void){structplatform_device*pd;
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:55:00
The panic notifiers' callbacks execute in an atomic context, with
interrupts/preemption disabled, and all CPUs not running the panic
function are off, so it's very dangerous to wait on a regular
spinlock, there's a risk of deadlock.
This patch refactors the panic notifier of parisc/power driver
to make use of spin_trylock - for that, we've added a second
version of the soft-power function. Also, some comments were
reorganized and trailing white spaces, useless header inclusion
and blank lines were removed.
Cc: Helge Deller <deller@gmx.de>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/parisc/include/asm/pdc.h | 1 +
arch/parisc/kernel/firmware.c | 27 +++++++++++++++++++++++----
drivers/parisc/power.c | 17 ++++++++++-------
3 files changed, 34 insertions(+), 11 deletions(-)
@@ -83,6 +83,7 @@ int pdc_do_firm_test_reset(unsigned long ftc_bitmap);intpdc_do_reset(void);intpdc_soft_power_info(unsignedlong*power_reg);intpdc_soft_power_button(intsw_control);+intpdc_soft_power_button_panic(intsw_control);voidpdc_io_reset(void);voidpdc_io_reset_devices(void);intpdc_iodc_getc(void);
@@ -1232,15 +1232,18 @@ int __init pdc_soft_power_info(unsigned long *power_reg)}/*-*pdc_soft_power_button-Controlthesoftpowerbuttonbehaviour-*@sw_control:0forhardwarecontrol,1forsoftwarecontrol+*pdc_soft_power_button{_panic}-Controlthesoftpowerbuttonbehaviour+*@sw_control:0forhardwarecontrol,1forsoftwarecontrol***ThisPDCfunctionplacesthesoftpowerbuttonundersoftwareor*hardwarecontrol.-*UndersoftwarecontroltheOSmaycontroltowhentoallowtoshut-*downthesystem.Underhardwarecontrolpressingthepowerbutton+*UndersoftwarecontroltheOSmaycontroltowhentoallowtoshut+*downthesystem.Underhardwarecontrolpressingthepowerbutton*powersoffthesystemimmediately.+*+*The_panicversionreliesinspin_trylocktopreventdeadlock+*onpanicpath.*/intpdc_soft_power_button(intsw_control){
@@ -1254,6 +1257,22 @@ int pdc_soft_power_button(int sw_control)returnretval;}+intpdc_soft_power_button_panic(intsw_control)+{+intretval;+unsignedlongflags;++if(!spin_trylock_irqsave(&pdc_lock,flags)){+pr_emerg("Couldn't enable soft power button\n");+return-EBUSY;/* ignored by the panic notifier */+}++retval=mem_pdc_call(PDC_SOFT_POWER,PDC_SOFT_POWER_ENABLE,__pa(pdc_result),sw_control);+spin_unlock_irqrestore(&pdc_lock,flags);++returnretval;+}+/**pdc_io_reset-HacktoavoidoverlappingrangeregistersofBridgesdevices.*PrimarilyaproblemonT600(whichparisc-linuxdoesn'tsupport)but
@@ -175,16 +174,21 @@ static void powerfail_interrupt(int code, void *x)-/* parisc_panic_event() is called by the panic handler.-*Assoonasapanicoccurs,ourtaskletsabovewillnotbe-*executedanylonger.Thisfunctionthenre-enablesthe-*soft-powerswitchandallowstheusertoswitchoffthesystem+/*+*parisc_panic_event()iscalledbythepanichandler.+*+*Assoonasapanicoccurs,ourtaskletsabovewillnot+*beexecutedanylonger.Thisfunctionthenre-enables+*thesoft-powerswitchandallowstheusertoswitchoff+*thesystem.Werelyinpdc_soft_power_button_panic()+*sincethisversionspin_trylocks(insteadofregular+*spinlock),preventingdeadlocksonpanicpath.*/staticintparisc_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr){/* re-enable the soft-power switch */-pdc_soft_power_button(0);+pdc_soft_power_button_panic(0);returnNOTIFY_DONE;}
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:55:08
Currently many console drivers for s390 rely on panic/reboot notifiers
to invoke callbacks on these events. The panic() function disables local
IRQs, secondary CPUs and preemption, so callbacks invoked on panic are
effectively running in atomic context.
Happens that most of these console callbacks from s390 doesn't take the
proper care with regards to atomic context, like taking spinlocks that
might be taken in other function/CPU and hence will cause a lockup
situation.
The goal for this patch is to improve the notifiers reliability, acting
on 4 console drivers, as detailed below:
(1) con3215: changed a regular spinlock to the trylock alternative.
(2) con3270: also changed a regular spinlock to its trylock counterpart,
but here we also have another problem: raw3270_activate_view() takes a
different spinlock. So, we worked a helper to validate if this other lock
is safe to acquire, and if so, raw3270_activate_view() should be safe.
Notice though that there is a functional change here: it's now possible
to continue the notifier code [reaching con3270_wait_write() and
con3270_rebuild_update()] without executing raw3270_activate_view().
(3) sclp: a global lock is used heavily in the functions called from
the notifier, so we added a check here - if the lock is taken already,
we just bail-out, preventing the lockup.
(4) sclp_vt220: same as (3), a lock validation was added to prevent the
potential lockup problem.
Besides (1)-(4), we also removed useless void functions, adding the
code called from the notifier inside its own body, and changed the
priority of such notifiers to execute late, since they are "heavyweight"
for the panic environment, so we aim to reduce risks here.
Changed return values to NOTIFY_DONE as well, the standard one.
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
As a design choice, the option used here to verify a given spinlock is taken
was the function "spin_is_locked()" - but we noticed that it is not often used.
An alternative would to take the lock with a spin_trylock() and if it succeeds,
just release the spinlock and continue the code. But that seemed weird...
Also, we'd like to ask a good validation of case (2) potential functionality
change from the s390 console experts - far from expert here, and in our naive
code observation, that seems fine, but that analysis might be missing some
corner case.
Thanks in advance!
drivers/s390/char/con3215.c | 36 +++++++++++++++--------------
drivers/s390/char/con3270.c | 34 +++++++++++++++------------
drivers/s390/char/raw3270.c | 18 +++++++++++++++
drivers/s390/char/raw3270.h | 1 +
drivers/s390/char/sclp_con.c | 28 +++++++++++++----------
drivers/s390/char/sclp_vt220.c | 42 +++++++++++++++++++---------------
6 files changed, 96 insertions(+), 63 deletions(-)
@@ -771,35 +771,37 @@ static struct tty_driver *con3215_device(struct console *c, int *index)}/*-*panic()callscon3215_flushthroughapanic_notifier-*beforethesystementersadisabled,endlessloop.+*Thebelowfunctioniscalledasapanic/rebootnotifierbeforethe+*systementersadisabled,endlessloop.+*+*Noticewemustusethespin_trylock()alternative,topreventlockups+*inatomiccontext(panicroutinerunswithsecondaryCPUs,localIRQs+*andpreemptiondisabled).*/-staticvoidcon3215_flush(void)-{-structraw3215_info*raw;-unsignedlongflags;--raw=raw3215[0];/* console 3215 is the first one */-spin_lock_irqsave(get_ccwdev_lock(raw->cdev),flags);-raw3215_make_room(raw,RAW3215_BUFFER_SIZE);-spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev),flags);-}-staticintcon3215_notify(structnotifier_block*self,unsignedlongevent,void*data){-con3215_flush();-returnNOTIFY_OK;+structraw3215_info*raw;+unsignedlongflags;++raw=raw3215[0];/* console 3215 is the first one */+if(!spin_trylock_irqsave(get_ccwdev_lock(raw->cdev),flags))+returnNOTIFY_DONE;++raw3215_make_room(raw,RAW3215_BUFFER_SIZE);+spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev),flags);++returnNOTIFY_DONE;}staticstructnotifier_blockon_panic_nb={.notifier_call=con3215_notify,-.priority=0,+.priority=INT_MIN+1,/* run the callback late */};staticstructnotifier_blockon_reboot_nb={.notifier_call=con3215_notify,-.priority=0,+.priority=INT_MIN+1,/* run the callback late */};/*
@@ -560,23 +569,18 @@ con3270_flush(void)con3270_wait_write(cp);}spin_unlock_irqrestore(&cp->view.lock,flags);-}-staticintcon3270_notify(structnotifier_block*self,-unsignedlongevent,void*data)-{-con3270_flush();-returnNOTIFY_OK;+returnNOTIFY_DONE;}staticstructnotifier_blockon_panic_nb={.notifier_call=con3270_notify,-.priority=0,+.priority=INT_MIN+1,/* run the callback late */};staticstructnotifier_blockon_reboot_nb={.notifier_call=con3270_notify,-.priority=0,+.priority=INT_MIN+1,/* run the callback late */};/*
@@ -220,30 +220,34 @@ sclp_console_device(struct console *c, int *index)}/*-*MakesurethatallbufferswillbeflushedtotheSCLP.+*Thispanic/rebootnotifiermakessurethatallbuffers+*willbeflushedtotheSCLP.*/-staticvoid-sclp_console_flush(void)-{-sclp_conbuf_emit();-sclp_console_sync_queue();-}-staticintsclp_console_notify(structnotifier_block*self,unsignedlongevent,void*data){-sclp_console_flush();-returnNOTIFY_OK;+/*+*Performthelockcheckbeforeeffectivelygettingthe+*lockonsclp_conbuf_emit()/sclp_console_sync_queue()+*topreventpotentiallockupsinatomiccontext.+*/+if(spin_is_locked(&sclp_con_lock))+returnNOTIFY_DONE;++sclp_conbuf_emit();+sclp_console_sync_queue();++returnNOTIFY_DONE;}staticstructnotifier_blockon_panic_nb={.notifier_call=sclp_console_notify,-.priority=1,+.priority=INT_MIN+1,/* run the callback late */};staticstructnotifier_blockon_reboot_nb={.notifier_call=sclp_console_notify,-.priority=1,+.priority=INT_MIN+1,/* run the callback late */};/*
@@ -797,22 +782,41 @@ sclp_vt220_con_device(struct console *c, int *index)returnsclp_vt220_driver;}+/*+*Thispanic/rebootnotifierrunsinatomiccontext,so+*lockingrestrictionsapplytopreventpotentiallockups.+*/staticintsclp_vt220_notify(structnotifier_block*self,unsignedlongevent,void*data){-__sclp_vt220_flush_buffer();-returnNOTIFY_OK;+unsignedlongflags;++if(spin_is_locked(&sclp_vt220_lock))+returnNOTIFY_DONE;++sclp_vt220_emit_current();++spin_lock_irqsave(&sclp_vt220_lock,flags);+del_timer(&sclp_vt220_timer);+while(sclp_vt220_queue_running){+spin_unlock_irqrestore(&sclp_vt220_lock,flags);+sclp_sync_wait();+spin_lock_irqsave(&sclp_vt220_lock,flags);+}+spin_unlock_irqrestore(&sclp_vt220_lock,flags);++returnNOTIFY_DONE;}staticstructnotifier_blockon_panic_nb={.notifier_call=sclp_vt220_notify,-.priority=1,+.priority=INT_MIN+1,/* run the callback late */};staticstructnotifier_blockon_reboot_nb={.notifier_call=sclp_vt220_notify,-.priority=1,+.priority=INT_MIN+1,/* run the callback late */};/* Structure needed to register with printk */
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:55:19
The notifiers infrastructure provides a way to pass an "id" to the
callbacks to determine what kind of event happened, i.e., what is
the reason behind they getting called.
The panic notifier currently pass 0, but this is soon to be
used in a multi-targeted notifier, so let's pass a meaningful
"id" over there.
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
include/linux/panic_notifier.h | 5 +++++
kernel/panic.c | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:56:28
Currently the panic notifiers from user mode linux don't follow
the convention for most of the other notifiers present in the
kernel (indentation, priority setting, numeric return).
More important, the priorities could be improved, since it's a
special case (userspace), hence we could run the notifiers earlier;
user mode linux shouldn't care much with other panic notifiers but
the ordering among the mconsole and arch notifier is important,
given that the arch one effectively triggers a core dump.
This patch fixes that by running the mconsole notifier as the first
panic notifier, followed by the architecture one (that coredumps).
Also, we remove a useless header inclusion.
Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Richard Weinberger <richard@nod.at>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/um/drivers/mconsole_kern.c | 8 +++-----
arch/um/kernel/um_arch.c | 8 ++++----
2 files changed, 7 insertions(+), 9 deletions(-)
@@ -846,13 +845,12 @@ static int notify_panic(struct notifier_block *self, unsigned long unused1,mconsole_notify(notify_socket,MCONSOLE_PANIC,message,strlen(message)+1);-return0;+returnNOTIFY_DONE;}staticstructnotifier_blockpanic_exit_notifier={-.notifier_call=notify_panic,-.next=NULL,-.priority=1+.notifier_call=notify_panic,+.priority=INT_MAX,/* run as soon as possible */};staticintadd_notifier(void)
@@ -246,13 +246,13 @@ static int panic_exit(struct notifier_block *self, unsigned long unused1,bust_spinlocks(0);uml_exitcode=1;os_dump_core();-return0;++returnNOTIFY_DONE;}staticstructnotifier_blockpanic_exit_notifier={-.notifier_call=panic_exit,-.next=NULL,-.priority=0+.notifier_call=panic_exit,+.priority=INT_MAX-1,/* run as 2nd notifier, won't return */};voiduml_finishsetup(void)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:56:46
Currently we have a debug infrastructure in the notifiers file, but
it's very simple/limited. This patch extends it by:
(a) Showing all registered/unregistered notifiers' callback names;
(b) Adding a dynamic debug tuning to allow showing called notifiers'
function names. Notice that this should be guarded as a tunable since
it can flood the kernel log buffer.
Cc: Arjan van de Ven <redacted>
Cc: Cong Wang <redacted>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Valentin Schneider <redacted>
Cc: Xiaoming Ni <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
We have some design decisions that worth discussing here:
(a) First of call, using C99 helps a lot to write clear and concise code, but
due to commit 4d94f910e79a ("Kbuild: use -Wdeclaration-after-statement") we
have a warning if mixing variable declarations with code. For this patch though,
doing that makes the code way clear, so decision was to add the debug code
inside brackets whenever this warning pops up. We can change that, but that'll
cause more ifdefs in the same function.
(b) In the symbol lookup helper function, we modify the parameter passed but
even more, we return it as well! This is unusual and seems unnecessary, but was
the strategy taken to allow embedding such function in the pr_debug() call.
Not doing that would likely requiring 3 symbol_name variables to avoid
concurrency (registering notifier A while calling notifier B) - we rely in
local variables as a serialization mechanism.
We're open for suggestions in case this design is not appropriate;
thanks in advance!
kernel/notifier.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:57:02
Currently the tracing dump_on_oops feature is implemented
through separate notifiers, one for die/oops and the other
for panic. With the addition of panic notifier "id", this
patch makes use of such "id" to unify both functions.
It also comments the function and changes the priority of the
notifier blocks, in order they run early compared to other
notifiers, to prevent useless trace data (like the callback
names for the other notifiers). Finally, we also removed an
unnecessary header inclusion.
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
kernel/trace/trace.c | 57 +++++++++++++++++++++++++-------------------
1 file changed, 32 insertions(+), 25 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:57:15
This patch improves the panic/die notifiers in this driver by
making use of a passed "id" instead of comparing pointer
address; also, it removes an useless prototype declaration
and unnecessary header inclusion.
This is part of a panic notifiers refactor - this notifier in
the future will be moved to a new list, that encompass the
information notifiers only.
Fixes: 9eb60880d9a9 ("bus: brcmstb_gisb: add notifier handling")
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
drivers/bus/brcmstb_gisb.c | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:57:23
Currently Hyper-V guests are among the most relevant users of the panic
infrastructure, like panic notifiers, kmsg dumpers, etc. The reasons rely
both in cleaning-up procedures (closing a hypervisor <-> guest connection,
disabling a paravirtualized timer) as well as to data collection (sending
panic information to the hypervisor) and framebuffer management.
The thing is: some notifiers are related to others, ordering matters, some
functionalities are duplicated and there are lots of conditionals behind
sending panic information to the hypervisor. This patch, as part of an
effort to clean-up the panic notifiers mechanism and better document
things, address some of the issues/complexities of Hyper-V panic handling
through the following changes:
(a) We have die and panic notifiers on vmbus_drv.c and both have goals of
sending panic information to the hypervisor, though the panic notifier is
also responsible for a cleaning-up procedure.
This commit clears the code by splitting the panic notifier in two, one
for closing the vmbus connection whereas the other is only for sending
panic info to hypervisor. With that, it was possible to merge the die and
panic notifiers in a single/well-documented function, and clear some
conditional complexities on sending such information to the hypervisor.
(b) The new panic notifier created after (a) is only doing a single thing:
cleaning the vmbus connection. This procedure might cause a delay (due to
hypervisor I/O completion), so we postpone that to run late. But more
relevant: this *same* vmbus unloading happens in the crash_shutdown()
handler, so if kdump is set, we can safely skip this panic notifier and
defer such clean-up to the kexec crash handler.
(c) There is also a Hyper-V framebuffer panic notifier, which relies in
doing a vmbus operation that demands a valid connection. So, we must
order this notifier with the panic notifier from vmbus_drv.c, in order to
guarantee that the framebuffer code executes before the vmbus connection
is unloaded.
Also, this commit removes a useless header.
Although there is code rework and re-ordering, we expect that this change
has no functional regressions but instead optimize the path and increase
panic reliability on Hyper-V. This was tested on Hyper-V with success.
Fixes: 792f232d57ff ("Drivers: hv: vmbus: Fix potential crash on module unload")
Fixes: 74347a99e73a ("x86/Hyper-V: Unload vmbus channel in hv panic callback")
Cc: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Michael Kelley <redacted>
Cc: Stephen Hemminger <redacted>
Cc: Tianyu Lan <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Tested-by: Fabio A M Martins <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Special thanks to Michael Kelley for the good information about the Hyper-V
panic path in email threads some months ago, and to Fabio for the testing
performed.
Michael and all Microsoft folks: a careful analysis to double-check our changes
and assumptions here is really appreciated, this code is complex and intricate,
it is possible some corner case might have been overlooked.
Thanks in advance!
drivers/hv/vmbus_drv.c | 109 ++++++++++++++++++++------------
drivers/video/fbdev/hyperv_fb.c | 8 +++
2 files changed, 76 insertions(+), 41 deletions(-)
@@ -68,51 +68,75 @@ static int hyperv_report_reg(void)return!sysctl_record_panic_msg||!hv_panic_page;}-staticinthyperv_panic_event(structnotifier_block*nb,unsignedlongval,+/*+*Thepanicnotifierbelowisresponsiblesolelyforunloadingthe+*vmbusconnection,whichisnecessaryinapanicevent.Butnotice+*thatthissameunloadingprocedureisexecutedintheHyper-V+*crash_shutdown()handler[seehv_crash_handler()],whichbasically+*meansthatwecanpostponeitsexecutionifwehavekdumpset,+*sinceitwillrunthecrash_shutdown()handleranyway.Evenmore+*intrincatedistherelationofthisnotifierwithHyper-Vframebuffer+*panicnotifier-weneedvmbusconnectionalivethereinorderto+*succeed,soweneedtoorderbothwitheachother[forreferencesee+*hvfb_on_panic()]-thisisdoneusingnotifiers'priorities.+*/+staticinthv_panic_vmbus_unload(structnotifier_block*nb,unsignedlongval,void*args)+{+if(!kexec_crash_loaded())+vmbus_initiate_unload(true);++returnNOTIFY_DONE;+}+staticstructnotifier_blockhyperv_panic_vmbus_unload_block={+.notifier_call=hv_panic_vmbus_unload,+.priority=INT_MIN+1,/* almost the latest one to execute */+};++/*+*Thefollowingcallbackworksbothasdieandpanicnotifier;its+*goalistoprovidepanicinformationtothehypervisorunlessthe+*kmsgdumperisgonnabeused[seehv_kmsg_dump()],whichprovides+*moreinformationbutisnotalwaysavailable.+*+*Noticethatboththepanic/diereportnotifiersareregisteredonly+*ifwehavethecapabilityHV_FEATURE_GUEST_CRASH_MSR_AVAILABLEset.+*/+staticinthv_die_panic_notify_crash(structnotifier_block*nb,+unsignedlongval,void*args){structpt_regs*regs;+boolis_die;-vmbus_initiate_unload(true);--/*-*Hyper-Vshouldbenotifiedonlyonceaboutapanic.Ifwewillbe-*doinghv_kmsg_dump()withkmsgdatalater,don'tdothenotification-*here.-*/-if(ms_hyperv.misc_features&HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE-&&hyperv_report_reg()){+/* Don't notify Hyper-V unless we have a die oops event or panic. */+switch(val){+caseDIE_OOPS:+is_die=true;+regs=((structdie_args*)args)->regs;+break;+casePANIC_NOTIFIER:+is_die=false;regs=current_pt_regs();-hyperv_report_panic(regs,val,false);-}-returnNOTIFY_DONE;-}--staticinthyperv_die_event(structnotifier_block*nb,unsignedlongval,-void*args)-{-structdie_args*die=args;-structpt_regs*regs=die->regs;--/* Don't notify Hyper-V if the die event is other than oops */-if(val!=DIE_OOPS)+break;+default:returnNOTIFY_DONE;+}/*-*Hyper-Vshouldbenotifiedonlyonceaboutapanic.Ifwewillbe-*doinghv_kmsg_dump()withkmsgdatalater,don'tdothenotification-*here.+*Hyper-Vshouldbenotifiedonlyonceaboutapanic/die.Ifwewill+*becallinghv_kmsg_dump()laterwithkmsgdata,don'tdothe+*notificationhere.*/if(hyperv_report_reg())-hyperv_report_panic(regs,val,true);+hyperv_report_panic(regs,val,is_die);+returnNOTIFY_DONE;}--staticstructnotifier_blockhyperv_die_block={-.notifier_call=hyperv_die_event,+staticstructnotifier_blockhyperv_die_report_block={+.notifier_call=hv_die_panic_notify_crash,};-staticstructnotifier_blockhyperv_panic_block={-.notifier_call=hyperv_panic_event,+staticstructnotifier_blockhyperv_panic_report_block={+.notifier_call=hv_die_panic_notify_crash,};staticconstchar*fb_mmio_name="fb_range";
@@ -1589,16 +1613,17 @@ static int vmbus_bus_init(void)if(hyperv_crash_ctl&HV_CRASH_CTL_CRASH_NOTIFY_MSG)hv_kmsg_dump_register();-register_die_notifier(&hyperv_die_block);+register_die_notifier(&hyperv_die_report_block);+atomic_notifier_chain_register(&panic_notifier_list,+&hyperv_panic_report_block);}/*-*Alwaysregisterthepanicnotifierbecauseweneedtounload-*theVMbuschannelconnectiontopreventanyVMbus-*activityaftertheVMpanics.+*Alwaysregisterthevmbusunloadpanicnotifierbecausewe+*needtoshuttheVMbuschannelconnectiononpanic.*/atomic_notifier_chain_register(&panic_notifier_list,-&hyperv_panic_block);+&hyperv_panic_vmbus_unload_block);vmbus_request_offers();
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:57:27
The goal of this new panic notifier is to allow its users to register
callbacks to run very early in the panic path. This aims hypervisor/FW
notification mechanisms as well as simple LED functions, and any other
simple and safe mechanism that should run early in the panic path; more
dangerous callbacks should execute later.
For now, the patch is almost a no-op (although it changes a bit the
ordering in which some panic notifiers are executed). In a subsequent
patch, the panic path will be refactored, then the panic hypervisor
notifiers will effectively run very early in the panic path.
We also defer documenting it all properly in the subsequent refactor
patch. While at it, we removed some useless header inclusions and
fixed some notifiers return too (by using the standard NOTIFY_DONE).
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Christophe JAILLET <redacted>
Cc: David Gow <redacted>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Doug Berger <opendmb@gmail.com>
Cc: Evan Green <redacted>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Julius Werner <jwerner@chromium.org>
Cc: Justin Chen <redacted>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Lee Jones <redacted>
Cc: Markus Mayer <mmayer@broadcom.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michael Kelley <redacted>
Cc: Mihai Carabas <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Cc: Pavel Machek <redacted>
Cc: Scott Branden <scott.branden@broadcom.com>
Cc: Sebastian Reichel <sre@kernel.org>
Cc: Shile Zhang <redacted>
Cc: Stephen Hemminger <redacted>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Tianyu Lan <redacted>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Wang ShaoBo <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: zhenwei pi <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/mips/sgi-ip22/ip22-reset.c | 2 +-
arch/mips/sgi-ip32/ip32-reset.c | 3 +--
arch/powerpc/kernel/setup-common.c | 2 +-
arch/sparc/kernel/sstate.c | 3 +--
drivers/firmware/google/gsmi.c | 4 ++--
drivers/hv/vmbus_drv.c | 4 ++--
drivers/leds/trigger/ledtrig-activity.c | 4 ++--
drivers/leds/trigger/ledtrig-heartbeat.c | 4 ++--
drivers/misc/bcm-vk/bcm_vk_dev.c | 6 +++---
drivers/misc/pvpanic/pvpanic.c | 4 ++--
drivers/power/reset/ltc2952-poweroff.c | 4 ++--
drivers/s390/char/zcore.c | 5 +++--
drivers/soc/bcm/brcmstb/pm/pm-arm.c | 2 +-
include/linux/panic_notifier.h | 1 +
kernel/panic.c | 4 ++++
15 files changed, 28 insertions(+), 24 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:57:34
The goal of this new panic notifier is to allow its users to
register callbacks to run earlier in the panic path than they
currently do. This aims at informational mechanisms, like dumping
kernel offsets and showing device error data (in case it's simple
registers reading, for example) as well as mechanisms to disable
log flooding (like hung_task detector / RCU warnings) and the
tracing dump_on_oops (when enabled).
Any (non-invasive) information that should be provided before
kmsg_dump() as well as log flooding preventing code should fit
here, as long it offers relatively low risk for kdump.
For now, the patch is almost a no-op, although it changes a bit
the ordering in which some panic notifiers are executed - specially
affected by this are the notifiers responsible for disabling the
hung_task detector / RCU warnings, which now run first. In a
subsequent patch, the panic path will be refactored, then the
panic informational notifiers will effectively run earlier,
before ksmg_dump() (and usually before kdump as well).
We also defer documenting it all properly in the subsequent
refactor patch. Finally, while at it, we removed some useless
header inclusions too.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Frederic Weisbecker <frederic@kernel.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Joel Fernandes <redacted>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Lai Jiangshan <jiangshanlai@gmail.com>
Cc: Leo Yan <redacted>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Mike Leach <redacted>
Cc: Mikko Perttunen <mperttunen@nvidia.com>
Cc: Neeraj Upadhyay <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Thierry Reding <redacted>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/arm64/kernel/setup.c | 2 +-
arch/mips/kernel/relocate.c | 2 +-
arch/powerpc/kernel/setup-common.c | 2 +-
arch/x86/kernel/setup.c | 2 +-
drivers/bus/brcmstb_gisb.c | 2 +-
drivers/hwtracing/coresight/coresight-cpu-debug.c | 4 ++--
drivers/soc/tegra/ari-tegra186.c | 3 ++-
include/linux/panic_notifier.h | 1 +
kernel/hung_task.c | 3 ++-
kernel/panic.c | 4 ++++
kernel/rcu/tree.c | 1 -
kernel/rcu/tree_stall.h | 3 ++-
kernel/trace/trace.c | 2 +-
13 files changed, 19 insertions(+), 12 deletions(-)
@@ -757,7 +757,7 @@ void __init setup_panic(void)&ppc_fadump_block);if(IS_ENABLED(CONFIG_RANDOMIZE_BASE)&&kaslr_offset()>0)-atomic_notifier_chain_register(&panic_notifier_list,+atomic_notifier_chain_register(&panic_info_list,&kernel_offset_notifier);/* Low-level platform-specific routines that should run on panic */
@@ -535,7 +535,7 @@ static int debug_func_init(void)&debug_func_knob_fops);/* Register function to be called for panic */-ret=atomic_notifier_chain_register(&panic_notifier_list,+ret=atomic_notifier_chain_register(&panic_info_list,&debug_notifier);if(ret){pr_err("%s: unable to register notifier: %d\n",
@@ -552,7 +552,7 @@ static int debug_func_init(void)staticvoiddebug_func_exit(void){-atomic_notifier_chain_unregister(&panic_notifier_list,+atomic_notifier_chain_unregister(&panic_info_list,&debug_notifier);debugfs_remove_recursive(debug_debugfs_dir);}
@@ -85,6 +85,7 @@ hung_task_panic(struct notifier_block *this, unsigned long event, void *ptr)staticstructnotifier_blockpanic_block={.notifier_call=hung_task_panic,+.priority=INT_MAX,/* run early to prevent potential log flood */};staticvoidcheck_hung_task(structtask_struct*t,unsignedlongtimeout)
@@ -378,7 +379,7 @@ static int watchdog(void *dummy)staticint__inithung_task_init(void){-atomic_notifier_chain_register(&panic_notifier_list,&panic_block);+atomic_notifier_chain_register(&panic_info_list,&panic_block);/* Disable hung task detector on suspend */pm_notifier(hungtask_pm_notify,0);
@@ -97,11 +97,12 @@ static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)staticstructnotifier_blockrcu_panic_block={.notifier_call=rcu_panic,+.priority=INT_MAX,/* run early to prevent potential log flood */};staticint__initcheck_cpu_stall_init(void){-atomic_notifier_chain_register(&panic_notifier_list,&rcu_panic_block);+atomic_notifier_chain_register(&panic_info_list,&rcu_panic_block);return0;}early_initcall(check_cpu_stall_init);
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 22:58:40
This patch renames the panic_notifier_list to panic_pre_reboot_list;
the idea is that a subsequent patch will refactor the panic path
in order to better split the notifiers, running some of them very
early, some of them not so early [but still before kmsg_dump()] and
finally, the rest should execute late, after kdump. The latter ones
are now in the panic pre-reboot list - the name comes from the idea
that these notifiers execute before panic() attempts rebooting the
machine (if that option is set).
We also took the opportunity to clean-up useless header inclusions,
improve some notifier block declarations (e.g. in ibmasm/heartbeat.c)
and more important, change some priorities - we hereby set 2 notifiers
to run late in the list [iss_panic_event() and the IPMI panic_event()]
due to the risks they offer (may not return, for example).
Proper documentation is going to be provided in a subsequent patch,
that effectively refactors the panic path.
Cc: Alex Elder <elder@kernel.org>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Bjorn Andersson <redacted>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Chris Zankel <chris@zankel.net>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Corey Minyard <redacted>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Helge Deller <deller@gmx.de>
Cc: Ivan Kokshaysky <redacted>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: James Morse <james.morse@arm.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Juergen Gross <jgross@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <redacted>
Cc: Pavel Machek <redacted>
Cc: Richard Henderson <redacted>
Cc: Richard Weinberger <richard@nod.at>
Cc: Robert Richter <rric@kernel.org>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Stephen Hemminger <redacted>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Notice that, with this name change, out-of-tree code that relies in the global
exported "panic_notifier_list" will fail to build. We could easily keep the
retro-compatibility by making the old symbol to still exist and point to the
pre_reboot list (or even, keep the old naming).
But our design choice was to allow the breakage, making users rethink their
notifiers, adding them in the list that fits best. If that wasn't a good
decision, we're open to change it, of course.
Thanks in advance for the review!
arch/alpha/kernel/setup.c | 4 ++--
arch/parisc/kernel/pdc_chassis.c | 3 +--
arch/powerpc/kernel/setup-common.c | 2 +-
arch/s390/kernel/ipl.c | 4 ++--
arch/um/drivers/mconsole_kern.c | 2 +-
arch/um/kernel/um_arch.c | 2 +-
arch/x86/xen/enlighten.c | 2 +-
arch/xtensa/platforms/iss/setup.c | 4 ++--
drivers/char/ipmi/ipmi_msghandler.c | 12 +++++++-----
drivers/edac/altera_edac.c | 3 +--
drivers/hv/vmbus_drv.c | 4 ++--
drivers/leds/trigger/ledtrig-panic.c | 3 +--
drivers/misc/ibmasm/heartbeat.c | 16 +++++++++-------
drivers/net/ipa/ipa_smp2p.c | 5 ++---
drivers/parisc/power.c | 4 ++--
drivers/remoteproc/remoteproc_core.c | 6 ++++--
drivers/s390/char/con3215.c | 2 +-
drivers/s390/char/con3270.c | 2 +-
drivers/s390/char/sclp_con.c | 2 +-
drivers/s390/char/sclp_vt220.c | 2 +-
drivers/staging/olpc_dcon/olpc_dcon.c | 6 ++++--
drivers/video/fbdev/hyperv_fb.c | 4 ++--
include/linux/panic_notifier.h | 2 +-
kernel/panic.c | 9 ++++-----
24 files changed, 54 insertions(+), 51 deletions(-)
@@ -472,8 +472,8 @@ setup_arch(char **cmdline_p)}/* Register a call for panic conditions. */-atomic_notifier_chain_register(&panic_notifier_list,-&alpha_panic_block);+atomic_notifier_chain_register(&panic_pre_reboot_list,+&alpha_panic_block);#ifndef alpha_using_srm/* Assume that we've booted from SRM if we haven't booted from MILO.
@@ -762,7 +762,7 @@ void __init setup_panic(void)/* Low-level platform-specific routines that should run on panic */if(ppc_md.panic)-atomic_notifier_chain_register(&panic_notifier_list,+atomic_notifier_chain_register(&panic_pre_reboot_list,&ppc_panic_block);}
@@ -2034,7 +2034,7 @@ static int on_panic_notify(struct notifier_block *self,unsignedlongevent,void*data){do_panic();-returnNOTIFY_OK;+returnNOTIFY_DONE;}staticstructnotifier_blockon_panic_nb={
@@ -2069,7 +2069,7 @@ void __init setup_ipl(void)/* We have no info to copy */break;}-atomic_notifier_chain_register(&panic_notifier_list,&on_panic_nb);+atomic_notifier_chain_register(&panic_pre_reboot_list,&on_panic_nb);}voids390_reset_system(void)
@@ -53,6 +52,7 @@ iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)staticstructnotifier_blockiss_panic_block={.notifier_call=iss_panic_event,+.priority=INT_MIN,/* run as late as possible, may not return */};void__initplatform_setup(char**p_cmdline)
@@ -138,13 +137,13 @@ static int ipa_smp2p_panic_notifier_register(struct ipa_smp2p *smp2p)smp2p->panic_notifier.notifier_call=ipa_smp2p_panic_notifier;smp2p->panic_notifier.priority=INT_MAX;/* Do it early */-returnatomic_notifier_chain_register(&panic_notifier_list,+returnatomic_notifier_chain_register(&panic_pre_reboot_list,&smp2p->panic_notifier);}staticvoidipa_smp2p_panic_notifier_unregister(structipa_smp2p*smp2p){-atomic_notifier_chain_unregister(&panic_notifier_list,+atomic_notifier_chain_unregister(&panic_pre_reboot_list,&smp2p->panic_notifier);}
@@ -233,7 +233,7 @@ static int __init power_init(void)}/* Register a call for panic conditions. */-atomic_notifier_chain_register(&panic_notifier_list,+atomic_notifier_chain_register(&panic_pre_reboot_list,&parisc_panic_block);return0;
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:00:35
Currently we have 3 notifier lists in the panic path, which will
be wired in a way to allow the notifier callbacks to run in
different moments at panic time, in a subsequent patch.
But there is also an odd set of architecture calls hardcoded in
the end of panic path, after the restart machinery. They're
responsible for late time tunings / events, like enabling a stop
button (Sparc) or effectively stopping the machine (s390).
This patch introduces yet another notifier list to offer the
architectures a way to add callbacks in such late moment on
panic path without the need of ifdefs / hardcoded approaches.
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/s390/kernel/setup.c | 19 ++++++++++++++++++-
arch/sparc/kernel/setup_32.c | 27 +++++++++++++++++++++++----
arch/sparc/kernel/setup_64.c | 29 ++++++++++++++++++++++++-----
include/linux/panic_notifier.h | 1 +
kernel/panic.c | 19 +++++++------------
5 files changed, 73 insertions(+), 22 deletions(-)
@@ -1058,4 +1072,7 @@ void __init setup_arch(char **cmdline_p)/* Add system specific data to the random pool */setup_randomness();++atomic_notifier_chain_register(&panic_post_reboot_list,+&post_reboot_panic_block);}
@@ -293,6 +295,24 @@ void __init sparc32_start_kernel(struct linux_romvec *rp)start_kernel();}+/*+*Thefollowingnotifierexecutesasoneofthelatestthingsinthepanic+*path,onlyiftherestartroutinesweren'texecuted(ordidn'tsucceed).+*/+staticintpanic_event(structnotifier_block*n,unsignedlongev,void*unused)+{+/* Make sure the user can actually press Stop-A (L1-A) */+stop_a_enabled=1;+pr_emerg("Press Stop-A (L1-A) from sun keyboard or send break\n"+"twice on console to return to the boot prom\n");++returnNOTIFY_DONE;+}++staticstructnotifier_blockpost_reboot_panic_block={+.notifier_call=panic_event,+};+void__initsetup_arch(char**cmdline_p){inti;
@@ -62,6 +63,8 @@#include"entry.h"#include"kernel.h"+intstop_a_enabled=1;+/* Used to synchronize accesses to NatSemi SUPER I/O chip configure*operationsinasm/ns87303.h*/
@@ -632,6 +635,24 @@ void __init alloc_irqstack_bootmem(void)}}+/*+*Thefollowingnotifierexecutesasoneofthelatestthingsinthepanic+*path,onlyiftherestartroutinesweren'texecuted(ordidn'tsucceed).+*/+staticintpanic_event(structnotifier_block*n,unsignedlongev,void*unused)+{+/* Make sure the user can actually press Stop-A (L1-A) */+stop_a_enabled=1;+pr_emerg("Press Stop-A (L1-A) from sun keyboard or send break\n"+"twice on console to return to the boot prom\n");++returnNOTIFY_DONE;+}++staticstructnotifier_blockpost_reboot_panic_block={+.notifier_call=panic_event,+};+void__initsetup_arch(char**cmdline_p){/* Initialize PROM console and command line. */
@@ -359,18 +362,10 @@ void panic(const char *fmt, ...)reboot_mode=panic_reboot_mode;emergency_restart();}-#ifdef __sparc__-{-externintstop_a_enabled;-/* Make sure the user can actually press Stop-A (L1-A) */-stop_a_enabled=1;-pr_emerg("Press Stop-A (L1-A) from sun keyboard or send break\n"-"twice on console to return to the boot prom\n");-}-#endif-#if defined(CONFIG_S390)-disabled_wait();-#endif++atomic_notifier_call_chain(&panic_post_reboot_list,+PANIC_NOTIFIER,buf);+pr_emerg("---[ end Kernel panic - not syncing: %s ]---\n",buf);/* Do not scroll important messages printed above */
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:01:42
The panic() function is somewhat convoluted - a lot of changes were
made over the years, adding comments that might be misleading/outdated
now, it has a code structure that is a bit complex to follow, with
lots of conditionals, for example. The panic notifier list is something
else - a single list, with multiple callbacks of different purposes,
that run in a non-deterministic order and may affect hardly kdump
reliability - see the "crash_kexec_post_notifiers" workaround-ish flag.
This patch proposes a major refactor on the panic path based on Petr's
idea [0] - basically we split the notifiers list in three, having a set
of different call points in the panic path. Below a list of changes
proposed in this patch, culminating in the panic notifiers level
concept:
(a) First of all, we improved comments all over the function
and removed useless variables / includes. Also, as part of this
clean-up we concentrate the console flushing functions in a helper.
(b) As mentioned before, there is a split of the panic notifier list
in three, based on the purpose of the callback. The code contains
good documentation in form of comments, but a summary of the three
lists follows:
- the hypervisor list aims low-risk procedures to inform hypervisors
or firmware about the panic event, also includes LED-related functions;
- the informational list contains callbacks that provide more details,
like kernel offset or trace dump (if enabled) and also includes the
callbacks aimed at reducing log pollution or warns, like the RCU and
hung task disable callbacks;
- finally, the pre_reboot list is the old notifier list renamed,
containing the more risky callbacks that didn't fit the previous
lists. There is also a 4th list (the post_reboot one), but it's not
related with the original list - it contains late time architecture
callbacks aimed at stopping the machine, for example.
The 3 notifiers lists execute in different moments, hypervisor being
the first, followed by informational and finally the pre_reboot list.
(c) But then, there is the ordering problem of the notifiers against
the crash_kernel() call - kdump must be as reliable as possible.
For that, a simple binary "switch" as "crash_kexec_post_notifiers"
is not enough, hence we introduce here concept of panic notifier
levels: there are 5 levels, from 0 (no notifier executes before
kdump) until 4 (all notifiers run before kdump); the default level
is 2, in which the hypervisor and (iff we have any kmsg dumper)
the informational notifiers execute before kdump.
The detailed documentation of the levels is present in code comments
and in the kernel-parameters.txt file; as an analogy with the previous
panic() implementation, the level 0 is exactly the same as the old
behavior of notifiers, running all after kdump, and the level 4 is
the same as "crash_kexec_post_notifiers=Y" (we kept this parameter as
a deprecated one).
(d) Finally, an important change made here: we now use only the
function "crash_smp_send_stop()" to shut all the secondary CPUs
in the panic path. Before, there was a case of using the regular
"smp_send_stop()", but the better approach is to simplify the
code and try to use the function which was created exclusively
for the panic path. Experiments showed that it works fine, and
code was very simplified with that.
Functional change is expected from this refactor, since now we
call some notifiers by default before kdump, but the goal here
besides code clean-up is to have a better panic path, more
reliable and deterministic, but also very customizable.
[0] https://lore.kernel.org/lkml/YfPxvzSzDLjO5ldp@alley/
Suggested-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Special thanks to Petr and Baoquan for the suggestion and feedback in a previous
email thread. There's some important design decisions that worth mentioning and
discussing:
* The default panic notifiers level is 2, based on Petr Mladek's suggestion,
which makes a lot of sense. Of course, this is customizable through the
parameter, but would be something worthwhile to have a KConfig option to set
the default level? It would help distros that want the old behavior
(no notifiers before kdump) as default.
* The implementation choice was to _avoid_ intricate if conditionals in the
panic path, which would _definitely_ be present with the panic notifiers levels
idea; so, instead of lots of if conditionals, the set/clear bits approach with
functions called in 2 points (but executing only in one of them) is much easier
to follow an was used here; the ordering helper function and the comments also
help a lot to avoid confusion (hopefully).
* Choice was to *always* use crash_smp_send_stop() instead of sometimes making
use of the regular smp_send_stop(); for most architectures they are the same,
including Xen (on x86). For the ones that override it, all should work fine,
in the powerpc case it's even more correct (see the subsequent patch
"powerpc: Do not force all panic notifiers to execute before kdump")
There seems to be 2 cases that requires some plumbing to work 100% right:
- ARM doesn't disable local interrupts / FIQs in the crash version of
send_stop(); we patched that early in this series;
- x86 could face an issue if we have VMX and do use crash_smp_send_stop()
_without_ kdump, but this is fixed in the first patch of the series (and
it's a bug present even before this refactor).
* Notice we didn't add a sysrq for panic notifiers level - should have it?
Alejandro proposed recently to add a sysrq for "crash_kexec_post_notifiers",
let me know if you feel the need here Alejandro, since the core parameters are
present in /sys, I didn't consider much gain in having a sysrq, but of course
I'm open to suggestions!
Thanks advance for the review!
.../admin-guide/kernel-parameters.txt | 42 ++-
include/linux/panic_notifier.h | 1 +
kernel/kexec_core.c | 8 +-
kernel/panic.c | 292 +++++++++++++-----
.../selftests/pstore/pstore_crash_test | 5 +-
5 files changed, 252 insertions(+), 96 deletions(-)
@@ -829,6 +829,13 @@ It will be ignored when crashkernel=X,high is not used or memory reserved is below 4G.+ crash_kexec_post_notifiers+ This was DEPRECATED - users should always prefer the+ parameter "panic_notifiers_level" - check its entry+ in this documentation for details on how it works.+ Setting this parameter is exactly the same as setting+ "panic_notifiers_level=4".+ cryptomgr.notests [KNL] Disable crypto self-tests
@@ -3784,6 +3791,33 @@ timeout < 0: reboot immediately Format: <timeout>+ panic_notifiers_level=+ [KNL] Set the panic notifiers execution order.+ Format: <unsigned int>+ We currently have 4 lists of panic notifiers; based+ on the functionality and risk (for panic success) the+ callbacks are added in a given list. The lists are:+ - hypervisor/FW notification list (low risk);+ - informational list (low/medium risk);+ - pre_reboot list (higher risk);+ - post_reboot list (only run late in panic and after+ kdump, not configurable for now).+ This parameter defines the ordering of the first 3+ lists with regards to kdump; the levels determine+ which set of notifiers execute before kdump. The+ accepted levels are:+ 0: kdump is the first thing to run, NO list is+ executed before kdump.+ 1: only the hypervisor list is executed before kdump.+ 2 (default level): the hypervisor list and (*if*+ there's any kmsg_dumper defined) the informational+ list are executed before kdump.+ 3: both the hypervisor and the informational lists+ (always) execute before kdump.+ 4: the 3 lists (hypervisor, info and pre_reboot)+ execute before kdump - this behavior is analog to the+ deprecated parameter "crash_kexec_post_notifiers".+ panic_print= Bitmask for printing system info when panic happens. User can chose combination of the following bits: bit 0: print all tasks info
@@ -3814,14 +3848,6 @@ panic_on_warn panic() instead of WARN(). Useful to cause kdump on a WARN().- crash_kexec_post_notifiers- Run kdump after running panic-notifiers and dumping- kmsg. This only for the users who doubt kdump always- succeeds in any situation.- Note that this also increases risks of kdump failure,- because some panic notifiers can make the crashed- kernel more unstable.- parkbd.port= [HW] Parallel port number the keyboard adapter is connected to, default is 0. Format: <parport#>
@@ -52,14 +51,23 @@ static unsigned long tainted_mask =staticintpause_on_oops;staticintpause_on_oops_flag;staticDEFINE_SPINLOCK(pause_on_oops_lock);-boolcrash_kexec_post_notifiers;+intpanic_on_warn__read_mostly;+boolpanic_on_taint_nousertaint;unsignedlongpanic_on_taint;-boolpanic_on_taint_nousertaint=false;intpanic_timeout=CONFIG_PANIC_TIMEOUT;EXPORT_SYMBOL_GPL(panic_timeout);+/* Initialized with all notifiers set to run before kdump */+staticunsignedlongpanic_notifiers_bits=15;++/* Default level is 2, see kernel-parameters.txt */+unsignedintpanic_notifiers_level=2;++/* DEPRECATED in favor of panic_notifiers_level */+boolcrash_kexec_post_notifiers;+#define PANIC_PRINT_TASK_INFO 0x00000001#define PANIC_PRINT_MEM_INFO 0x00000002#define PANIC_PRINT_TIMER_INFO 0x00000004
@@ -266,73 +381,75 @@ void panic(const char *fmt, ...)kgdb_panic(buf);/*-*Ifwehavecrashedandwehaveacrashkernelloadedletithandle-*everythingelse.-*Ifwewanttorunthisaftercallingpanic_notifiers,pass-*the"crash_kexec_post_notifiers"optiontothekernel.+*Hereliesoneofthemostsubtlepartsofthepanicpath,+*thepanicnotifiersandtheirorderwithregardstokdump.+*Wecurrentlyhave4setsofnotifiers:*-*Bypassthepanic_cpucheckandcall__crash_kexecdirectly.+*-thehypervisorlistiscomposedbycallbacksthatarerelated+*towarntheFW/hypervisoraboutpanic,ornon-invasiveLED+*controllingfunctions-(hopefully)low-riskforkdump,should+*runearlyifpossible.+*+*-theinformationallistiscomposedbyfunctionsdumpingdata+*likekerneloffsets,deviceerrorregistersortracingbuffer;+*alsologfloodingpreventioncallbacksfitinthislist.Itis+*relativelysafetorunbeforekdump.+*+*-thepre_rebootlistbasicallyiseverythingelse,allthe+*callbacksthatdon'tfitinthe2previouslists.Itshould+*run*after*kdumpifpossible,asitcontainshigh-risk+*functionsthatmaybreakkdump.+*+*-wealsohavea4thlistofnotifiers,thepost_reboot+*callbacks.Thisisnotstronglyrelatedtokdumpsinceit's+*alwaysexecutedlateinthepanicpath,aftertherestart+*mechanism(ifset);itsgoalistoprovideawayfor+*architecturecodeeffectivelypower-off/disablethesystem.+*+*Thekernelprovidesthe"panic_notifiers_level"parameter+*toadjusttheorderinginwhichthesenotifiersshouldrun+*withregardstokdump-thedefaultlevelis2,soboththe+*hypervisorandinformationalnotifiersshouldexecutebefore+*the__crash_kexec();theinfonotifierwon'trunbydefault+*unlessthere'ssomekmsg_dumper()registered.Fordetails+*aboutit,checkDocumentation/admin-guide/kernel-parameters.txt.+*+*Noticethatthecodereliesinbitsset/clearoperationsto+*determinetheordering,functions*_once()executeonlyone+*time,astheirnameimplies.Thegoalistopreventtoomuch+*ifconditionalsandmoreconfusion.Finally,regardingCPUs+*disabling:unlessNOpanicnotifierexecutesbeforekdump,+*wealwaysdisablesecondaryCPUsbefore__crash_kexec()and+*thenotifiersexecute.*/-if(!_crash_kexec_post_notifiers){+order_panic_notifiers_and_kdump();++/* If no level, we should kdump ASAP. */+if(!panic_notifiers_level)__crash_kexec(NULL);-/*-*Notesmp_send_stopistheusualsmpshutdownfunction,which-*unfortunatelymeansitmaynotbehardenedtoworkina-*panicsituation.-*/-smp_send_stop();-}else{-/*-*Ifwewanttodocrashdumpafternotifiercallsand-*kmsg_dump,wewillneedarchitecturedependentextra-*worksinadditiontostoppingotherCPUs.-*/-crash_smp_send_stop();-}+crash_smp_send_stop();+panic_notifier_hypervisor_once(buf);-/*-*Runanypanichandlers,includingthosethatmightneedto-*addinformationtothekmsgdumpoutput.-*/-atomic_notifier_call_chain(&panic_hypervisor_list,PANIC_NOTIFIER,buf);-atomic_notifier_call_chain(&panic_info_list,PANIC_NOTIFIER,buf);-atomic_notifier_call_chain(&panic_pre_reboot_list,PANIC_NOTIFIER,buf);+if(panic_notifier_info_once(buf)){+panic_print_sys_info(false);+kmsg_dump(KMSG_DUMP_PANIC);+}-panic_print_sys_info(false);+panic_notifier_pre_reboot_once(buf);-kmsg_dump(KMSG_DUMP_PANIC);+__crash_kexec(NULL);-/*-*Ifyoudoubtkdumpalwaysworksfineinanysituation,-*"crash_kexec_post_notifiers"offersyouachancetorun-*panic_notifiersanddumpingkmsgbeforekdump.-*Note:sincesomepanic_notifierscanmakecrashedkernel-*moreunstable,itcanincreaserisksofthekdumpfailuretoo.-*-*Bypassthepanic_cpucheckandcall__crash_kexecdirectly.-*/-if(_crash_kexec_post_notifiers)-__crash_kexec(NULL);+panic_notifier_hypervisor_once(buf);-#ifdef CONFIG_VT-unblank_screen();-#endif-console_unblank();--/*-*WemayhaveendedupstoppingtheCPUholdingthelock(in-*smp_send_stop())whilestillhavingsomevaluabledataintheconsole-*buffer.Trytoacquirethelockthenreleaseitregardlessofthe-*result.Thereleasewillalsoprintthebuffersout.Locksdebug-*shouldbedisabledtoavoidreportingbadunlockbalancewhen-*panic()isnotbeingcallledfromOOPS.-*/-debug_locks_off();-console_flush_on_panic(CONSOLE_FLUSH_PENDING);+if(panic_notifier_info_once(buf)){+panic_print_sys_info(false);+kmsg_dump(KMSG_DUMP_PANIC);+}-panic_print_sys_info(true);+panic_notifier_pre_reboot_once(buf);+console_flushing();if(!panic_blink)panic_blink=no_blink;
@@ -363,8 +480,7 @@ void panic(const char *fmt, ...)emergency_restart();}-atomic_notifier_call_chain(&panic_post_reboot_list,-PANIC_NOTIFIER,buf);+panic_notifier_post_reboot_once(buf);pr_emerg("---[ end Kernel panic - not syncing: %s ]---\n",buf);
@@ -25,6 +25,7 @@ touch $REBOOT_FLAG sync # cause crash-# Note: If you use kdump and want to see kmesg-* files after reboot, you should-# specify 'crash_kexec_post_notifiers' in 1st kernel's cmdline.+# Note: If you use kdump and want to see kmsg-* files after reboot, you should+# be sure that the parameter "panic_notifiers_level" is more than '2' (the+# default value for this parameter is '2') in the first kernel's cmdline. echo c > /proc/sysrq-trigger
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:01:50
Currently we don't have a way to check if there are dumpers set,
except counting the list members maybe. This patch introduces a very
simple helper to provide this information, by just keeping track of
registered/unregistered kmsg dumpers. It's going to be used on the
panic path in the subsequent patch.
Notice that the spinlock guarding kmsg_dumpers list also guards
increment/decrement of the dumper's counter, but there's no need
for that when reading the counter in the panic path, since that is
an atomic path and there's no other (planned) user.
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
include/linux/kmsg_dump.h | 7 +++++++
kernel/printk/printk.c | 14 ++++++++++++++
2 files changed, 21 insertions(+)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:01:57
Currently the parameter "panic_print" relies in a function called
directly on panic path; one of the flags the users can set for
panic_print triggers a console replay mechanism, to show the
entire kernel log buffer (from the beginning) in a panic event.
Two problems with that: the dual nature of the panic_print
isn't really appropriate, the function was originally meant
to allow users dumping system information on panic events,
and was "overridden" to also force a console flush of the full
kernel log buffer. It also turns the code a bit more complex
and duplicate than it needs to be.
This patch proposes 2 changes: first, we decouple panic_print
from the console flushing mechanism, in the form of a new kernel
core parameter (panic_console_replay); we kept the functionality
on panic_print to avoid userspace breakage, although we comment
in both code and documentation that this panic_print usage is
deprecated.
We converted panic_print function to a panic notifier too, adding
it on the panic informational notifier list, executed as the final
callback. This allows a more clear code and makes sense, as
panic_print_sys_info() is really a panic-time only function.
We also moved its code to kernel/printk.c, it seems to make more
sense given it's related to printing stuff.
Suggested-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
.../admin-guide/kernel-parameters.txt | 12 +++-
Documentation/admin-guide/sysctl/kernel.rst | 5 +-
include/linux/console.h | 2 +
include/linux/panic.h | 1 -
include/linux/printk.h | 1 +
kernel/panic.c | 51 +++------------
kernel/printk/printk.c | 62 +++++++++++++++++++
7 files changed, 87 insertions(+), 47 deletions(-)
@@ -3791,6 +3791,14 @@ timeout < 0: reboot immediately Format: <timeout>+ panic_console_replay+ [KNL] Force a kernel log replay in the console on+ panic event. Notice that there is already a flush+ mechanism for pending messages; this option is meant+ for users that wish to replay the *full* buffer.+ It deprecates the bit 5 setting on "panic_print",+ both having the same functionality.+ panic_notifiers_level= [KNL] Set the panic notifiers execution order. Format: <unsigned int>
@@ -3825,12 +3833,14 @@ bit 2: print timer info bit 3: print locks info if CONFIG_LOCKDEP is on bit 4: print ftrace buffer- bit 5: print all printk messages in buffer+ bit 5: print all printk messages in buffer (DEPRECATED) bit 6: print all CPUs backtrace (if available in the arch) *Be aware* that this option may print a _lot_ of lines, so there are risks of losing older messages in the log. Use this option carefully, maybe worth to setup a bigger log buffer with "log_buf_len" along with this.+ Also, notice that bit 5 was deprecated in favor of the+ parameter "panic_console_replay". panic_on_taint= Bitmask for conditionally calling panic() in add_taint() Format: <hex>[,nousertaint]
@@ -763,10 +763,13 @@ bit 1 print system memory info bit 2 print timer info bit 3 print locks info if ``CONFIG_LOCKDEP`` is on bit 4 print ftrace buffer-bit 5 print all printk messages in buffer+bit 5 print all printk messages in buffer (DEPRECATED) bit 6 print all CPUs backtrace (if available in the arch) ===== ============================================+Notice that bit 5 was deprecated in favor of kernel core parameter+"panic_console_replay" (see kernel-parameters.txt documentation).+ So for example to print tasks and memory info on panic, user can:: echo 3 > /proc/sys/kernel/panic_print
@@ -13,6 +13,7 @@externconstcharlinux_banner[];externconstcharlinux_proc_banner[];+externunsignedlongpanic_print;externintoops_in_progress;/* If set, an oops, panic(), BUG() or die() is in progress */#define PRINTK_MAX_SINGLE_HEADER_LEN 2
@@ -218,7 +182,11 @@ static void console_flushing(void)debug_locks_off();console_flush_on_panic(CONSOLE_FLUSH_PENDING);-panic_print_sys_info(true);+/* In case users wish to replay the full log buffer... */+if(panic_console_replay){+pr_warn("Replaying the log buffer from the beginning\n");+console_flush_on_panic(CONSOLE_REPLAY_ALL);+}}#define PN_HYPERVISOR_BIT 0
@@ -3234,6 +3235,61 @@ void __init console_init(void)}}+#define PANIC_PRINT_TASK_INFO 0x00000001+#define PANIC_PRINT_MEM_INFO 0x00000002+#define PANIC_PRINT_TIMER_INFO 0x00000004+#define PANIC_PRINT_LOCK_INFO 0x00000008+#define PANIC_PRINT_FTRACE_INFO 0x00000010++/* DEPRECATED - please use "panic_console_replay" */+#define PANIC_PRINT_ALL_PRINTK_MSG 0x00000020++#define PANIC_PRINT_ALL_CPU_BT 0x00000040++unsignedlongpanic_print;+boolpanic_console_replay;++staticintpanic_print_sys_info(structnotifier_block*self,+unsignedlongev,void*unused)+{+if(panic_print&PANIC_PRINT_ALL_CPU_BT)+trigger_all_cpu_backtrace();++if(panic_print&PANIC_PRINT_TASK_INFO)+show_state();++if(panic_print&PANIC_PRINT_MEM_INFO)+show_mem(0,NULL);++if(panic_print&PANIC_PRINT_TIMER_INFO)+sysrq_timer_list_show();++if(panic_print&PANIC_PRINT_LOCK_INFO)+debug_show_all_locks();++if(panic_print&PANIC_PRINT_FTRACE_INFO)+ftrace_dump(DUMP_ALL);++/*+*Thisislegacy/deprecatedfeaturefrompanic_print,+*theconsoleforceflushing.Wehavenowtheparameter+*"panic_console_replay",butweneedtokeepthe+*retro-compatibilitywiththeoldstuff...+*/+if(panic_print&PANIC_PRINT_ALL_PRINTK_MSG)+panic_console_replay=true;++returnNOTIFY_DONE;+}++staticstructnotifier_blockpanic_print_nb={+.notifier_call=panic_print_sys_info,+.priority=INT_MIN,/* defer to run as late as possible */+};++core_param(panic_print,panic_print,ulong,0644);+core_param(panic_console_replay,panic_console_replay,bool,0644);+/**Somebootconsolesaccessdatathatisintheinitsectionandwhichwill*bediscardedaftertheinitcallshavebeenrun.Tomakesurethatnocode
@@ -3253,6 +3309,12 @@ static int __init printk_late_init(void)structconsole*con;intret;+/*+*Registerthepanicnotifiertoprintuserinformation+*incasetheuserhavethatset.+*/+atomic_notifier_chain_register(&panic_info_list,&panic_print_nb);+for_each_console(con){if(!(con->flags&CON_BOOT))continue;
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:02:01
Since commit a11589563e96 ("x86/Hyper-V: Report crash register
data or kmsg before running crash kernel") Hyper-V forcibly sets
the kernel parameter "crash_kexec_post_notifiers"; with that, it
did enforce the execution of *all* panic notifiers before kdump.
The main reason behind that is that Hyper-V has an hypervisor
notification mechanism that has the ability of warning the
hypervisor when the guest panics.
Happens that after the panic notifiers refactor, we now have 3 lists
and a level mechanism that defines the ordering of the notifiers
execution with regards to kdump. And for Hyper-V, the specific
notifier to inform the hypervisor about a panic lies in the first
list, which *by default* is set to execute before kdump. Hence,
this patch removes the hardcoded setting, effectively reverting
the aforementioned commit.
One of the problems with the forced approach was greatly exposed by
commit d57d6fe5bf34 ("drivers: hv: log when enabling crash_kexec_post_notifiers")
which ended-up confusing the user that didn't expect the notifiers
to execute before kdump, since it's a user setting and wasn't
enabled by such user. With the patch hereby proposed, that kind
of issue doesn't happen anymore, the panic notifiers level is
well-documented and users can expect a predictable behavior.
Fixes: a11589563e96 ("x86/Hyper-V: Report crash register data or kmsg before running crash kernel")
Fixes: d57d6fe5bf34 ("drivers: hv: log when enabling crash_kexec_post_notifiers"
Cc: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Michael Kelley <redacted>
Cc: Stephen Brennan <redacted>
Cc: Stephen Hemminger <redacted>
Cc: Tianyu Lan <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Tested-by: Fabio A M Martins <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Special thanks to Michael Kelley for the good information about the Hyper-V
panic path in email threads some months ago, and to Fabio for the testing
performed.
drivers/hv/hv_common.c | 12 ------------
1 file changed, 12 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:02:10
Commit 06e629c25daa ("powerpc/fadump: Fix inaccurate CPU state info in
vmcore generated with panic") introduced a hardcoded setting of kernel
parameter "crash_kexec_post_notifiers", effectively forcing all the
panic notifiers to execute earlier in the panic path, before kdump.
The reason for that was a fadump issue on collecting data accurately,
due to smp_send_stop() setting all CPUs offline, so the net effect
desired with this change was to avoid calling the regular CPU
shutdown function, and instead rely on crash_smp_send_stop(), which
copes fine with fadump. The collateral effect was to increase the
risk for kdump if fadump is not used, since it forces all panic
notifiers to execute early, before kdump.
Happens that, after a panic refactor, crash_smp_send_stop() is
now used by default in the panic path, so there is no reason to
mess with the notifiers ordering (which was also improved in the
refactor) from within arch code.
Fixes: 06e629c25daa ("powerpc/fadump: Fix inaccurate CPU state info in vmcore generated with panic")
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
We'd like to thanks specially the MiniCloud infrastructure [0] maintainers,
that allow us to test PowerPC code in a very complete, functional and FREE
environment.
[0] https://openpower.ic.unicamp.br/minicloud
arch/powerpc/kernel/fadump.c | 8 --------
1 file changed, 8 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:02:19
There is no users anymore of this variable that requires
it to be "exported" in the headers; also, it was deprecated
by the kernel parameter "panic_notifiers_level".
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
include/linux/panic.h | 2 --
include/linux/panic_notifier.h | 1 -
2 files changed, 3 deletions(-)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:02:29
Currently both pseries and ps3 are platforms that define special
panic notifiers that run as callbacks inside powerpc generic panic
notifier. In both cases kmsg_dump() is called, and the reason seems
to be that both of these callbacks aims to effectively stop the
machine, so nothing would execute after that - hence, both force
a series of console flushing related operations, after calling
the kmsg dumpers.
Happens that recently the panic path was refactored, and now
kmsg_dump() is *certainly* called before the pre_reboot panic
notifiers, category in which both pseries/ps3 callbacks belong.
In other words: kmsg_dump() will execute twice in both platforms,
on panic path.
This patch prevents that by disabling the kmsg_dump() for both
platform's notifiers. But worth to notice that PowerNV still
has a legit use for executing kmsg_dump() in its unrecoverable
error path, so we rely in parameter passing to differentiate
both cases. Also, since the pre_reboot notifiers still run
earlier than console flushing routines, we kept that for
both pseries and ps3 platforms, only skipping kmsg_dump().
Fixes: 35adacd6fc48 ("powerpc/pseries, ps3: panic flush kernel messages before halting system")
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
We'd like to thanks specially the MiniCloud infrastructure [0] maintainers,
that allow us to test PowerPC code in a very complete, functional and FREE
environment.
[0] https://openpower.ic.unicamp.br/minicloud
arch/powerpc/include/asm/bug.h | 2 +-
arch/powerpc/kernel/traps.c | 6 ++++--
arch/powerpc/platforms/powernv/opal.c | 2 +-
arch/powerpc/platforms/ps3/setup.c | 2 +-
arch/powerpc/platforms/pseries/setup.c | 2 +-
5 files changed, 8 insertions(+), 6 deletions(-)
@@ -102,7 +102,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();+panic_flush_kmsg_end(false);while(1)lv1_pause(1);
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-27 23:02:54
Currently the panic notifier panic_exit() calls kmsg_dump() and
some console flushing routines - this makes sense since such
panic notifier exits UserMode Linux and never returns.
Happens that after a panic refactor, kmsg_dump() is now always
called *before* the pre_reboot list of panic notifiers, in which
panic_exit() belongs, leading to a double call situation.
This patch changes that by removing such call from the panic
notifier, but leaving the console flushing calls since the
pre_reboot list still runs before console flushing on panic().
Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Richard Weinberger <richard@nod.at>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/um/kernel/um_arch.c | 1 -
1 file changed, 1 deletion(-)
From: "Paul E. McKenney" <paulmck@kernel.org> Date: 2022-04-27 23:50:00
On Wed, Apr 27, 2022 at 07:49:14PM -0300, Guilherme G. Piccoli wrote:
The goal of this new panic notifier is to allow its users to
register callbacks to run earlier in the panic path than they
currently do. This aims at informational mechanisms, like dumping
kernel offsets and showing device error data (in case it's simple
registers reading, for example) as well as mechanisms to disable
log flooding (like hung_task detector / RCU warnings) and the
tracing dump_on_oops (when enabled).
Any (non-invasive) information that should be provided before
kmsg_dump() as well as log flooding preventing code should fit
here, as long it offers relatively low risk for kdump.
For now, the patch is almost a no-op, although it changes a bit
the ordering in which some panic notifiers are executed - specially
affected by this are the notifiers responsible for disabling the
hung_task detector / RCU warnings, which now run first. In a
subsequent patch, the panic path will be refactored, then the
panic informational notifiers will effectively run earlier,
before ksmg_dump() (and usually before kdump as well).
We also defer documenting it all properly in the subsequent
refactor patch. Finally, while at it, we removed some useless
header inclusions too.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Frederic Weisbecker <frederic@kernel.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Joel Fernandes <redacted>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Lai Jiangshan <jiangshanlai@gmail.com>
Cc: Leo Yan <redacted>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Mike Leach <redacted>
Cc: Mikko Perttunen <mperttunen@nvidia.com>
Cc: Neeraj Upadhyay <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Thierry Reding <redacted>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
From an RCU perspective:
Acked-by: Paul E. McKenney <paulmck@kernel.org>
@@ -757,7 +757,7 @@ void __init setup_panic(void)&ppc_fadump_block);if(IS_ENABLED(CONFIG_RANDOMIZE_BASE)&&kaslr_offset()>0)-atomic_notifier_chain_register(&panic_notifier_list,+atomic_notifier_chain_register(&panic_info_list,&kernel_offset_notifier);/* Low-level platform-specific routines that should run on panic */
@@ -535,7 +535,7 @@ static int debug_func_init(void)&debug_func_knob_fops);/* Register function to be called for panic */-ret=atomic_notifier_chain_register(&panic_notifier_list,+ret=atomic_notifier_chain_register(&panic_info_list,&debug_notifier);if(ret){pr_err("%s: unable to register notifier: %d\n",
@@ -552,7 +552,7 @@ static int debug_func_init(void)staticvoiddebug_func_exit(void){-atomic_notifier_chain_unregister(&panic_notifier_list,+atomic_notifier_chain_unregister(&panic_info_list,&debug_notifier);debugfs_remove_recursive(debug_debugfs_dir);}
@@ -85,6 +85,7 @@ hung_task_panic(struct notifier_block *this, unsigned long event, void *ptr)staticstructnotifier_blockpanic_block={.notifier_call=hung_task_panic,+.priority=INT_MAX,/* run early to prevent potential log flood */};staticvoidcheck_hung_task(structtask_struct*t,unsignedlongtimeout)
@@ -378,7 +379,7 @@ static int watchdog(void *dummy)staticint__inithung_task_init(void){-atomic_notifier_chain_register(&panic_notifier_list,&panic_block);+atomic_notifier_chain_register(&panic_info_list,&panic_block);/* Disable hung task detector on suspend */pm_notifier(hungtask_pm_notify,0);
@@ -97,11 +97,12 @@ static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)staticstructnotifier_blockrcu_panic_block={.notifier_call=rcu_panic,+.priority=INT_MAX,/* run early to prevent potential log flood */};staticint__initcheck_cpu_stall_init(void){-atomic_notifier_chain_register(&panic_notifier_list,&rcu_panic_block);+atomic_notifier_chain_register(&panic_info_list,&rcu_panic_block);return0;}early_initcall(check_cpu_stall_init);
From: Randy Dunlap <rdunlap@infradead.org> Date: 2022-04-28 00:29:01
On 4/27/22 15:49, Guilherme G. Piccoli wrote:
+ crash_kexec_post_notifiers
+ This was DEPRECATED - users should always prefer the
This is DEPRECATED - users should always prefer the
+ parameter "panic_notifiers_level" - check its entry
+ in this documentation for details on how it works.
+ Setting this parameter is exactly the same as setting
+ "panic_notifiers_level=4".
From: Xiaoming Ni <hidden> Date: 2022-04-28 01:01:31
On 2022/4/28 6:49, Guilherme G. Piccoli wrote:
quoted hunk
Currently we have a debug infrastructure in the notifiers file, but
it's very simple/limited. This patch extends it by:
(a) Showing all registered/unregistered notifiers' callback names;
(b) Adding a dynamic debug tuning to allow showing called notifiers'
function names. Notice that this should be guarded as a tunable since
it can flood the kernel log buffer.
Cc: Arjan van de Ven <redacted>
Cc: Cong Wang <redacted>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Valentin Schneider <redacted>
Cc: Xiaoming Ni <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
We have some design decisions that worth discussing here:
(a) First of call, using C99 helps a lot to write clear and concise code, but
due to commit 4d94f910e79a ("Kbuild: use -Wdeclaration-after-statement") we
have a warning if mixing variable declarations with code. For this patch though,
doing that makes the code way clear, so decision was to add the debug code
inside brackets whenever this warning pops up. We can change that, but that'll
cause more ifdefs in the same function.
(b) In the symbol lookup helper function, we modify the parameter passed but
even more, we return it as well! This is unusual and seems unnecessary, but was
the strategy taken to allow embedding such function in the pr_debug() call.
Not doing that would likely requiring 3 symbol_name variables to avoid
concurrency (registering notifier A while calling notifier B) - we rely in
local variables as a serialization mechanism.
We're open for suggestions in case this design is not appropriate;
thanks in advance!
kernel/notifier.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2022-04-28 08:11:46
Hi Guilherme,
On 27/04/2022 23:49, Guilherme G. Piccoli wrote:
The panic notifier infrastructure executes registered callbacks when
a panic event happens - such callbacks are executed in atomic context,
with interrupts and preemption disabled in the running CPU and all other
CPUs disabled. That said, mutexes in such context are not a good idea.
This patch replaces a regular mutex with a mutex_trylock safer approach;
given the nature of the mutex used in the driver, it should be pretty
uncommon being unable to acquire such mutex in the panic path, hence
no functional change should be observed (and if it is, that would be
likely a deadlock with the regular mutex).
Fixes: 2227b7c74634 ("coresight: add support for CPU debug module")
Cc: Leo Yan <redacted>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Mike Leach <redacted>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
How would you like to proceed with queuing this ? I am happy
either way. In case you plan to push this as part of this
series (I don't see any potential conflicts) :
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
From: Suzuki K Poulose <suzuki.poulose@arm.com> Date: 2022-04-28 08:14:34
On 27/04/2022 23:49, Guilherme G. Piccoli wrote:
The goal of this new panic notifier is to allow its users to
register callbacks to run earlier in the panic path than they
currently do. This aims at informational mechanisms, like dumping
kernel offsets and showing device error data (in case it's simple
registers reading, for example) as well as mechanisms to disable
log flooding (like hung_task detector / RCU warnings) and the
tracing dump_on_oops (when enabled).
Any (non-invasive) information that should be provided before
kmsg_dump() as well as log flooding preventing code should fit
here, as long it offers relatively low risk for kdump.
For now, the patch is almost a no-op, although it changes a bit
the ordering in which some panic notifiers are executed - specially
affected by this are the notifiers responsible for disabling the
hung_task detector / RCU warnings, which now run first. In a
subsequent patch, the panic path will be refactored, then the
panic informational notifiers will effectively run earlier,
before ksmg_dump() (and usually before kdump as well).
We also defer documenting it all properly in the subsequent
refactor patch. Finally, while at it, we removed some useless
header inclusions too.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Frederic Weisbecker <frederic@kernel.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Joel Fernandes <redacted>
Cc: Jonathan Hunter <jonathanh@nvidia.com>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Lai Jiangshan <jiangshanlai@gmail.com>
Cc: Leo Yan <redacted>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Mike Leach <redacted>
Cc: Mikko Perttunen <mperttunen@nvidia.com>
Cc: Neeraj Upadhyay <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Thierry Reding <redacted>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/arm64/kernel/setup.c | 2 +-
arch/mips/kernel/relocate.c | 2 +-
arch/powerpc/kernel/setup-common.c | 2 +-
arch/x86/kernel/setup.c | 2 +-
drivers/bus/brcmstb_gisb.c | 2 +-
drivers/hwtracing/coresight/coresight-cpu-debug.c | 4 ++--
drivers/soc/tegra/ari-tegra186.c | 3 ++-
include/linux/panic_notifier.h | 1 +
kernel/hung_task.c | 3 ++-
kernel/panic.c | 4 ++++
kernel/rcu/tree.c | 1 -
kernel/rcu/tree_stall.h | 3 ++-
kernel/trace/trace.c | 2 +-
13 files changed, 19 insertions(+), 12 deletions(-)
@@ -535,7 +535,7 @@ static int debug_func_init(void)&debug_func_knob_fops);/* Register function to be called for panic */-ret=atomic_notifier_chain_register(&panic_notifier_list,+ret=atomic_notifier_chain_register(&panic_info_list,&debug_notifier);if(ret){pr_err("%s: unable to register notifier: %d\n",
@@ -552,7 +552,7 @@ static int debug_func_init(void)staticvoiddebug_func_exit(void){-atomic_notifier_chain_unregister(&panic_notifier_list,+atomic_notifier_chain_unregister(&panic_info_list,&debug_notifier);debugfs_remove_recursive(debug_debugfs_dir);}
Acked-by: Suzuki K Poulose <suzuki.poulose@arm.com>
From: Alex Elder <hidden> Date: 2022-04-28 14:13:36
On 4/27/22 5:49 PM, Guilherme G. Piccoli wrote:
This patch renames the panic_notifier_list to panic_pre_reboot_list;
the idea is that a subsequent patch will refactor the panic path
in order to better split the notifiers, running some of them very
early, some of them not so early [but still before kmsg_dump()] and
finally, the rest should execute late, after kdump. The latter ones
are now in the panic pre-reboot list - the name comes from the idea
that these notifiers execute before panic() attempts rebooting the
machine (if that option is set).
We also took the opportunity to clean-up useless header inclusions,
improve some notifier block declarations (e.g. in ibmasm/heartbeat.c)
and more important, change some priorities - we hereby set 2 notifiers
to run late in the list [iss_panic_event() and the IPMI panic_event()]
due to the risks they offer (may not return, for example).
Proper documentation is going to be provided in a subsequent patch,
that effectively refactors the panic path.
Cc: Alex Elder <elder@kernel.org>
For "drivers/net/ipa/ipa_smp2p.c":
Acked-by: Alex Elder <elder@kernel.org>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Bjorn Andersson <redacted>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Chris Zankel <chris@zankel.net>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Corey Minyard <redacted>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Helge Deller <deller@gmx.de>
Cc: Ivan Kokshaysky <redacted>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: James Morse <james.morse@arm.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Juergen Gross <jgross@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <redacted>
Cc: Pavel Machek <redacted>
Cc: Richard Henderson <redacted>
Cc: Richard Weinberger <richard@nod.at>
Cc: Robert Richter <rric@kernel.org>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Stephen Hemminger <redacted>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
On Wed, Apr 27, 2022 at 07:49:15PM -0300, Guilherme G. Piccoli wrote:
This patch renames the panic_notifier_list to panic_pre_reboot_list;
the idea is that a subsequent patch will refactor the panic path
in order to better split the notifiers, running some of them very
early, some of them not so early [but still before kmsg_dump()] and
finally, the rest should execute late, after kdump. The latter ones
are now in the panic pre-reboot list - the name comes from the idea
that these notifiers execute before panic() attempts rebooting the
machine (if that option is set).
We also took the opportunity to clean-up useless header inclusions,
improve some notifier block declarations (e.g. in ibmasm/heartbeat.c)
and more important, change some priorities - we hereby set 2 notifiers
to run late in the list [iss_panic_event() and the IPMI panic_event()]
due to the risks they offer (may not return, for example).
Proper documentation is going to be provided in a subsequent patch,
that effectively refactors the panic path.
For the IPMI portion:
Acked-by: Corey Minyard <redacted>
Note that the IPMI panic_event() should always return, but it may take
some time, especially if the IPMI controller is no longer functional.
So the risk of a long delay is there and it makes sense to move it very
late.
-corey
quoted hunk
Cc: Alex Elder <elder@kernel.org>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Bjorn Andersson <redacted>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Chris Zankel <chris@zankel.net>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Corey Minyard <redacted>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Helge Deller <deller@gmx.de>
Cc: Ivan Kokshaysky <redacted>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Cc: James Morse <james.morse@arm.com>
Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: Juergen Gross <jgross@suse.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Max Filippov <jcmvbkbc@gmail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Paul Mackerras <redacted>
Cc: Pavel Machek <redacted>
Cc: Richard Henderson <redacted>
Cc: Richard Weinberger <richard@nod.at>
Cc: Robert Richter <rric@kernel.org>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Stephen Hemminger <redacted>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Wei Liu <wei.liu@kernel.org>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Notice that, with this name change, out-of-tree code that relies in the global
exported "panic_notifier_list" will fail to build. We could easily keep the
retro-compatibility by making the old symbol to still exist and point to the
pre_reboot list (or even, keep the old naming).
But our design choice was to allow the breakage, making users rethink their
notifiers, adding them in the list that fits best. If that wasn't a good
decision, we're open to change it, of course.
Thanks in advance for the review!
arch/alpha/kernel/setup.c | 4 ++--
arch/parisc/kernel/pdc_chassis.c | 3 +--
arch/powerpc/kernel/setup-common.c | 2 +-
arch/s390/kernel/ipl.c | 4 ++--
arch/um/drivers/mconsole_kern.c | 2 +-
arch/um/kernel/um_arch.c | 2 +-
arch/x86/xen/enlighten.c | 2 +-
arch/xtensa/platforms/iss/setup.c | 4 ++--
drivers/char/ipmi/ipmi_msghandler.c | 12 +++++++-----
drivers/edac/altera_edac.c | 3 +--
drivers/hv/vmbus_drv.c | 4 ++--
drivers/leds/trigger/ledtrig-panic.c | 3 +--
drivers/misc/ibmasm/heartbeat.c | 16 +++++++++-------
drivers/net/ipa/ipa_smp2p.c | 5 ++---
drivers/parisc/power.c | 4 ++--
drivers/remoteproc/remoteproc_core.c | 6 ++++--
drivers/s390/char/con3215.c | 2 +-
drivers/s390/char/con3270.c | 2 +-
drivers/s390/char/sclp_con.c | 2 +-
drivers/s390/char/sclp_vt220.c | 2 +-
drivers/staging/olpc_dcon/olpc_dcon.c | 6 ++++--
drivers/video/fbdev/hyperv_fb.c | 4 ++--
include/linux/panic_notifier.h | 2 +-
kernel/panic.c | 9 ++++-----
24 files changed, 54 insertions(+), 51 deletions(-)
@@ -472,8 +472,8 @@ setup_arch(char **cmdline_p)}/* Register a call for panic conditions. */-atomic_notifier_chain_register(&panic_notifier_list,-&alpha_panic_block);+atomic_notifier_chain_register(&panic_pre_reboot_list,+&alpha_panic_block);#ifndef alpha_using_srm/* Assume that we've booted from SRM if we haven't booted from MILO.
@@ -762,7 +762,7 @@ void __init setup_panic(void)/* Low-level platform-specific routines that should run on panic */if(ppc_md.panic)-atomic_notifier_chain_register(&panic_notifier_list,+atomic_notifier_chain_register(&panic_pre_reboot_list,&ppc_panic_block);}
@@ -2034,7 +2034,7 @@ static int on_panic_notify(struct notifier_block *self,unsignedlongevent,void*data){do_panic();-returnNOTIFY_OK;+returnNOTIFY_DONE;}staticstructnotifier_blockon_panic_nb={
@@ -2069,7 +2069,7 @@ void __init setup_ipl(void)/* We have no info to copy */break;}-atomic_notifier_chain_register(&panic_notifier_list,&on_panic_nb);+atomic_notifier_chain_register(&panic_pre_reboot_list,&on_panic_nb);}voids390_reset_system(void)
@@ -53,6 +52,7 @@ iss_panic_event(struct notifier_block *this, unsigned long event, void *ptr)staticstructnotifier_blockiss_panic_block={.notifier_call=iss_panic_event,+.priority=INT_MIN,/* run as late as possible, may not return */};void__initplatform_setup(char**p_cmdline)
@@ -138,13 +137,13 @@ static int ipa_smp2p_panic_notifier_register(struct ipa_smp2p *smp2p)smp2p->panic_notifier.notifier_call=ipa_smp2p_panic_notifier;smp2p->panic_notifier.priority=INT_MAX;/* Do it early */-returnatomic_notifier_chain_register(&panic_notifier_list,+returnatomic_notifier_chain_register(&panic_pre_reboot_list,&smp2p->panic_notifier);}staticvoidipa_smp2p_panic_notifier_unregister(structipa_smp2p*smp2p){-atomic_notifier_chain_unregister(&panic_notifier_list,+atomic_notifier_chain_unregister(&panic_pre_reboot_list,&smp2p->panic_notifier);}
@@ -233,7 +233,7 @@ static int __init power_init(void)}/* Register a call for panic conditions. */-atomic_notifier_chain_register(&panic_notifier_list,+atomic_notifier_chain_register(&panic_pre_reboot_list,&parisc_panic_block);return0;
The panic notifiers' callbacks execute in an atomic context, with
interrupts/preemption disabled, and all CPUs not running the panic
function are off, so it's very dangerous to wait on a regular
spinlock, there's a risk of deadlock.
This patch refactors the panic notifier of parisc/power driver
to make use of spin_trylock - for that, we've added a second
version of the soft-power function. Also, some comments were
reorganized and trailing white spaces, useless header inclusion
and blank lines were removed.
Cc: Helge Deller <deller@gmx.de>
Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
You may add:
Acked-by: Helge Deller <deller@gmx.de> # parisc
Helge
@@ -83,6 +83,7 @@ int pdc_do_firm_test_reset(unsigned long ftc_bitmap);intpdc_do_reset(void);intpdc_soft_power_info(unsignedlong*power_reg);intpdc_soft_power_button(intsw_control);+intpdc_soft_power_button_panic(intsw_control);voidpdc_io_reset(void);voidpdc_io_reset_devices(void);intpdc_iodc_getc(void);
@@ -1232,15 +1232,18 @@ int __init pdc_soft_power_info(unsigned long *power_reg)}/*-*pdc_soft_power_button-Controlthesoftpowerbuttonbehaviour-*@sw_control:0forhardwarecontrol,1forsoftwarecontrol+*pdc_soft_power_button{_panic}-Controlthesoftpowerbuttonbehaviour+*@sw_control:0forhardwarecontrol,1forsoftwarecontrol***ThisPDCfunctionplacesthesoftpowerbuttonundersoftwareor*hardwarecontrol.-*UndersoftwarecontroltheOSmaycontroltowhentoallowtoshut-*downthesystem.Underhardwarecontrolpressingthepowerbutton+*UndersoftwarecontroltheOSmaycontroltowhentoallowtoshut+*downthesystem.Underhardwarecontrolpressingthepowerbutton*powersoffthesystemimmediately.+*+*The_panicversionreliesinspin_trylocktopreventdeadlock+*onpanicpath.*/intpdc_soft_power_button(intsw_control){
@@ -1254,6 +1257,22 @@ int pdc_soft_power_button(int sw_control)returnretval;}+intpdc_soft_power_button_panic(intsw_control)+{+intretval;+unsignedlongflags;++if(!spin_trylock_irqsave(&pdc_lock,flags)){+pr_emerg("Couldn't enable soft power button\n");+return-EBUSY;/* ignored by the panic notifier */+}++retval=mem_pdc_call(PDC_SOFT_POWER,PDC_SOFT_POWER_ENABLE,__pa(pdc_result),sw_control);+spin_unlock_irqrestore(&pdc_lock,flags);++returnretval;+}+/**pdc_io_reset-HacktoavoidoverlappingrangeregistersofBridgesdevices.*PrimarilyaproblemonT600(whichparisc-linuxdoesn'tsupport)but
@@ -175,16 +174,21 @@ static void powerfail_interrupt(int code, void *x)-/* parisc_panic_event() is called by the panic handler.-*Assoonasapanicoccurs,ourtaskletsabovewillnotbe-*executedanylonger.Thisfunctionthenre-enablesthe-*soft-powerswitchandallowstheusertoswitchoffthesystem+/*+*parisc_panic_event()iscalledbythepanichandler.+*+*Assoonasapanicoccurs,ourtaskletsabovewillnot+*beexecutedanylonger.Thisfunctionthenre-enables+*thesoft-powerswitchandallowstheusertoswitchoff+*thesystem.Werelyinpdc_soft_power_button_panic()+*sincethisversionspin_trylocks(insteadofregular+*spinlock),preventingdeadlocksonpanicpath.*/staticintparisc_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr){/* re-enable the soft-power switch */-pdc_soft_power_button(0);+pdc_soft_power_button_panic(0);returnNOTIFY_DONE;}
From: Sergei Shtylyov <hidden> Date: 2022-04-29 09:22:57
Hello!
On 4/28/22 1:49 AM, Guilherme G. Piccoli wrote:
quoted hunk
Currently the tracing dump_on_oops feature is implemented
through separate notifiers, one for die/oops and the other
for panic. With the addition of panic notifier "id", this
patch makes use of such "id" to unify both functions.
It also comments the function and changes the priority of the
notifier blocks, in order they run early compared to other
notifiers, to prevent useless trace data (like the callback
names for the other notifiers). Finally, we also removed an
unnecessary header inclusion.
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
kernel/trace/trace.c | 57 +++++++++++++++++++++++++-------------------
1 file changed, 32 insertions(+), 25 deletions(-)
@@ -9767,38 +9766,46 @@ static __init int tracer_init_tracefs(void) fs_initcall(tracer_init_tracefs);-static int trace_panic_handler(struct notifier_block *this,- unsigned long event, void *unused)+/*+ * The idea is to execute the following die/panic callback early, in order+ * to avoid showing irrelevant information in the trace (like other panic+ * notifier functions); we are the 2nd to run, after hung_task/rcu_stall+ * warnings get disabled (to prevent potential log flooding).+ */+static int trace_die_panic_handler(struct notifier_block *self,+ unsigned long ev, void *unused) {- if (ftrace_dump_on_oops)+ int do_dump;
bool?
+
+ if (!ftrace_dump_on_oops)
+ return NOTIFY_DONE;
+
+ switch (ev) {
+ case DIE_OOPS:
+ do_dump = 1;
+ break;
+ case PANIC_NOTIFIER:
+ do_dump = 1;
+ break;
Why not:
case DIE_OOPS:
case PANIC_NOTIFIER:
do_dump = 1;
break;
Why not:
case DIE_OOPS:
case PANIC_NOTIFIER:
do_dump = 1;
break;
Agreed.
Other than that.
Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
-- Steve
Thanks Sergei and Steven, good idea! I thought about the switch change
you propose, but I confess I got a bit confused by the "fallthrough"
keyword - do I need to use it?
About the s/int/bool, for sure! Not sure why I didn't use bool at
first...heheh
Cheers,
Guilherme
From: Steven Rostedt <rostedt@goodmis.org> Date: 2022-04-29 14:05:00
On Fri, 29 Apr 2022 10:46:35 -0300
"Guilherme G. Piccoli" [off-list ref] wrote:
Thanks Sergei and Steven, good idea! I thought about the switch change
you propose, but I confess I got a bit confused by the "fallthrough"
keyword - do I need to use it?
No. The fallthrough keyword is only needed when there's code between case
labels. As it is very common to list multiple cases for the same code path.
That is:
case DIE_OOPS:
case PANIC_NOTIFIER:
do_dump = 1;
break;
Does not need a fall through label, as there's no code between the DIE_OOPS
and the PANIC_NOTIFIER. But if you had:
case DIE_OOPS:
x = true;
case PANIC_NOTIFIER:
do_dump = 1;
break;
Then you do.
-- Steve
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 14:06:52
On 28/04/2022 05:11, Suzuki K Poulose wrote:
Hi Guilherme,
[...]
How would you like to proceed with queuing this ? I am happy
either way. In case you plan to push this as part of this
series (I don't see any potential conflicts) :
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Thanks for your review Suzuki, much appreciated!
About your question, I'm not sure yet - in case the core changes would
take a while (like if community find them polemic, require many changes,
etc) I might split this series in 2 parts, the fixes part vs the
improvements per se. Either way, a V2 is going to happen for sure, and
in that moment, I'll let you know what I think it's best.
But either way, any choice you prefer is fine by me as well (like if you
want to merge it now or postpone to get merged in the future), this is
not an urgent fix I think =)
Cheers,
Guilherme
@@ -83,6 +83,7 @@ int pdc_do_firm_test_reset(unsigned long ftc_bitmap);intpdc_do_reset(void);intpdc_soft_power_info(unsignedlong*power_reg);intpdc_soft_power_button(intsw_control);+intpdc_soft_power_button_panic(intsw_control);voidpdc_io_reset(void);voidpdc_io_reset_devices(void);intpdc_iodc_getc(void);
@@ -1232,15 +1232,18 @@ int __init pdc_soft_power_info(unsigned long *power_reg)}/*-*pdc_soft_power_button-Controlthesoftpowerbuttonbehaviour-*@sw_control:0forhardwarecontrol,1forsoftwarecontrol+*pdc_soft_power_button{_panic}-Controlthesoftpowerbuttonbehaviour+*@sw_control:0forhardwarecontrol,1forsoftwarecontrol***ThisPDCfunctionplacesthesoftpowerbuttonundersoftwareor*hardwarecontrol.-*UndersoftwarecontroltheOSmaycontroltowhentoallowtoshut-*downthesystem.Underhardwarecontrolpressingthepowerbutton+*UndersoftwarecontroltheOSmaycontroltowhentoallowtoshut+*downthesystem.Underhardwarecontrolpressingthepowerbutton*powersoffthesystemimmediately.+*+*The_panicversionreliesinspin_trylocktopreventdeadlock+*onpanicpath.*/intpdc_soft_power_button(intsw_control){
@@ -1254,6 +1257,22 @@ int pdc_soft_power_button(int sw_control)returnretval;}+intpdc_soft_power_button_panic(intsw_control)+{+intretval;+unsignedlongflags;++if(!spin_trylock_irqsave(&pdc_lock,flags)){+pr_emerg("Couldn't enable soft power button\n");+return-EBUSY;/* ignored by the panic notifier */+}++retval=mem_pdc_call(PDC_SOFT_POWER,PDC_SOFT_POWER_ENABLE,__pa(pdc_result),sw_control);+spin_unlock_irqrestore(&pdc_lock,flags);++returnretval;+}+/**pdc_io_reset-HacktoavoidoverlappingrangeregistersofBridgesdevices.*PrimarilyaproblemonT600(whichparisc-linuxdoesn'tsupport)but
@@ -175,16 +174,21 @@ static void powerfail_interrupt(int code, void *x)-/* parisc_panic_event() is called by the panic handler.-*Assoonasapanicoccurs,ourtaskletsabovewillnotbe-*executedanylonger.Thisfunctionthenre-enablesthe-*soft-powerswitchandallowstheusertoswitchoffthesystem+/*+*parisc_panic_event()iscalledbythepanichandler.+*+*Assoonasapanicoccurs,ourtaskletsabovewillnot+*beexecutedanylonger.Thisfunctionthenre-enables+*thesoft-powerswitchandallowstheusertoswitchoff+*thesystem.Werelyinpdc_soft_power_button_panic()+*sincethisversionspin_trylocks(insteadofregular+*spinlock),preventingdeadlocksonpanicpath.*/staticintparisc_panic_event(structnotifier_block*this,unsignedlongevent,void*ptr){/* re-enable the soft-power switch */-pdc_soft_power_button(0);+pdc_soft_power_button_panic(0);returnNOTIFY_DONE;}
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 14:46:17
On 29/04/2022 10:56, Steven Rostedt wrote:
[...]
No. The fallthrough keyword is only needed when there's code between case
labels. As it is very common to list multiple cases for the same code path.
That is:
case DIE_OOPS:
case PANIC_NOTIFIER:
do_dump = 1;
break;
Does not need a fall through label, as there's no code between the DIE_OOPS
and the PANIC_NOTIFIER. But if you had:
case DIE_OOPS:
x = true;
case PANIC_NOTIFIER:
do_dump = 1;
break;
Then you do.
-- Steve
Thanks a bunch for the clarification, changed that for V2 =)
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 15:19:57
On 28/04/2022 13:26, Corey Minyard wrote:
[...]
For the IPMI portion:
Acked-by: Corey Minyard <redacted>
Thanks Alex and Corey for the ACKs!
Note that the IPMI panic_event() should always return, but it may take
some time, especially if the IPMI controller is no longer functional.
So the risk of a long delay is there and it makes sense to move it very
late.
Thanks, I agree - the patch moves it to the (latest - 1) position, since
some arch code might run as the latest and effectively stops the machine.
Cheers,
Guilherme
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 16:04:54
On 27/04/2022 21:28, Randy Dunlap wrote:
On 4/27/22 15:49, Guilherme G. Piccoli wrote:
quoted
+ crash_kexec_post_notifiers
+ This was DEPRECATED - users should always prefer the
This is DEPRECATED - users should always prefer the
quoted
+ parameter "panic_notifiers_level" - check its entry
+ in this documentation for details on how it works.
+ Setting this parameter is exactly the same as setting
+ "panic_notifiers_level=4".
Thanks Randy, for your suggestion - but I confess I couldn't understand
it properly. It's related to spaces/tabs, right? What you suggest me to
change in this formatting? Just by looking the email I can't parse.
Cheers,
Guilherme
From: Max Filippov <jcmvbkbc@gmail.com> Date: 2022-04-29 16:05:00
On Wed, Apr 27, 2022 at 3:55 PM Guilherme G. Piccoli
[off-list ref] wrote:
This patch renames the panic_notifier_list to panic_pre_reboot_list;
the idea is that a subsequent patch will refactor the panic path
in order to better split the notifiers, running some of them very
early, some of them not so early [but still before kmsg_dump()] and
finally, the rest should execute late, after kdump. The latter ones
are now in the panic pre-reboot list - the name comes from the idea
that these notifiers execute before panic() attempts rebooting the
machine (if that option is set).
We also took the opportunity to clean-up useless header inclusions,
improve some notifier block declarations (e.g. in ibmasm/heartbeat.c)
and more important, change some priorities - we hereby set 2 notifiers
to run late in the list [iss_panic_event() and the IPMI panic_event()]
due to the risks they offer (may not return, for example).
Proper documentation is going to be provided in a subsequent patch,
that effectively refactors the panic path.
From: Michael Kelley (LINUX) <hidden> Date: 2022-04-29 16:26:38
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Wednesday, April 27, 2022 3:49 PM
Currently the regular CPU shutdown path for ARM disables IRQs/FIQs
in the secondary CPUs - smp_send_stop() calls ipi_cpu_stop(), which
is responsible for that. This makes sense, since we're turning off
such CPUs, putting them in an endless busy-wait loop.
Problem is that there is an alternative path for disabling CPUs,
in the form of function crash_smp_send_stop(), used for kexec/panic
paths. This functions relies in a SMP call that also triggers a
s/functions relies in/function relies on/
quoted hunk
busy-wait loop [at machine_crash_nonpanic_core()], but *without*
disabling interrupts. This might lead to odd scenarios, like early
interrupts in the boot of kexec'd kernel or even interrupts in
other CPUs while the main one still works in the panic path and
assumes all secondary CPUs are (really!) off.
This patch mimics the ipi_cpu_stop() interrupt disable mechanism
in the crash CPU shutdown path, hence disabling IRQs/FIQs in all
secondary CPUs in the kexec/panic path as well.
Cc: Marc Zyngier <maz@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/arm/kernel/machine_kexec.c | 3 +++
1 file changed, 3 insertions(+)
From: Michael Kelley (LINUX) <hidden> Date: 2022-04-29 16:28:22
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Wednesday, April 27, 2022 3:49 PM
Currently we have a debug infrastructure in the notifiers file, but
it's very simple/limited. This patch extends it by:
(a) Showing all registered/unregistered notifiers' callback names;
(b) Adding a dynamic debug tuning to allow showing called notifiers'
function names. Notice that this should be guarded as a tunable since
it can flood the kernel log buffer.
Cc: Arjan van de Ven <redacted>
Cc: Cong Wang <redacted>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Valentin Schneider <redacted>
Cc: Xiaoming Ni <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
We have some design decisions that worth discussing here:
(a) First of call, using C99 helps a lot to write clear and concise code, but
s/call/all/
quoted hunk
due to commit 4d94f910e79a ("Kbuild: use -Wdeclaration-after-statement") we
have a warning if mixing variable declarations with code. For this patch though,
doing that makes the code way clear, so decision was to add the debug code
inside brackets whenever this warning pops up. We can change that, but that'll
cause more ifdefs in the same function.
(b) In the symbol lookup helper function, we modify the parameter passed but
even more, we return it as well! This is unusual and seems unnecessary, but was
the strategy taken to allow embedding such function in the pr_debug() call.
Not doing that would likely requiring 3 symbol_name variables to avoid
concurrency (registering notifier A while calling notifier B) - we rely in
local variables as a serialization mechanism.
We're open for suggestions in case this design is not appropriate;
thanks in advance!
kernel/notifier.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
From: Michael Kelley (LINUX) <hidden> Date: 2022-04-29 17:17:18
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Wednesday, April 27, 2022 3:49 PM
Currently Hyper-V guests are among the most relevant users of the panic
infrastructure, like panic notifiers, kmsg dumpers, etc. The reasons rely
both in cleaning-up procedures (closing a hypervisor <-> guest connection,
disabling a paravirtualized timer) as well as to data collection (sending
panic information to the hypervisor) and framebuffer management.
The thing is: some notifiers are related to others, ordering matters, some
functionalities are duplicated and there are lots of conditionals behind
sending panic information to the hypervisor. This patch, as part of an
effort to clean-up the panic notifiers mechanism and better document
things, address some of the issues/complexities of Hyper-V panic handling
through the following changes:
(a) We have die and panic notifiers on vmbus_drv.c and both have goals of
sending panic information to the hypervisor, though the panic notifier is
also responsible for a cleaning-up procedure.
This commit clears the code by splitting the panic notifier in two, one
for closing the vmbus connection whereas the other is only for sending
panic info to hypervisor. With that, it was possible to merge the die and
panic notifiers in a single/well-documented function, and clear some
conditional complexities on sending such information to the hypervisor.
(b) The new panic notifier created after (a) is only doing a single thing:
cleaning the vmbus connection. This procedure might cause a delay (due to
hypervisor I/O completion), so we postpone that to run late. But more
relevant: this *same* vmbus unloading happens in the crash_shutdown()
handler, so if kdump is set, we can safely skip this panic notifier and
defer such clean-up to the kexec crash handler.
While the last sentence is true for Hyper-V on x86/x64, it's not true for
Hyper-V on ARM64. x86/x64 has the 'machine_ops' data structure
with the ability to provide a custom crash_shutdown() function, which
Hyper-V does in the form of hv_machine_crash_shutdown(). But ARM64
has no mechanism to provide such a custom function that will eventually
do the needed vmbus_initiate_unload() before running kdump.
I'm not immediately sure what the best solution is for ARM64. At this
point, I'm just pointing out the problem and will think about the tradeoffs
for various possible solutions. Please do the same yourself. :-)
(c) There is also a Hyper-V framebuffer panic notifier, which relies in
doing a vmbus operation that demands a valid connection. So, we must
order this notifier with the panic notifier from vmbus_drv.c, in order to
guarantee that the framebuffer code executes before the vmbus connection
is unloaded.
Patch 21 of this set puts the Hyper-V FB panic notifier on the pre_reboot
notifier list, which means it won't execute before the VMbus connection
unload in the case of kdump. This notifier is making sure that Hyper-V
is notified about the last updates made to the frame buffer before the
panic, so maybe it needs to be put on the hypervisor notifier list. It
sends a message to Hyper-V over its existing VMbus channel, but it
does not wait for a reply. It does, however, obtain a spin lock on the
ring buffer used to communicate with Hyper-V. Unless someone has
a better suggestion, I'm inclined to take the risk of blocking on that
spin lock.
Also, this commit removes a useless header.
Although there is code rework and re-ordering, we expect that this change
has no functional regressions but instead optimize the path and increase
panic reliability on Hyper-V. This was tested on Hyper-V with success.
Fixes: 792f232d57ff ("Drivers: hv: vmbus: Fix potential crash on module unload")
Fixes: 74347a99e73a ("x86/Hyper-V: Unload vmbus channel in hv panic callback")
The "Fixes:" tags imply that these changes should be backported to older
longterm kernel versions, which I don't think is the case. There is a
dependency on Patch 14 of your series where PANIC_NOTIFIER is
introduced.
quoted hunk
Cc: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Michael Kelley <redacted>
Cc: Stephen Hemminger <redacted>
Cc: Tianyu Lan <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Tested-by: Fabio A M Martins <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Special thanks to Michael Kelley for the good information about the Hyper-V
panic path in email threads some months ago, and to Fabio for the testing
performed.
Michael and all Microsoft folks: a careful analysis to double-check our changes
and assumptions here is really appreciated, this code is complex and intricate,
it is possible some corner case might have been overlooked.
Thanks in advance!
drivers/hv/vmbus_drv.c | 109 ++++++++++++++++++++------------
drivers/video/fbdev/hyperv_fb.c | 8 +++
2 files changed, 76 insertions(+), 41 deletions(-)
@@ -68,51 +68,75 @@ static int hyperv_report_reg(void)return!sysctl_record_panic_msg||!hv_panic_page;}-staticinthyperv_panic_event(structnotifier_block*nb,unsignedlongval,+/*+*Thepanicnotifierbelowisresponsiblesolelyforunloadingthe+*vmbusconnection,whichisnecessaryinapanicevent.Butnotice+*thatthissameunloadingprocedureisexecutedintheHyper-V+*crash_shutdown()handler[seehv_crash_handler()],whichbasically+*meansthatwecanpostponeitsexecutionifwehavekdumpset,+*sinceitwillrunthecrash_shutdown()handleranyway.Evenmore+*intrincatedistherelationofthisnotifierwithHyper-Vframebuffer
s/intrincated/intricate/
+ * panic notifier - we need vmbus connection alive there in order to
+ * succeed, so we need to order both with each other [for reference see
+ * hvfb_on_panic()] - this is done using notifiers' priorities.
+ */
+static int hv_panic_vmbus_unload(struct notifier_block *nb, unsigned long val,
void *args)
+{
+ if (!kexec_crash_loaded())
I'm not clear on the purpose of this condition. I think it means
we will skip the vmbus_initiate_unload() if a panic occurs in the
kdump kernel. Is there a reason a panic in the kdump kernel
should be treated differently? Or am I misunderstanding?
quoted hunk
+ vmbus_initiate_unload(true);
+
+ return NOTIFY_DONE;
+}
+static struct notifier_block hyperv_panic_vmbus_unload_block = {
+ .notifier_call = hv_panic_vmbus_unload,
+ .priority = INT_MIN + 1, /* almost the latest one to execute */
+};
+
+/*
+ * The following callback works both as die and panic notifier; its
+ * goal is to provide panic information to the hypervisor unless the
+ * kmsg dumper is gonna be used [see hv_kmsg_dump()], which provides
+ * more information but is not always available.
+ *
+ * Notice that both the panic/die report notifiers are registered only
+ * if we have the capability HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE set.
+ */
+static int hv_die_panic_notify_crash(struct notifier_block *nb,
+ unsigned long val, void *args)
{
struct pt_regs *regs;
+ bool is_die;
- vmbus_initiate_unload(true);
-
- /*
- * Hyper-V should be notified only once about a panic. If we will be
- * doing hv_kmsg_dump() with kmsg data later, don't do the notification
- * here.
- */
- if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
- && hyperv_report_reg()) {
+ /* Don't notify Hyper-V unless we have a die oops event or panic. */
+ switch (val) {
+ case DIE_OOPS:
+ is_die = true;
+ regs = ((struct die_args *)args)->regs;
+ break;
+ case PANIC_NOTIFIER:
+ is_die = false;
regs = current_pt_regs();
- hyperv_report_panic(regs, val, false);
- }
- return NOTIFY_DONE;
-}
-
-static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
- void *args)
-{
- struct die_args *die = args;
- struct pt_regs *regs = die->regs;
-
- /* Don't notify Hyper-V if the die event is other than oops */
- if (val != DIE_OOPS)
+ break;
+ default:
return NOTIFY_DONE;
+ }
/*
- * Hyper-V should be notified only once about a panic. If we will be
- * doing hv_kmsg_dump() with kmsg data later, don't do the notification
- * here.
+ * Hyper-V should be notified only once about a panic/die. If we will
+ * be calling hv_kmsg_dump() later with kmsg data, don't do the
+ * notification here.
*/
if (hyperv_report_reg())
- hyperv_report_panic(regs, val, true);
+ hyperv_report_panic(regs, val, is_die);
+
return NOTIFY_DONE;
}
-
-static struct notifier_block hyperv_die_block = {
- .notifier_call = hyperv_die_event,
+static struct notifier_block hyperv_die_report_block = {
+ .notifier_call = hv_die_panic_notify_crash,
};
-static struct notifier_block hyperv_panic_block = {
- .notifier_call = hyperv_panic_event,
+static struct notifier_block hyperv_panic_report_block = {
+ .notifier_call = hv_die_panic_notify_crash,
};
static const char *fb_mmio_name = "fb_range";
@@ -1589,16 +1613,17 @@ static int vmbus_bus_init(void) if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG) hv_kmsg_dump_register();- register_die_notifier(&hyperv_die_block);+ register_die_notifier(&hyperv_die_report_block);+ atomic_notifier_chain_register(&panic_notifier_list,+ &hyperv_panic_report_block); } /*- * Always register the panic notifier because we need to unload- * the VMbus channel connection to prevent any VMbus- * activity after the VM panics.+ * Always register the vmbus unload panic notifier because we+ * need to shut the VMbus channel connection on panic. */ atomic_notifier_chain_register(&panic_notifier_list,- &hyperv_panic_block);+ &hyperv_panic_vmbus_unload_block); vmbus_request_offers();
@@ -2817,15 +2842,17 @@ static void __exit vmbus_exit(void) if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) { kmsg_dump_unregister(&hv_kmsg_dumper);- unregister_die_notifier(&hyperv_die_block);+ unregister_die_notifier(&hyperv_die_report_block);+ atomic_notifier_chain_unregister(&panic_notifier_list,+ &hyperv_panic_report_block); } /*- * The panic notifier is always registered, hence we should+ * The vmbus panic notifier is always registered, hence we should * also unconditionally unregister it here as well. */ atomic_notifier_chain_unregister(&panic_notifier_list,- &hyperv_panic_block);+ &hyperv_panic_vmbus_unload_block); free_page((unsigned long)hv_panic_page); unregister_sysctl_table(hv_ctl_table_hdr);
From: Michael Kelley (LINUX) <hidden> Date: 2022-04-29 17:31:22
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Wednesday, April 27, 2022 3:49 PM
The goal of this new panic notifier is to allow its users to register
callbacks to run very early in the panic path. This aims hypervisor/FW
notification mechanisms as well as simple LED functions, and any other
simple and safe mechanism that should run early in the panic path; more
dangerous callbacks should execute later.
For now, the patch is almost a no-op (although it changes a bit the
ordering in which some panic notifiers are executed). In a subsequent
patch, the panic path will be refactored, then the panic hypervisor
notifiers will effectively run very early in the panic path.
We also defer documenting it all properly in the subsequent refactor
patch. While at it, we removed some useless header inclusions and
fixed some notifiers return too (by using the standard NOTIFY_DONE).
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Christophe JAILLET <redacted>
Cc: David Gow <redacted>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Dexuan Cui <decui@microsoft.com>
Cc: Doug Berger <opendmb@gmail.com>
Cc: Evan Green <redacted>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Hari Bathini <hbathini@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Julius Werner <jwerner@chromium.org>
Cc: Justin Chen <redacted>
Cc: "K. Y. Srinivasan" <kys@microsoft.com>
Cc: Lee Jones <redacted>
Cc: Markus Mayer <mmayer@broadcom.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Michael Kelley <redacted>
Cc: Mihai Carabas <redacted>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Paul Mackerras <redacted>
Cc: Pavel Machek <redacted>
Cc: Scott Branden <scott.branden@broadcom.com>
Cc: Sebastian Reichel <sre@kernel.org>
Cc: Shile Zhang <redacted>
Cc: Stephen Hemminger <redacted>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Tianyu Lan <redacted>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Wang ShaoBo <redacted>
Cc: Wei Liu <wei.liu@kernel.org>
Cc: zhenwei pi <redacted>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/mips/sgi-ip22/ip22-reset.c | 2 +-
arch/mips/sgi-ip32/ip32-reset.c | 3 +--
arch/powerpc/kernel/setup-common.c | 2 +-
arch/sparc/kernel/sstate.c | 3 +--
drivers/firmware/google/gsmi.c | 4 ++--
drivers/hv/vmbus_drv.c | 4 ++--
drivers/leds/trigger/ledtrig-activity.c | 4 ++--
drivers/leds/trigger/ledtrig-heartbeat.c | 4 ++--
drivers/misc/bcm-vk/bcm_vk_dev.c | 6 +++---
drivers/misc/pvpanic/pvpanic.c | 4 ++--
drivers/power/reset/ltc2952-poweroff.c | 4 ++--
drivers/s390/char/zcore.c | 5 +++--
drivers/soc/bcm/brcmstb/pm/pm-arm.c | 2 +-
include/linux/panic_notifier.h | 1 +
kernel/panic.c | 4 ++++
15 files changed, 28 insertions(+), 24 deletions(-)
Using the hypervisor_list here produces a bit of a mismatch. In many cases
this notifier will do nothing, and will defer to the kmsg_dump() mechanism
to notify the hypervisor about the panic. Running the kmsg_dump()
mechanism is linked to the info_list, so I'm thinking the Hyper-V panic report
notifier should be on the info_list as well. That way the reporting behavior
is triggered at the same point in the panic path regardless of which
reporting mechanism is used.
From: Michael Kelley (LINUX) <hidden> Date: 2022-04-29 17:54:23
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Wednesday, April 27, 2022 3:49 PM
quoted hunk
The panic() function is somewhat convoluted - a lot of changes were
made over the years, adding comments that might be misleading/outdated
now, it has a code structure that is a bit complex to follow, with
lots of conditionals, for example. The panic notifier list is something
else - a single list, with multiple callbacks of different purposes,
that run in a non-deterministic order and may affect hardly kdump
reliability - see the "crash_kexec_post_notifiers" workaround-ish flag.
This patch proposes a major refactor on the panic path based on Petr's
idea [0] - basically we split the notifiers list in three, having a set
of different call points in the panic path. Below a list of changes
proposed in this patch, culminating in the panic notifiers level
concept:
(a) First of all, we improved comments all over the function
and removed useless variables / includes. Also, as part of this
clean-up we concentrate the console flushing functions in a helper.
(b) As mentioned before, there is a split of the panic notifier list
in three, based on the purpose of the callback. The code contains
good documentation in form of comments, but a summary of the three
lists follows:
- the hypervisor list aims low-risk procedures to inform hypervisors
or firmware about the panic event, also includes LED-related functions;
- the informational list contains callbacks that provide more details,
like kernel offset or trace dump (if enabled) and also includes the
callbacks aimed at reducing log pollution or warns, like the RCU and
hung task disable callbacks;
- finally, the pre_reboot list is the old notifier list renamed,
containing the more risky callbacks that didn't fit the previous
lists. There is also a 4th list (the post_reboot one), but it's not
related with the original list - it contains late time architecture
callbacks aimed at stopping the machine, for example.
The 3 notifiers lists execute in different moments, hypervisor being
the first, followed by informational and finally the pre_reboot list.
(c) But then, there is the ordering problem of the notifiers against
the crash_kernel() call - kdump must be as reliable as possible.
For that, a simple binary "switch" as "crash_kexec_post_notifiers"
is not enough, hence we introduce here concept of panic notifier
levels: there are 5 levels, from 0 (no notifier executes before
kdump) until 4 (all notifiers run before kdump); the default level
is 2, in which the hypervisor and (iff we have any kmsg dumper)
the informational notifiers execute before kdump.
The detailed documentation of the levels is present in code comments
and in the kernel-parameters.txt file; as an analogy with the previous
panic() implementation, the level 0 is exactly the same as the old
behavior of notifiers, running all after kdump, and the level 4 is
the same as "crash_kexec_post_notifiers=Y" (we kept this parameter as
a deprecated one).
(d) Finally, an important change made here: we now use only the
function "crash_smp_send_stop()" to shut all the secondary CPUs
in the panic path. Before, there was a case of using the regular
"smp_send_stop()", but the better approach is to simplify the
code and try to use the function which was created exclusively
for the panic path. Experiments showed that it works fine, and
code was very simplified with that.
Functional change is expected from this refactor, since now we
call some notifiers by default before kdump, but the goal here
besides code clean-up is to have a better panic path, more
reliable and deterministic, but also very customizable.
[0] https://lore.kernel.org/lkml/YfPxvzSzDLjO5ldp@alley/
Suggested-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
Special thanks to Petr and Baoquan for the suggestion and feedback in a previous
email thread. There's some important design decisions that worth mentioning and
discussing:
* The default panic notifiers level is 2, based on Petr Mladek's suggestion,
which makes a lot of sense. Of course, this is customizable through the
parameter, but would be something worthwhile to have a KConfig option to set
the default level? It would help distros that want the old behavior
(no notifiers before kdump) as default.
* The implementation choice was to _avoid_ intricate if conditionals in the
panic path, which would _definitely_ be present with the panic notifiers levels
idea; so, instead of lots of if conditionals, the set/clear bits approach with
functions called in 2 points (but executing only in one of them) is much easier
to follow an was used here; the ordering helper function and the comments also
help a lot to avoid confusion (hopefully).
* Choice was to *always* use crash_smp_send_stop() instead of sometimes making
use of the regular smp_send_stop(); for most architectures they are the same,
including Xen (on x86). For the ones that override it, all should work fine,
in the powerpc case it's even more correct (see the subsequent patch
"powerpc: Do not force all panic notifiers to execute before kdump")
There seems to be 2 cases that requires some plumbing to work 100% right:
- ARM doesn't disable local interrupts / FIQs in the crash version of
send_stop(); we patched that early in this series;
- x86 could face an issue if we have VMX and do use crash_smp_send_stop()
_without_ kdump, but this is fixed in the first patch of the series (and
it's a bug present even before this refactor).
* Notice we didn't add a sysrq for panic notifiers level - should have it?
Alejandro proposed recently to add a sysrq for "crash_kexec_post_notifiers",
let me know if you feel the need here Alejandro, since the core parameters are
present in /sys, I didn't consider much gain in having a sysrq, but of course
I'm open to suggestions!
Thanks advance for the review!
.../admin-guide/kernel-parameters.txt | 42 ++-
include/linux/panic_notifier.h | 1 +
kernel/kexec_core.c | 8 +-
kernel/panic.c | 292 +++++++++++++-----
.../selftests/pstore/pstore_crash_test | 5 +-
5 files changed, 252 insertions(+), 96 deletions(-)
@@ -829,6 +829,13 @@ It will be ignored when crashkernel=X,high is not used or memory reserved is below 4G.+ crash_kexec_post_notifiers+ This was DEPRECATED - users should always prefer the+ parameter "panic_notifiers_level" - check its entry+ in this documentation for details on how it works.+ Setting this parameter is exactly the same as setting+ "panic_notifiers_level=4".+ cryptomgr.notests [KNL] Disable crypto self-tests
@@ -3784,6 +3791,33 @@ timeout < 0: reboot immediately Format: <timeout>+ panic_notifiers_level=+ [KNL] Set the panic notifiers execution order.+ Format: <unsigned int>+ We currently have 4 lists of panic notifiers; based+ on the functionality and risk (for panic success) the+ callbacks are added in a given list. The lists are:+ - hypervisor/FW notification list (low risk);+ - informational list (low/medium risk);+ - pre_reboot list (higher risk);+ - post_reboot list (only run late in panic and after+ kdump, not configurable for now).+ This parameter defines the ordering of the first 3+ lists with regards to kdump; the levels determine+ which set of notifiers execute before kdump. The+ accepted levels are:+ 0: kdump is the first thing to run, NO list is+ executed before kdump.+ 1: only the hypervisor list is executed before kdump.+ 2 (default level): the hypervisor list and (*if*+ there's any kmsg_dumper defined) the informational+ list are executed before kdump.+ 3: both the hypervisor and the informational lists+ (always) execute before kdump.
I'm not clear on why level 2 exists. What is the scenario where
execution of the info list before kdump should be conditional on the
existence of a kmsg_dumper? Maybe the scenario is described
somewhere in the patch set and I just missed it.
quoted hunk
+ 4: the 3 lists (hypervisor, info and pre_reboot)
+ execute before kdump - this behavior is analog to the
+ deprecated parameter "crash_kexec_post_notifiers".
+
panic_print= Bitmask for printing system info when panic happens.
User can chose combination of the following bits:
bit 0: print all tasks info
@@ -3814,14 +3848,6 @@ panic_on_warn panic() instead of WARN(). Useful to cause kdump on a WARN().- crash_kexec_post_notifiers- Run kdump after running panic-notifiers and dumping- kmsg. This only for the users who doubt kdump always- succeeds in any situation.- Note that this also increases risks of kdump failure,- because some panic notifiers can make the crashed- kernel more unstable.- parkbd.port= [HW] Parallel port number the keyboard adapter is connected to, default is 0. Format: <parport#>
@@ -52,14 +51,23 @@ static unsigned long tainted_mask =staticintpause_on_oops;staticintpause_on_oops_flag;staticDEFINE_SPINLOCK(pause_on_oops_lock);-boolcrash_kexec_post_notifiers;+intpanic_on_warn__read_mostly;+boolpanic_on_taint_nousertaint;unsignedlongpanic_on_taint;-boolpanic_on_taint_nousertaint=false;intpanic_timeout=CONFIG_PANIC_TIMEOUT;EXPORT_SYMBOL_GPL(panic_timeout);+/* Initialized with all notifiers set to run before kdump */+staticunsignedlongpanic_notifiers_bits=15;++/* Default level is 2, see kernel-parameters.txt */+unsignedintpanic_notifiers_level=2;++/* DEPRECATED in favor of panic_notifiers_level */+boolcrash_kexec_post_notifiers;+#define PANIC_PRINT_TASK_INFO 0x00000001#define PANIC_PRINT_MEM_INFO 0x00000002#define PANIC_PRINT_TIMER_INFO 0x00000004
I think the above switch statement could be done as follows:
if (panic_notifiers_level <= 3)
clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
if (panic_notifiers_level <= 2)
if (!kmsg_has_dumpers())
clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
if (panic_notifiers_level <=1)
clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
if (panic_notifiers_level == 0)
clear_bit(PN_HYPERVISOR_BIT, &panic_notifiers_bits);
That's about half the lines of code. It's somewhat a matter of style,
so treat this as just a suggestion to consider. I just end up looking
for a better solution when I see the same line of code repeated
3 or 4 times!
quoted hunk
+}
+
+/*
+ * Set of helpers to execute the panic notifiers only once.
+ * Just the informational notifier cares about the return.
+ */
+static inline bool notifier_run_once(struct atomic_notifier_head head,
+ char *buf, long bit)
+{
+ if (test_and_change_bit(bit, &panic_notifiers_bits)) {
+ atomic_notifier_call_chain(&head, PANIC_NOTIFIER, buf);
+ return true;
+ }
+ return false;
+}
+
+#define panic_notifier_hypervisor_once(buf)\
+ notifier_run_once(panic_hypervisor_list, buf, PN_HYPERVISOR_BIT)
+
+#define panic_notifier_info_once(buf)\
+ notifier_run_once(panic_info_list, buf, PN_INFO_BIT)
+
+#define panic_notifier_pre_reboot_once(buf)\
+ notifier_run_once(panic_pre_reboot_list, buf, PN_PRE_REBOOT_BIT)
+
+#define panic_notifier_post_reboot_once(buf)\
+ notifier_run_once(panic_post_reboot_list, buf, PN_POST_REBOOT_BIT)
+
/**
* panic - halt the system
* @fmt: The text string to print
@@ -198,32 +316,29 @@ void panic(const char *fmt, ...) long i, i_next = 0, len; int state = 0; int old_cpu, this_cpu;- bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;- if (panic_on_warn) {- /*- * This thread may hit another WARN() in the panic path.- * Resetting this prevents additional WARN() from panicking the- * system on this thread. Other threads are blocked by the- * panic_mutex in panic().- */- panic_on_warn = 0;- }+ /*+ * This thread may hit another WARN() in the panic path, so+ * resetting this option prevents additional WARN() from+ * re-panicking the system here.+ */+ panic_on_warn = 0; /* * Disable local interrupts. This will prevent panic_smp_self_stop- * from deadlocking the first cpu that invokes the panic, since- * there is nothing to prevent an interrupt handler (that runs- * after setting panic_cpu) from invoking panic() again.+ * from deadlocking the first cpu that invokes the panic, since there+ * is nothing to prevent an interrupt handler (that runs after setting+ * panic_cpu) from invoking panic() again. Also disables preemption+ * here - notice it's not safe to rely on interrupt disabling to avoid+ * preemption, since any cond_resched() or cond_resched_lock() might+ * trigger a reschedule if the preempt count is 0 (for reference, see+ * Documentation/locking/preempt-locking.rst). Some functions called+ * from here want preempt disabled, so no point enabling it later. */ local_irq_disable(); preempt_disable_notrace(); /*- * It's possible to come here directly from a panic-assertion and- * not have preempt disabled. Some functions called from here want- * preempt to be disabled. No point enabling it later though...- * * Only one CPU is allowed to execute the panic code from here. For * multiple parallel invocations of panic, all other CPUs either * stop themself or will wait until they are stopped by the 1st CPU
@@ -266,73 +381,75 @@ void panic(const char *fmt, ...) kgdb_panic(buf); /*- * If we have crashed and we have a crash kernel loaded let it handle- * everything else.- * If we want to run this after calling panic_notifiers, pass- * the "crash_kexec_post_notifiers" option to the kernel.+ * Here lies one of the most subtle parts of the panic path,+ * the panic notifiers and their order with regards to kdump.+ * We currently have 4 sets of notifiers: *- * Bypass the panic_cpu check and call __crash_kexec directly.+ * - the hypervisor list is composed by callbacks that are related+ * to warn the FW / hypervisor about panic, or non-invasive LED+ * controlling functions - (hopefully) low-risk for kdump, should+ * run early if possible.+ *+ * - the informational list is composed by functions dumping data+ * like kernel offsets, device error registers or tracing buffer;+ * also log flooding prevention callbacks fit in this list. It is+ * relatively safe to run before kdump.+ *+ * - the pre_reboot list basically is everything else, all the+ * callbacks that don't fit in the 2 previous lists. It should+ * run *after* kdump if possible, as it contains high-risk+ * functions that may break kdump.+ *+ * - we also have a 4th list of notifiers, the post_reboot+ * callbacks. This is not strongly related to kdump since it's+ * always executed late in the panic path, after the restart+ * mechanism (if set); its goal is to provide a way for+ * architecture code effectively power-off/disable the system.+ *+ * The kernel provides the "panic_notifiers_level" parameter+ * to adjust the ordering in which these notifiers should run+ * with regards to kdump - the default level is 2, so both the+ * hypervisor and informational notifiers should execute before+ * the __crash_kexec(); the info notifier won't run by default+ * unless there's some kmsg_dumper() registered. For details+ * about it, check Documentation/admin-guide/kernel-parameters.txt.+ *+ * Notice that the code relies in bits set/clear operations to+ * determine the ordering, functions *_once() execute only one+ * time, as their name implies. The goal is to prevent too much+ * if conditionals and more confusion. Finally, regarding CPUs+ * disabling: unless NO panic notifier executes before kdump,+ * we always disable secondary CPUs before __crash_kexec() and+ * the notifiers execute. */- if (!_crash_kexec_post_notifiers) {+ order_panic_notifiers_and_kdump();++ /* If no level, we should kdump ASAP. */+ if (!panic_notifiers_level) __crash_kexec(NULL);- /*- * Note smp_send_stop is the usual smp shutdown function, which- * unfortunately means it may not be hardened to work in a- * panic situation.- */- smp_send_stop();- } else {- /*- * If we want to do crash dump after notifier calls and- * kmsg_dump, we will need architecture dependent extra- * works in addition to stopping other CPUs.- */- crash_smp_send_stop();- }+ crash_smp_send_stop();+ panic_notifier_hypervisor_once(buf);- /*- * Run any panic handlers, including those that might need to- * add information to the kmsg dump output.- */- atomic_notifier_call_chain(&panic_hypervisor_list, PANIC_NOTIFIER, buf);- atomic_notifier_call_chain(&panic_info_list, PANIC_NOTIFIER, buf);- atomic_notifier_call_chain(&panic_pre_reboot_list, PANIC_NOTIFIER, buf);+ if (panic_notifier_info_once(buf)) {+ panic_print_sys_info(false);+ kmsg_dump(KMSG_DUMP_PANIC);+ }- panic_print_sys_info(false);+ panic_notifier_pre_reboot_once(buf);- kmsg_dump(KMSG_DUMP_PANIC);+ __crash_kexec(NULL);- /*- * If you doubt kdump always works fine in any situation,- * "crash_kexec_post_notifiers" offers you a chance to run- * panic_notifiers and dumping kmsg before kdump.- * Note: since some panic_notifiers can make crashed kernel- * more unstable, it can increase risks of the kdump failure too.- *- * Bypass the panic_cpu check and call __crash_kexec directly.- */- if (_crash_kexec_post_notifiers)- __crash_kexec(NULL);+ panic_notifier_hypervisor_once(buf);-#ifdef CONFIG_VT- unblank_screen();-#endif- console_unblank();-- /*- * We may have ended up stopping the CPU holding the lock (in- * smp_send_stop()) while still having some valuable data in the console- * buffer. Try to acquire the lock then release it regardless of the- * result. The release will also print the buffers out. Locks debug- * should be disabled to avoid reporting bad unlock balance when- * panic() is not being callled from OOPS.- */- debug_locks_off();- console_flush_on_panic(CONSOLE_FLUSH_PENDING);+ if (panic_notifier_info_once(buf)) {+ panic_print_sys_info(false);+ kmsg_dump(KMSG_DUMP_PANIC);+ }- panic_print_sys_info(true);+ panic_notifier_pre_reboot_once(buf);+ console_flushing(); if (!panic_blink) panic_blink = no_blink;
@@ -383,6 +499,15 @@ void panic(const char *fmt, ...) EXPORT_SYMBOL(panic);+/*+ * Helper used in the kexec code, to validate if any+ * panic notifier is set to execute early, before kdump.+ */+inline bool panic_notifiers_before_kdump(void)+{+ return panic_notifiers_level || crash_kexec_post_notifiers;+}+ /* * TAINT_FORCED_RMMOD could be a per-module flag but the module * is being removed anyway.
@@ -25,6 +25,7 @@ touch $REBOOT_FLAG sync # cause crash-# Note: If you use kdump and want to see kmesg-* files after reboot, you should-# specify 'crash_kexec_post_notifiers' in 1st kernel's cmdline.+# Note: If you use kdump and want to see kmsg-* files after reboot, you should+# be sure that the parameter "panic_notifiers_level" is more than '2' (the+# default value for this parameter is '2') in the first kernel's cmdline. echo c > /proc/sysrq-trigger--
Using the hypervisor_list here produces a bit of a mismatch. In many cases
this notifier will do nothing, and will defer to the kmsg_dump() mechanism
to notify the hypervisor about the panic. Running the kmsg_dump()
mechanism is linked to the info_list, so I'm thinking the Hyper-V panic report
notifier should be on the info_list as well. That way the reporting behavior
is triggered at the same point in the panic path regardless of which
reporting mechanism is used.
Hi Michael, thanks for your feedback! I agree that your idea could work,
but...there is one downside: imagine the kmsg_dump() approach is not set
in some Hyper-V guest, then we would rely in the regular notification
mechanism [hv_die_panic_notify_crash()], right?
But...you want then to run this notifier in the informational list,
which...won't execute *by default* before kdump if no kmsg_dump() is
set. So, this logic is convoluted when you mix it with the default level
concept + kdump.
May I suggest something? If possible, take a run with this patch set +
DEBUG_NOTIFIER=y, in *both* cases (with and without the kmsg_dump()
set). I did that and they run almost at the same time...I've checked the
notifiers called, it's like almost nothing runs in-between.
I feel the panic notification mechanism does really fit with a
hypervisor list, it's a good match with the nature of the list, which
aims at informing the panic notification to the hypervisor/FW.
Of course we can modify it if you prefer...but please take into account
the kdump case and how it complicates the logic.
Let me know your considerations, in case you can experiment with the
patch set as-is.
Cheers,
Guilherme
From: Marc Zyngier <maz@kernel.org> Date: 2022-04-29 18:20:58
On Wed, 27 Apr 2022 23:48:56 +0100,
"Guilherme G. Piccoli" [off-list ref] wrote:
quoted hunk
Currently the regular CPU shutdown path for ARM disables IRQs/FIQs
in the secondary CPUs - smp_send_stop() calls ipi_cpu_stop(), which
is responsible for that. This makes sense, since we're turning off
such CPUs, putting them in an endless busy-wait loop.
Problem is that there is an alternative path for disabling CPUs,
in the form of function crash_smp_send_stop(), used for kexec/panic
paths. This functions relies in a SMP call that also triggers a
busy-wait loop [at machine_crash_nonpanic_core()], but *without*
disabling interrupts. This might lead to odd scenarios, like early
interrupts in the boot of kexec'd kernel or even interrupts in
other CPUs while the main one still works in the panic path and
assumes all secondary CPUs are (really!) off.
This patch mimics the ipi_cpu_stop() interrupt disable mechanism
in the crash CPU shutdown path, hence disabling IRQs/FIQs in all
secondary CPUs in the kexec/panic path as well.
Cc: Marc Zyngier <maz@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
arch/arm/kernel/machine_kexec.c | 3 +++
1 file changed, 3 insertions(+)
My expectations would be that, since we're getting here using an IPI,
interrupts are already masked. So what reenabled them the first place?
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
On Wed, Apr 27, 2022 at 07:49:07PM -0300, Guilherme G. Piccoli wrote:
Currently many console drivers for s390 rely on panic/reboot notifiers
to invoke callbacks on these events. The panic() function disables local
IRQs, secondary CPUs and preemption, so callbacks invoked on panic are
effectively running in atomic context.
Happens that most of these console callbacks from s390 doesn't take the
proper care with regards to atomic context, like taking spinlocks that
might be taken in other function/CPU and hence will cause a lockup
situation.
The goal for this patch is to improve the notifiers reliability, acting
on 4 console drivers, as detailed below:
(1) con3215: changed a regular spinlock to the trylock alternative.
(2) con3270: also changed a regular spinlock to its trylock counterpart,
but here we also have another problem: raw3270_activate_view() takes a
different spinlock. So, we worked a helper to validate if this other lock
is safe to acquire, and if so, raw3270_activate_view() should be safe.
Notice though that there is a functional change here: it's now possible
to continue the notifier code [reaching con3270_wait_write() and
con3270_rebuild_update()] without executing raw3270_activate_view().
(3) sclp: a global lock is used heavily in the functions called from
the notifier, so we added a check here - if the lock is taken already,
we just bail-out, preventing the lockup.
(4) sclp_vt220: same as (3), a lock validation was added to prevent the
potential lockup problem.
Besides (1)-(4), we also removed useless void functions, adding the
code called from the notifier inside its own body, and changed the
priority of such notifiers to execute late, since they are "heavyweight"
for the panic environment, so we aim to reduce risks here.
Changed return values to NOTIFY_DONE as well, the standard one.
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Sven Schnelle <svens@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
As a design choice, the option used here to verify a given spinlock is taken
was the function "spin_is_locked()" - but we noticed that it is not often used.
An alternative would to take the lock with a spin_trylock() and if it succeeds,
just release the spinlock and continue the code. But that seemed weird...
Also, we'd like to ask a good validation of case (2) potential functionality
change from the s390 console experts - far from expert here, and in our naive
code observation, that seems fine, but that analysis might be missing some
corner case.
Thanks in advance!
drivers/s390/char/con3215.c | 36 +++++++++++++++--------------
drivers/s390/char/con3270.c | 34 +++++++++++++++------------
drivers/s390/char/raw3270.c | 18 +++++++++++++++
drivers/s390/char/raw3270.h | 1 +
drivers/s390/char/sclp_con.c | 28 +++++++++++++----------
drivers/s390/char/sclp_vt220.c | 42 +++++++++++++++++++---------------
6 files changed, 96 insertions(+), 63 deletions(-)
Code looks good, and everything still seems to work. I applied this
internally for the time being, and if it passes testing, I'll schedule
it for the next merge window.
Thanks!
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 19:31:56
On 29/04/2022 15:46, Heiko Carstens wrote:
[...]
Code looks good, and everything still seems to work. I applied this
internally for the time being, and if it passes testing, I'll schedule
it for the next merge window.
Thanks!
Perfect Heiko, thanks a bunch for your review and tests!
Let me know if anything breaks heh
Cheers,
Guilherme
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 19:38:50
On 27/04/2022 22:01, Xiaoming Ni wrote:
[...]
Duplicate Code.
Is it better to use __func__ and %pS?
pr_info("%s: %pS\n", __func__, n->notifier_call);
This is a great suggestion Xiaoming, much appreciated!
I feel like reinventing the wheel here - with your idea, code was super
clear and concise, very nice suggestion!!
The only 2 things that diverge from your idea: I'm using '%ps' (not
showing offsets) and also, kept the wording "(un)registered/calling",
not using __func__ - I feel it's a bit odd in the output.
OK for you?
I'm definitely using your idea in V2 heh
Cheers,
Guilherme
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 20:39:54
On 29/04/2022 14:53, Michael Kelley (LINUX) wrote:
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Wednesday, April 27, 2022 3:49 PM
quoted
[...]
+ panic_notifiers_level=
+ [KNL] Set the panic notifiers execution order.
+ Format: <unsigned int>
+ We currently have 4 lists of panic notifiers; based
+ on the functionality and risk (for panic success) the
+ callbacks are added in a given list. The lists are:
+ - hypervisor/FW notification list (low risk);
+ - informational list (low/medium risk);
+ - pre_reboot list (higher risk);
+ - post_reboot list (only run late in panic and after
+ kdump, not configurable for now).
+ This parameter defines the ordering of the first 3
+ lists with regards to kdump; the levels determine
+ which set of notifiers execute before kdump. The
+ accepted levels are:
+ 0: kdump is the first thing to run, NO list is
+ executed before kdump.
+ 1: only the hypervisor list is executed before kdump.
+ 2 (default level): the hypervisor list and (*if*
+ there's any kmsg_dumper defined) the informational
+ list are executed before kdump.
+ 3: both the hypervisor and the informational lists
+ (always) execute before kdump.
I'm not clear on why level 2 exists. What is the scenario where
execution of the info list before kdump should be conditional on the
existence of a kmsg_dumper? Maybe the scenario is described
somewhere in the patch set and I just missed it.
Hi Michael, thanks for your review/consideration. So, this idea started
kind of some time ago. It all started with a need of exposing more
information on kernel log *before* kdump and *before* pstore -
specifically, we're talking about panic_print. But this cause some
reactions, Baoquan was very concerned with that [0]. Soon after, I've
proposed a panic notifiers filter (orthogonal) approach, to which Petr
suggested instead doing a major refactor [1] - it finally is alive in
the form of this series.
The theory behind the level 2 is to allow a scenario of kdump with the
minimum amount of notifiers - what is the point in printing more
information if the user doesn't care, since it's going to kdump? Now, if
there is a kmsg dumper, it means that there is likely some interest in
collecting information, and that might as well be required before the
potential kdump (which is my case, hence the proposal on [0]).
Instead of forcing one of the two behaviors (level 1 or level 3), we
have a middle-term/compromise: if there's interest in collecting such
data (in the form of a kmsg dumper), we then execute the informational
notifiers before kdump. If not, why to increase (even slightly) the risk
for kdump?
I'm OK in removing the level 2 if people prefer, but I don't feel it's a
burden, quite opposite - seems a good way to accommodate the somewhat
antagonistic ideas (jump to kdump ASAP vs collecting more info in the
panicked kernel log).
[0] https://lore.kernel.org/lkml/20220126052246.GC2086@MiWiFi-R3L-srv/
[1] https://lore.kernel.org/lkml/YfPxvzSzDLjO5ldp@alley/
[...]
quoted
+ * Based on the level configured (smaller than 4), we clear the
+ * proper bits in "panic_notifiers_bits". Notice that this bitfield
+ * is initialized with all notifiers set.
+ */
+ switch (panic_notifiers_level) {
+ case 3:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+ break;
+ case 2:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+
+ if (!kmsg_has_dumpers())
+ clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
+ break;
+ case 1:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+ clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
+ break;
+ case 0:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+ clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
+ clear_bit(PN_HYPERVISOR_BIT, &panic_notifiers_bits);
+ break;
+ }
I think the above switch statement could be done as follows:
if (panic_notifiers_level <= 3)
clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
if (panic_notifiers_level <= 2)
if (!kmsg_has_dumpers())
clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
if (panic_notifiers_level <=1)
clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
if (panic_notifiers_level == 0)
clear_bit(PN_HYPERVISOR_BIT, &panic_notifiers_bits);
That's about half the lines of code. It's somewhat a matter of style,
so treat this as just a suggestion to consider. I just end up looking
for a better solution when I see the same line of code repeated
3 or 4 times!
It's a good idea - I liked your code. The switch seems more
natural/explicit for me, even duplicating some lines, but in case more
people prefer your way, I can definitely change the code - thanks for
the suggestion.
Cheers,
Guilherme
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 21:39:20
Thanks Marc and Michael for the review/discussion.
On 29/04/2022 15:20, Marc Zyngier wrote:
[...]
My expectations would be that, since we're getting here using an IPI,
interrupts are already masked. So what reenabled them the first place?
Thanks,
M.
Marc, I did some investigation in the code (and tried/failed in the ARM
documentation as well heh), but this is still not 100% clear for me.
You're saying IPI calls disable IRQs/FIQs by default in the the target
CPUs? Where does it happen? I'm a bit confused if this a processor
mechanism, or it's in code.
Looking the smp_send_stop() in arch/arm/, it does IPI the CPUs, with the
flag IPI_CPU_STOP, eventually calling ipi_cpu_stop(), and the latter
does disable IRQ/FIQ in code - that's where I stole my code from.
But crash_smp_send_stop() is different, it seems to IPI the other CPUs
with the flag IPI_CALL_FUNC, which leads to calling
generic_smp_call_function_interrupt() - does it disable interrupts/FIQs
as well? I couldn't find it.
Appreciate your clarifications about that, thanks again.
Cheers,
Guilherme
From: "Russell King (Oracle)" <linux@armlinux.org.uk> Date: 2022-04-29 21:46:07
On Fri, Apr 29, 2022 at 06:38:19PM -0300, Guilherme G. Piccoli wrote:
Thanks Marc and Michael for the review/discussion.
On 29/04/2022 15:20, Marc Zyngier wrote:
quoted
[...]
quoted
My expectations would be that, since we're getting here using an IPI,
interrupts are already masked. So what reenabled them the first place?
Thanks,
M.
Marc, I did some investigation in the code (and tried/failed in the ARM
documentation as well heh), but this is still not 100% clear for me.
You're saying IPI calls disable IRQs/FIQs by default in the the target
CPUs? Where does it happen? I'm a bit confused if this a processor
mechanism, or it's in code.
When we taken an IRQ, IRQs will be masked, FIQs will not. IPIs are
themselves interrupts, so IRQs will be masked while the IPI is being
processed. Therefore, there should be no need to re-disable the
already disabled interrupts.
But crash_smp_send_stop() is different, it seems to IPI the other CPUs
with the flag IPI_CALL_FUNC, which leads to calling
generic_smp_call_function_interrupt() - does it disable interrupts/FIQs
as well? I couldn't find it.
It's buried in the architecture behaviour. When the CPU takes an
interrupt and jumps to the interrupt vector in the vectors page, it is
architecturally defined that interrupts will be disabled. If they
weren't architecturally disabled at this point, then as soon as the
first instruction is processed (at the interrupt vector, likely a
branch) the CPU would immediately take another jump to the interrupt
vector, and this process would continue indefinitely, making interrupt
handling utterly useless.
So, you won't find an explicit instruction in the code path from the
vectors to the IPI handler that disables interrupts - because it's
written into the architecture that this is what must happen.
IRQs are a lower priority than FIQs, so FIQs remain unmasked.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 21:57:20
On 29/04/2022 18:45, Russell King (Oracle) wrote:
[...]
quoted
Marc, I did some investigation in the code (and tried/failed in the ARM
documentation as well heh), but this is still not 100% clear for me.
You're saying IPI calls disable IRQs/FIQs by default in the the target
CPUs? Where does it happen? I'm a bit confused if this a processor
mechanism, or it's in code.
When we taken an IRQ, IRQs will be masked, FIQs will not. IPIs are
themselves interrupts, so IRQs will be masked while the IPI is being
processed. Therefore, there should be no need to re-disable the
already disabled interrupts.
quoted
But crash_smp_send_stop() is different, it seems to IPI the other CPUs
with the flag IPI_CALL_FUNC, which leads to calling
generic_smp_call_function_interrupt() - does it disable interrupts/FIQs
as well? I couldn't find it.
It's buried in the architecture behaviour. When the CPU takes an
interrupt and jumps to the interrupt vector in the vectors page, it is
architecturally defined that interrupts will be disabled. If they
weren't architecturally disabled at this point, then as soon as the
first instruction is processed (at the interrupt vector, likely a
branch) the CPU would immediately take another jump to the interrupt
vector, and this process would continue indefinitely, making interrupt
handling utterly useless.
So, you won't find an explicit instruction in the code path from the
vectors to the IPI handler that disables interrupts - because it's
written into the architecture that this is what must happen.
IRQs are a lower priority than FIQs, so FIQs remain unmasked.
Thanks a lot for the *great* explanation Russell, much appreciated.
So, this leads to the both following questions:
a) Shall we then change the patch to only disable FIQs, since it's panic
path and we don't want secondary CPUs getting interrupted, but only
spinning quietly "forever"?
b) How about cleaning ipi_cpu_stop() then, by dropping the call to
local_irq_disable() there, to avoid the double IRQ disabling?
Thanks,
Guilherme
From: Marc Zyngier <maz@kernel.org> Date: 2022-04-29 22:00:50
On Fri, 29 Apr 2022 22:45:14 +0100,
"Russell King (Oracle)" [off-list ref] wrote:
On Fri, Apr 29, 2022 at 06:38:19PM -0300, Guilherme G. Piccoli wrote:
quoted
Thanks Marc and Michael for the review/discussion.
On 29/04/2022 15:20, Marc Zyngier wrote:
quoted
[...]
quoted
My expectations would be that, since we're getting here using an IPI,
interrupts are already masked. So what reenabled them the first place?
Thanks,
M.
Marc, I did some investigation in the code (and tried/failed in the ARM
documentation as well heh), but this is still not 100% clear for me.
You're saying IPI calls disable IRQs/FIQs by default in the the target
CPUs? Where does it happen? I'm a bit confused if this a processor
mechanism, or it's in code.
When we taken an IRQ, IRQs will be masked, FIQs will not. IPIs are
themselves interrupts, so IRQs will be masked while the IPI is being
processed. Therefore, there should be no need to re-disable the
already disabled interrupts.
quoted
But crash_smp_send_stop() is different, it seems to IPI the other CPUs
with the flag IPI_CALL_FUNC, which leads to calling
generic_smp_call_function_interrupt() - does it disable interrupts/FIQs
as well? I couldn't find it.
It's buried in the architecture behaviour. When the CPU takes an
interrupt and jumps to the interrupt vector in the vectors page, it is
architecturally defined that interrupts will be disabled. If they
weren't architecturally disabled at this point, then as soon as the
first instruction is processed (at the interrupt vector, likely a
branch) the CPU would immediately take another jump to the interrupt
vector, and this process would continue indefinitely, making interrupt
handling utterly useless.
So, you won't find an explicit instruction in the code path from the
vectors to the IPI handler that disables interrupts - because it's
written into the architecture that this is what must happen.
IRQs are a lower priority than FIQs, so FIQs remain unmasked.
Ah, you're of course right. That's one of the huge differences between
AArch32 and AArch64, where the former has per target mode masking
rules, and the later masks everything on entry...
M.
--
Without deviation from the norm, progress is not possible.
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-04-29 22:36:02
Hi Michael, first of all thanks for the great review, much appreciated.
Some comments inline below:
On 29/04/2022 14:16, Michael Kelley (LINUX) wrote:
[...]
quoted
hypervisor I/O completion), so we postpone that to run late. But more
relevant: this *same* vmbus unloading happens in the crash_shutdown()
handler, so if kdump is set, we can safely skip this panic notifier and
defer such clean-up to the kexec crash handler.
While the last sentence is true for Hyper-V on x86/x64, it's not true for
Hyper-V on ARM64. x86/x64 has the 'machine_ops' data structure
with the ability to provide a custom crash_shutdown() function, which
Hyper-V does in the form of hv_machine_crash_shutdown(). But ARM64
has no mechanism to provide such a custom function that will eventually
do the needed vmbus_initiate_unload() before running kdump.
I'm not immediately sure what the best solution is for ARM64. At this
point, I'm just pointing out the problem and will think about the tradeoffs
for various possible solutions. Please do the same yourself. :-)
Oh, you're totally right! I just assumed ARM64 would the the same, my
bad. Just to propose some alternatives, so you/others can also discuss
here and we can reach a consensus about the trade-offs:
(a) We could forget about this change, and always do the clean-up here,
not relying in machine_crash_shutdown().
Pro: really simple, behaves the same as it is doing currently.
Con: less elegant/concise, doesn't allow arm64 customization.
(b) Add a way to allow ARM64 customization of shutdown crash handler.
Pro: matches x86, more customizable, improves arm64 arch code.
Con: A tad more complex.
Also, a question that came-up: if ARM64 has no way of calling special
crash shutdown handler, how can you execute hv_stimer_cleanup() and
hv_synic_disable_regs() there? Or are they not required in ARM64?
quoted
(c) There is also a Hyper-V framebuffer panic notifier, which relies in
doing a vmbus operation that demands a valid connection. So, we must
order this notifier with the panic notifier from vmbus_drv.c, in order to
guarantee that the framebuffer code executes before the vmbus connection
is unloaded.
Patch 21 of this set puts the Hyper-V FB panic notifier on the pre_reboot
notifier list, which means it won't execute before the VMbus connection
unload in the case of kdump. This notifier is making sure that Hyper-V
is notified about the last updates made to the frame buffer before the
panic, so maybe it needs to be put on the hypervisor notifier list. It
sends a message to Hyper-V over its existing VMbus channel, but it
does not wait for a reply. It does, however, obtain a spin lock on the
ring buffer used to communicate with Hyper-V. Unless someone has
a better suggestion, I'm inclined to take the risk of blocking on that
spin lock.
The logic behind that was: when kdump is set, we'd skip the vmbus
disconnect on notifiers, deferring that to crash_shutdown(), logic this
one refuted in the above discussion on ARM64 (one more Pro argument to
the idea of refactoring aarch64 code to allow a custom crash shutdown
handler heh). But you're right, for the default level 2, we skip the
pre_reboot notifiers on kdump, effectively skipping this notifier.
Some ideas of what we can do here:
I) we could change the framebuffer notifier to rely on trylocks, instead
of risking a lockup scenario, and with that, we can execute it before
the vmbus disconnect in the hypervisor list;
II) we ignore the hypervisor notifier in case of kdump _by default_, and
if the users don't want that, they can always set the panic notifier
level to 4 and run all notifiers prior to kdump; would that be terrible
you think? Kdump users might don't care about the framebuffer...
III) we go with approach (b) above and refactor arm64 code to allow the
custom crash handler on kdump time, then [with point (I) above] the
logic proposed in this series is still valid - seems more and more the
most correct/complete solution.
In any case, I guess we should avoid workarounds if possible and do the
things the best way we can, to encompass all (or almost all) the
possible scenarios and don't force things on users (like enforcing panic
notifier level 4 for Hyper-V or something like this...)
More feedback from you / Hyper-V folks is pretty welcome about this.
quoted
[...]
The "Fixes:" tags imply that these changes should be backported to older
longterm kernel versions, which I don't think is the case. There is a
dependency on Patch 14 of your series where PANIC_NOTIFIER is
introduced.
Oh, this was more related with archeology of the kernel. When I'm
investigating stuff, I really want to understand why code was added and
that usually require some time git blaming stuff, so having that pronto
in the commit message is a bonus.
But of course we don't need to use the Fixes tag for that, easy to only
mention it in the text. A secondary benefit by using this tag is to
indicate this is a _real fix_ to some code, and not an improvement, but
as you say, I agree we shouldn't backport it to previous releases having
or not the Fixes tag (AFAIK it's not mandatory to backport stuff with
Fixes tag).
quoted
[...]
+ * intrincated is the relation of this notifier with Hyper-V framebuffer
s/intrincated/intricate/
Thanks, fixed in V2!
quoted
[...]
+static int hv_panic_vmbus_unload(struct notifier_block *nb, unsigned long val,
void *args)
+{
+ if (!kexec_crash_loaded())
I'm not clear on the purpose of this condition. I think it means
we will skip the vmbus_initiate_unload() if a panic occurs in the
kdump kernel. Is there a reason a panic in the kdump kernel
should be treated differently? Or am I misunderstanding?
This is really related with the point discussed in the top of this
response - I assumed both ARM64/x86_64 would behave the same and
disconnect the vmbus through the custom crash handler when kdump is set,
so worth skipping it here in the notifier. But that's not true for ARM64
as you pointed, so this guard against kexec is really part of the
decision/discussion on what to do with ARM64 heh
Cheers!
This patch improves the panic/die notifiers in this driver by
making use of a passed "id" instead of comparing pointer
address; also, it removes an useless prototype declaration
and unnecessary header inclusion.
This is part of a panic notifiers refactor - this notifier in
the future will be moved to a new list, that encompass the
information notifiers only.
Fixes: 9eb60880d9a9 ("bus: brcmstb_gisb: add notifier handling")
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Not sure if the Fixes tag is warranted however as this is a clean up,
and not really fixing a bug.
--
Florian
The panic notifier of this driver is very simple code-wise, just a memory
write to a special position with some numeric code. But this is not clear
from the semantic point-of-view, and there is no public documentation
about that either.
After discussing this in the mailing-lists [0] and having Florian explained
it very well, this patch just document that in the code for the future
generations asking the same questions. Also, it removes a useless header.
[0] https://lore.kernel.org/lkml/781cafb0-8d06-8b56-907a-5175c2da196a@gmail.com
Fixes: 0b741b8234c8 ("soc: bcm: brcmstb: Add support for S2/S3/S5 suspend states (ARM)")
Cc: Brian Norris <computersforpeace@gmail.com>
Cc: Doug Berger <opendmb@gmail.com>
Cc: Florian Fainelli <f.fainelli@gmail.com>
Cc: Justin Chen <redacted>
Cc: Lee Jones <redacted>
Cc: Markus Mayer <mmayer@broadcom.com>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Likewise, I am not sure if the Fixes tag is necessary here.
--
Florian
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-05-02 15:51:16
On 02/05/2022 12:38, Florian Fainelli wrote:
[...]
Acked-by: Florian Fainelli <f.fainelli@gmail.com>
Not sure if the Fixes tag is warranted however as this is a clean up,
and not really fixing a bug.
Perfect, thanks Florian. I'll add your ACK and remove the fixes tag in V2.
Cheers,
Guilherme
From: Michael Kelley (LINUX) <hidden> Date: 2022-05-03 17:32:04
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Friday, April 29, 2022 1:38 PM
On 29/04/2022 14:53, Michael Kelley (LINUX) wrote:
quoted
From: Guilherme G. Piccoli <gpiccoli@igalia.com> Sent: Wednesday, April 27, 2022
3:49 PM
quoted
quoted
[...]
+ panic_notifiers_level=
+ [KNL] Set the panic notifiers execution order.
+ Format: <unsigned int>
+ We currently have 4 lists of panic notifiers; based
+ on the functionality and risk (for panic success) the
+ callbacks are added in a given list. The lists are:
+ - hypervisor/FW notification list (low risk);
+ - informational list (low/medium risk);
+ - pre_reboot list (higher risk);
+ - post_reboot list (only run late in panic and after
+ kdump, not configurable for now).
+ This parameter defines the ordering of the first 3
+ lists with regards to kdump; the levels determine
+ which set of notifiers execute before kdump. The
+ accepted levels are:
+ 0: kdump is the first thing to run, NO list is
+ executed before kdump.
+ 1: only the hypervisor list is executed before kdump.
+ 2 (default level): the hypervisor list and (*if*
+ there's any kmsg_dumper defined) the informational
+ list are executed before kdump.
+ 3: both the hypervisor and the informational lists
+ (always) execute before kdump.
I'm not clear on why level 2 exists. What is the scenario where
execution of the info list before kdump should be conditional on the
existence of a kmsg_dumper? Maybe the scenario is described
somewhere in the patch set and I just missed it.
Hi Michael, thanks for your review/consideration. So, this idea started
kind of some time ago. It all started with a need of exposing more
information on kernel log *before* kdump and *before* pstore -
specifically, we're talking about panic_print. But this cause some
reactions, Baoquan was very concerned with that [0]. Soon after, I've
proposed a panic notifiers filter (orthogonal) approach, to which Petr
suggested instead doing a major refactor [1] - it finally is alive in
the form of this series.
The theory behind the level 2 is to allow a scenario of kdump with the
minimum amount of notifiers - what is the point in printing more
information if the user doesn't care, since it's going to kdump? Now, if
there is a kmsg dumper, it means that there is likely some interest in
collecting information, and that might as well be required before the
potential kdump (which is my case, hence the proposal on [0]).
Instead of forcing one of the two behaviors (level 1 or level 3), we
have a middle-term/compromise: if there's interest in collecting such
data (in the form of a kmsg dumper), we then execute the informational
notifiers before kdump. If not, why to increase (even slightly) the risk
for kdump?
I'm OK in removing the level 2 if people prefer, but I don't feel it's a
burden, quite opposite - seems a good way to accommodate the somewhat
antagonistic ideas (jump to kdump ASAP vs collecting more info in the
panicked kernel log).
[0] https://lore.kernel.org/lkml/20220126052246.GC2086@MiWiFi-R3L-srv/
[1] https://lore.kernel.org/lkml/YfPxvzSzDLjO5ldp@alley/
To me, it's a weak correlation between having a kmsg dumper, and
wanting or not wanting the info level output to come before kdump.
Hyper-V is one of only a few places that register a kmsg dumper, so most
Linux instances outside of Hyper-V guest (and PowerPC systems?) will have
the info level output after kdump. It seems like anyone who cared strongly
about the info level output would set the panic_notifier_level to 1 or to 3
so that the result is more deterministic. But that's just my opinion, and
it's probably an opinion that is not as well informed on the topic as some
others in the discussion. So keeping things as in your patch set is not a
show-stopper for me.
However, I would request a clarification in the documentation. The
panic_notifier_level affects not only the hypervisor, informational,
and pre_reboot lists, but it also affects panic_print_sys_info() and
kmsg_dump(). Specifically, at level 1, panic_print_sys_info() and
kmsg_dump() will not be run before kdump. At level 3, they will
always be run before kdump. Your documentation above mentions
"informational lists" (plural), which I take to vaguely include
kmsg_dump() and panic_print_sys_info(), but being explicit about
the effect would be better.
Michael
quoted
[...]
quoted
+ * Based on the level configured (smaller than 4), we clear the
+ * proper bits in "panic_notifiers_bits". Notice that this bitfield
+ * is initialized with all notifiers set.
+ */
+ switch (panic_notifiers_level) {
+ case 3:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+ break;
+ case 2:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+
+ if (!kmsg_has_dumpers())
+ clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
+ break;
+ case 1:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+ clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
+ break;
+ case 0:
+ clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
+ clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
+ clear_bit(PN_HYPERVISOR_BIT, &panic_notifiers_bits);
+ break;
+ }
I think the above switch statement could be done as follows:
if (panic_notifiers_level <= 3)
clear_bit(PN_PRE_REBOOT_BIT, &panic_notifiers_bits);
if (panic_notifiers_level <= 2)
if (!kmsg_has_dumpers())
clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
if (panic_notifiers_level <=1)
clear_bit(PN_INFO_BIT, &panic_notifiers_bits);
if (panic_notifiers_level == 0)
clear_bit(PN_HYPERVISOR_BIT, &panic_notifiers_bits);
That's about half the lines of code. It's somewhat a matter of style,
so treat this as just a suggestion to consider. I just end up looking
for a better solution when I see the same line of code repeated
3 or 4 times!
It's a good idea - I liked your code. The switch seems more
natural/explicit for me, even duplicating some lines, but in case more
people prefer your way, I can definitely change the code - thanks for
the suggestion.
Cheers,
Guilherme
Using the hypervisor_list here produces a bit of a mismatch. In many cases
this notifier will do nothing, and will defer to the kmsg_dump() mechanism
to notify the hypervisor about the panic. Running the kmsg_dump()
mechanism is linked to the info_list, so I'm thinking the Hyper-V panic report
notifier should be on the info_list as well. That way the reporting behavior
is triggered at the same point in the panic path regardless of which
reporting mechanism is used.
Hi Michael, thanks for your feedback! I agree that your idea could work,
but...there is one downside: imagine the kmsg_dump() approach is not set
in some Hyper-V guest, then we would rely in the regular notification
mechanism [hv_die_panic_notify_crash()], right?
But...you want then to run this notifier in the informational list,
which...won't execute *by default* before kdump if no kmsg_dump() is
set. So, this logic is convoluted when you mix it with the default level
concept + kdump.
Yes, you are right. But to me that speaks as much to the linkage
between the informational list and kmsg_dump() being the core
problem. But as I described in my reply to Patch 24, I can live with
the linkage as-is.
FWIW, guests on newer versions of Hyper-V will always register a
kmsg dumper. The flags that are tested to decide whether to
register provide compatibility with older versions of Hyper-V that
don’t support the 4K bytes of notification info.
May I suggest something? If possible, take a run with this patch set +
DEBUG_NOTIFIER=y, in *both* cases (with and without the kmsg_dump()
set). I did that and they run almost at the same time...I've checked the
notifiers called, it's like almost nothing runs in-between.
I feel the panic notification mechanism does really fit with a
hypervisor list, it's a good match with the nature of the list, which
aims at informing the panic notification to the hypervisor/FW.
Of course we can modify it if you prefer...but please take into account
the kdump case and how it complicates the logic.
I agree that the runtime effect of one list vs. the other is nil. The
code works and can stay as you written it.
I was trying to align from a conceptual standpoint. It was a bit
unexpected that one path would be on the hypervisor list, and the
other path effectively on the informational list. When I see
conceptual mismatches like that, I tend to want to understand why,
and if there is something more fundamental that is out-of-whack.
Let me know your considerations, in case you can experiment with the
patch set as-is.
Cheers,
Guilherme
From: "Guilherme G. Piccoli" <gpiccoli@igalia.com> Date: 2022-05-03 17:58:10
On 03/05/2022 14:44, Michael Kelley (LINUX) wrote:
[...]
quoted
Hi Michael, thanks for your feedback! I agree that your idea could work,
but...there is one downside: imagine the kmsg_dump() approach is not set
in some Hyper-V guest, then we would rely in the regular notification
mechanism [hv_die_panic_notify_crash()], right?
But...you want then to run this notifier in the informational list,
which...won't execute *by default* before kdump if no kmsg_dump() is
set. So, this logic is convoluted when you mix it with the default level
concept + kdump.
Yes, you are right. But to me that speaks as much to the linkage
between the informational list and kmsg_dump() being the core
problem. But as I described in my reply to Patch 24, I can live with
the linkage as-is.
Thanks for the feedback Michael!
[...]
quoted
I feel the panic notification mechanism does really fit with a
hypervisor list, it's a good match with the nature of the list, which
aims at informing the panic notification to the hypervisor/FW.
Of course we can modify it if you prefer...but please take into account
the kdump case and how it complicates the logic.
I agree that the runtime effect of one list vs. the other is nil. The
code works and can stay as you written it.
I was trying to align from a conceptual standpoint. It was a bit
unexpected that one path would be on the hypervisor list, and the
other path effectively on the informational list. When I see
conceptual mismatches like that, I tend to want to understand why,
and if there is something more fundamental that is out-of-whack.
Totally agree with you here, I am like that as well - try to really
understand the details, this is very important specially in this patch
set, since it's a refactor and affects every user of the notifiers
infrastructure.
Again, just to double-say it: feel free to suggest any change for the
Hyper-V portion (might as well for any patch in the series, indeed) -
you and the other Hyper-V maintainers own this code and I'd be glad to
align with your needs, you are honor citizens in the panic notifiers
area, being one the most heavy users for that =)
Cheers,
Guilherme
From: Evan Green <hidden> Date: 2022-05-03 18:04:24
On Wed, Apr 27, 2022 at 3:51 PM Guilherme G. Piccoli
[off-list ref] wrote:
quoted hunk
Currently the gsmi driver registers a panic notifier as well as
reboot and die notifiers. The callbacks registered are called in
atomic and very limited context - for instance, panic disables
preemption, local IRQs and all other CPUs that aren't running the
current panic function.
With that said, taking a spinlock in this scenario is a
dangerous invitation for a deadlock scenario. So, we fix
that in this commit by changing the regular spinlock with
a trylock, which is a safer approach.
Fixes: 74c5b31c6618 ("driver: Google EFI SMI")
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: David Gow <redacted>
Cc: Evan Green <redacted>
Cc: Julius Werner <jwerner@chromium.org>
Signed-off-by: Guilherme G. Piccoli <gpiccoli@igalia.com>
---
drivers/firmware/google/gsmi.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
@@ -629,7 +629,10 @@ static int gsmi_shutdown_reason(int reason)if(saved_reason&(1<<reason))return0;-spin_lock_irqsave(&gsmi_dev.lock,flags);+if(!spin_trylock_irqsave(&gsmi_dev.lock,flags)){+rc=-EBUSY;+gotoout;+}
gsmi_shutdown_reason() is a common function called in other scenarios
as well, like reboot and thermal trip, where it may still make sense
to wait to acquire a spinlock. Maybe we should add a parameter to
gsmi_shutdown_reason() so that you can get your change on panic, but
we don't convert other callbacks into try-fail scenarios causing us to
miss logs.
Though thinking more about it, is this really a Good Change (TM)? The
spinlock itself already disables interrupts, meaning the only case
where this change makes a difference is if the panic happens from
within the function that grabbed the spinlock (in which case the
callback is also likely to panic), or in an NMI that panics within
that window. The downside of this change is that if one core was
politely working through an event with the lock held, and another core
panics, we now might lose the panic log, even though it probably would
have gone through fine assuming the other core has a chance to
continue.
-Evan