How to use kexec for fast reboot/crashdump.
What is kexec
?
kexec
is a system call
that allows user to load a kernel into the memory, and boot
directly from it, without time-consuming bootloading.
This is useful for kernel developers or other people who need
to reboot very quickly without waiting for the whole BIOS boot
process to finish. Moreover, it is also used to boot up an
“emergency kernel” upon crash (e.g., panic()
). This
material
explains this.
Install and Config kexec
Kernel Configuration
To use kexec
, the following kernel config must be enabled.
Processor type and features --->
[*] kexec system call
[*] kexec file based system call
If you need crashdump, then the following config is needed as well.
Processor type and features --->
[*] kexec system call
[*] kernel crash dumps
[*] Build a relocatable kernel
Kernel hacking --->
[*] Kernel debugging
Compile-time checks and compiler options --->
[*] Compile the kernel with debug info
File systems --->
Pseudo filesystems --->
-*- /proc file system support
[*] /proc/kcore support
[*] /proc/vmcore support
GRUB Configuration
One need to prepare sufficient space for kexec
to put the
new kernel. Therefore, we need to add/modify the following line
in /etc/default/grub
.
GRUB_CMDLINE_LINUX="crashkernel=1024M,high nokaslr"
The crashkernel
might be a lower value if you have less
memory available. My PC has 32 GiB of memory, just for reference.
The nokaslr
disables address space randomization so that,
GDB can correctly recognize debug symbols from /proc/vmcore
.
Installation
Use the following to install userland utilities (on Gentoo).
sudo emerge --ask --verbose sys-apps/kexec-tools
Usage I: Fast Reboot
For fast reboot, the command is simple. Note that the --initrd
is not mandatory if you don’t have one. Moreover, --append
might be replaced with --reuse-cmdline
if you want to use
the same set of cmdline arguments.
kexec -l path_to_kernel_image --initrd=path_to_initrd_image \
--append=command-line-options
A concrete example would the following.
sudo kexec -l /boot/vmlinuz-6.1.38 --reuse-cmdline
With new kernel loaded, you can use the following command
to fast reboot if you’re using systemd
.
sudo systemctl kexec
Usage II: Crash Dump
For crashdump, things are a far more complicated. Here is a list of points to pay attention.
- Use
-p
instead of-l
to load crashdump kernel. - Remove unnecessary modules via
modprobe.blacklist=<comma-separated-list>
. - Limit the number of CPUs by
maxcpus=1
. - Use
irqpoll
for stable interrupt handling.
With all that, we can come up with the following command.
sudo kexec -p /boot/vmlinuz-6.1.31-gentoo --reset-vga --console-vga \
--command-line="root=/dev/nvme0n1p5 maxcpus=1 irqpoll quite splash loglevel=3 \
systemd.show_status=false modprobe.blacklist=iptable_nat,nvidia_drm \
,nvidia_modeset,nvidia,iwlmvm,kvm_intel,iwlwifi,fuse,efivarfs \
systemd.journald.forward_to_console=no"
If you’re using a X-based GUI environment, I would suggest
that you use VTx
via Ctrl+Alt+F{1-6}
before you do something
to crash your kernel otherwise kernel will just be stuck.
Sidenote: If you are using a display manager (e.g., lxdm) repeatedly respawn itself on failure. This repeated behavior should be disabled, since it will force the screen to constantly switch back to VT1. For
systemd
, just comment outRestart=Always
to prevent this.