Booting, halting and power management
Booting and halting
[edit | edit source]Boot sequence
[edit | edit source]- Firmware/POST – hardware initialization, device detection
- Bootloader (GRUB, systemd-boot, EFI stub doc) – loads kernel image into memory
- Kernel – decompresses, initializes, starts man 1 init
Kernel booting
[edit | edit source]This is loaded in two stages - in the first stage the kernel (as a compressed image file) is loaded into memory and decompressed, and a few fundamental functions such as essential hardware and basic memory management (memory paging) are set up. Control is then switched one final time to the main kernel start process calling start_kernel id, which then performs the majority of system setup (interrupts, the rest of memory management, device and driver initialization, etc.) before spawning separately, the idle process and scheduler, and the init process (which is executed in user space).
Kernel loading stage
The kernel as loaded is typically an image file, compressed into either zImage or bzImage formats with zlib. A routine at the head of it does a minimal amount of hardware setup, decompresses the image fully into high memory, and takes note of any RAM disk if configured. It then executes kernel startup via startup_64 (for x86_64 architecture).
- arch/x86/boot src – boot protocol, CPU feature detection (x86 Feature Flags doc)
- arch/x86/boot/compressed/vmlinux.lds.S src - linker script defines entry startup_64 id in
- arch/x86/boot/compressed/head_64.S src - assembly of extractor
- extract_kernel id - extractor in language C
- prints
Decompressing Linux... done. Booting the kernel.
Kernel startup stage
The startup function for the kernel (also called the swapper or process 0) establishes memory management (paging tables and memory paging), detects the type of CPU and any additional functionality such as floating point capabilities, and then switches to non-architecture specific Linux kernel functionality via a call to start_kernel id.
↯ Startup call hierarchy:
- arch/x86/kernel/vmlinux.lds.S src – linker script
- arch/x86/kernel/head_64.S src – assembly of uncompressed startup code
- arch/x86/kernel/head64.c src – platform dependent startup:
- init/main.c src – main initialization code
- init/init_task.c src – initial task (PID 0, swapper), init_task id
- init/do_mounts.c src – root device mounting (mount_root id, prepare_namespace id)
- init/do_mounts_initrd.c src – initrd (initial ramdisk) unpacking and pivot to real root
- init/do_mounts_rd.c src – RAM disk image mounting (legacy rd= parameter)
- init/initramfs.c src – built-in initramfs (cpio) unpacking (populate_rootfs id)
- init/calibrate.c src – BogoMIPS delay loop calibration (calibrate_delay id)
- init/version.c src – kernel version string and build timestamp (linux_banner id)
- init/noinitramfs.c src – default root mount when no initramfs is configured
- start_kernel id 200 SLOC
- mm_init id
- sched_init id
- rcu_init id – Read-copy-update
- rest_init id
- kernel_init id - deferred kernel thread #1
- kernel_init_freeable id This and following functions are defined with attribute __init id
- run_init_process id obviously runs the first process man 1 init
- kthreadd id – deferred kernel thread #2
- cpu_startup_entry id
- kernel_init id - deferred kernel thread #1
- start_kernel id 200 SLOC
🛠️ Utilities
- man 8 dracut – generate initramfs images; dracut --list-modules shows available modules
- man 1 lsinitrd – list contents of an initramfs image
start_kernel id executes a wide range of initialization functions. It sets up interrupt handling (IRQs), further configures memory, starts the man 1 init process (the first user-space process), and then starts the idle task via cpu_startup_entry id. Notably, the kernel startup process also mounts the initial ramdisk (initrd) that was loaded previously as the temporary root file system during the boot phase. The initrd allows driver modules to be loaded directly from memory, without reliance upon other devices (e.g. a hard disk) and the drivers that are needed to access them (e.g. a SATA driver). This split of some drivers statically compiled into the kernel and other drivers loaded from initrd allows for a smaller kernel. The root file system is later switched via a call to man 8 pivot_root / man 2 pivot_root which unmounts the temporary root file system and replaces it with the use of the real one, once the latter is accessible. The memory used by the temporary root file system is then reclaimed.
⚙️ Internals
- arch/x86/Kconfig.debug src – x86 debugging Kconfig options
- linux/smpboot.h inc
- kernel/smpboot.c src – common SMP CPU bringup/teardown
- arch/x86/kernel/smpboot.c src – x86 SMP booting
- linux/kallsyms.h inc, kernel/kallsyms.c src – the /proc/kallsyms kernel symbol table
...
[edit | edit source]📖 References
- Article about booting of the kernel
- Initial RAM disk doc
- initcall_debug, boot argument
- Linux startup process
- init
- Linux (U)EFI boot process
- The kernel’s command-line parameters doc
- The EFI Boot Stub doc
- Boot Configuration doc
- Boot time memory management doc
- Kernel booting process
- Kernel initialization process
📚 Further reading
💾 Historical
- http://tldp.org/HOWTO/Linux-i386-Boot-Code-HOWTO/
- http://www.tldp.org/LDP/lki/lki-1.html
- http://www.tldp.org/HOWTO/KernelAnalysis-HOWTO-4.html
Halting or rebooting
[edit | edit source]🔧 TODO
⚲ API
- linux/reboot.h inc
- linux/stop_machine.h inc
- man 2 reboot ↪ sys_reboot id
- man 2 kexec_load ↪ kernel/kexec.c src – load a new kernel for later execution (kdump)
- reboot_mode id
- linux/reboot-mode.h inc
⚙️ Internals
- kernel/reboot.c src – reboot, halt and power-off
- kernel/stop_machine.c src – stop all CPUs for safe code patching
- cpu_stopper id
- cpu_stop_init id
- cpu_stopper_thread id – "migration" tasks
- arch/x86/kernel/reboot.c src – x86 reboot methods
Power management
[edit | edit source]Keyword: suspend, alarm, hibernation.
⚲ API
- /sys/power/
- /sys/kernel/debug/wakeup_sources
- ⌨️ hands-on:
- sudo awk '{gsub("^ ","?")} NR>1 {if ($6) {print $1}}' /sys/kernel/debug/wakeup_sources
- linux/pm.h inc
- linux/pm_qos.h inc
- linux/pm_clock.h inc
- linux/pm_domain.h inc
- linux/pm_wakeirq.h inc
- linux/pm_wakeup.h inc
- linux/suspend.h inc
- pm_suspend id suspends the system
- linux/freezer.h inc – process freezer for suspend/hibernate
- Suspend and wakeup depend on
- man 2 timer_create and man 2 timerfd_create with clock ids CLOCK_REALTIME_ALARM id or CLOCK_BOOTTIME_ALARM id will wake the system if it is suspended.
- man 2 epoll_ctl with flag EPOLLWAKEUP id blocks suspend
- See also man 7 capabilities CAP_WAKE_ALARM id, CAP_BLOCK_SUSPEND id
⚙️ Internals
- CONFIG_PM id
- CONFIG_SUSPEND id
- kernel/power src – suspend, hibernate and PM core
- alarm_init id
- kernel/time/alarmtimer.c src – alarm timer for wakeup events
- drivers/base/power src: wakeup_sources id
📖 References
- PM administration doc
- CPU and Device PM doc
- Power Management doc
- sysfs power testing ABI doc
- https://lwn.net/Kernel/Index/#Power_management
- PowerTOP
- cpupower
- tlp – apply laptop power management settings
- ACPI – Advanced Configuration and Power Interface
Runtime PM
[edit | edit source]Keywords: runtime power management, devices power management opportunistic suspend, autosuspend, autosleep.
⚲ API
- /sys/devices/.../power/:
- async autosuspend_delay_ms control runtime_active_kids runtime_active_time runtime_enabled runtime_status runtime_suspended_time runtime_usage
- linux/pm_runtime.h inc
- pm_runtime_mark_last_busy id
- devm_pm_runtime_enable id
- pm_runtime_disable id
- pm_runtime_get id – asynchronous get
- pm_runtime_get_sync id
- pm_runtime_resume_and_get id – preferable synchronous get
- pm_runtime_put id
- pm_runtime_put_noidle id – just decrement usage counter
- pm_runtime_put_sync id
- pm_runtime_put_autosuspend id
- SET_RUNTIME_PM_OPS id
👁 Example: ac97_pm id
⚙️ Internals
...
[edit | edit source]📖 References
- Runtime Power Management Framework for I/O Devices doc
- CPU idle power saving methods for real-time workloads
- Sysfs devices PM API
- Power Management for USB
- Opportunistic suspend
📚 Further reading