[Linux Tech Share][Startup Debugging][initcall_debug and ignore_loglevel]

In the Linux kernel startup and debugging process,initcall_debug and ignore-loglevel are key startup parameters that allow for deep tracking of the initialization process and log output. The following example is based on the 6.8 kernel used in the RUBIK Pi 3 Ubuntu/Debian system.

initcall_debug

After this parameter is enabled, the kernel will output execution details of all initialization functions and driver probe functions, including function return values, execution time, and process IDs, which is essential for pinpointing boot delays or initialization failures. Check the following example:

[    7.042579] probe of 100000000.gpio-regulator returned -517 after 0 usecs
[    7.042587] probe of 0.gpio-regulator returned -517 after 0 usecs
[    7.042702] calling  gpio_regulator_init+0x0/0x50 @ 1
[    7.042799] initcall gpio_regulator_init+0x0/0x50 returned 0 after 1000 usecs

Enable initcall_debug:

  1. Modify the /etc/default/grub configuration file on the target board by adding the initcall_debug parameter to the GRUB_CMDLINE_LINUX variable, as shown below:
GRUB_CMDLINE_LINUX="root=LABEL=writable rw console=ttyMSM0,115200n8 pcie_pme=nomsi earlycon ignore_loglevel initcall_debug"
  1. Execute the following commands to update the grub configuration. The changes apply after a reboot. If you want the kernel debug messages to be printed via the serial port during boot, add the ignore_loglevel parameter to the GRUB_CMDLINE_LINUX variable:
sudo update-grub
sudo reboot

Alternatively, during boot, press the e key in the GRUB menu to boot the kernel with modified boot parameters.

Source code analysis:

init/main.c

bool initcall_debug;
core_param(initcall_debug, initcall_debug, bool, 0644);

If initcall_debug is defined in the kernel startup parameters, the initcall_debug variable will be set to true. In the start_kernel function, initcall_debug_enable will be called.

Finally, the execution parameters of the initialization functions are printed through the functions trace_initcall_start_cb and trace_initcall_finish_cb, as shown below:

void start_kernel(void)
{

...
        if (initcall_debug)
                initcall_debug_enable();
...

}

static void __init initcall_debug_enable(void)
{
        int ret;

        ret = register_trace_initcall_start(trace_initcall_start_cb,
                                            &initcall_calltime);
        ret |= register_trace_initcall_finish(trace_initcall_finish_cb,
                                              &initcall_calltime);
        WARN(ret, "Failed to register initcall tracepoints\n");
}

static __init_or_module void
trace_initcall_start_cb(void *data, initcall_t fn)
{
        ktime_t *calltime = data;

        printk(KERN_DEBUG "calling  %pS @ %i\n", fn, task_pid_nr(current));
        *calltime = ktime_get();
}

static __init_or_module void
trace_initcall_finish_cb(void *data, initcall_t fn, int ret)
{
        ktime_t rettime, *calltime = data;

        rettime = ktime_get();
        printk(KERN_DEBUG "initcall %pS returned %d after %lld usecs\n",
                 fn, ret, (unsigned long long)ktime_us_delta(rettime, *calltime));
}

The information printing for the probe function is handled through the __driver_probe_device function, which checks the initcall_debug variable to determine whether to call the really_probe or really_probe_debug function:

drivers/base/dd.c

static int __driver_probe_device(struct device_driver *drv, struct device *dev)
{
...
        if (initcall_debug)
                ret = really_probe_debug(dev, drv);
        else
                ret = really_probe(dev, drv);
...
}

ignore_loglevel

This parameter is used to forcibly output kernel logs at all levels in the terminal to avoid the loss of debugging information due to log level filtering. It is suitable for troubleshooting problems during early startup.

Enable ignore_loglevel:

  1. Modify the /etc/default/grub configuration file on the target board by adding the ignore_loglevel parameter to the GRUB_CMDLINE_LINUX variable, as shown below:
GRUB_CMDLINE_LINUX="root=LABEL=writable rw console=ttyMSM0,115200n8 pcie_pme=nomsi earlycon ignore_loglevel initcall_debug"
  1. Execute the following commands to update the grub configuration. The changes apply after a reboot.
sudo update-grub
sudo reboot

Alternatively, during boot, press the e key in the GRUB menu to boot the kernel with modified boot parameters.

Source code analysis:

kernel/printk/printk.c

static bool __read_mostly ignore_loglevel;

static int __init ignore_loglevel_setup(char *str)
{
        ignore_loglevel = true;
        pr_info("debug: ignoring loglevel setting.\n");

        return 0;
}

early_param("ignore_loglevel", ignore_loglevel_setup);
module_param(ignore_loglevel, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(ignore_loglevel,
                 "ignore loglevel setting (prints all kernel messages to the console)");

static bool suppress_message_printing(int level)
{
        return (level >= console_loglevel && !ignore_loglevel);
}

After adding ignore_loglevel to the startup parameters, it can be found in the above code that the ignore_loglevel variable is set to true, and the suppress_message_printing function will always return false, indicating that the log printing is not disabled.

Additionally, after booting up, you can set the ignore-loglevel parameter at any time through the /sys/module/printk/parameters/ignore_loglevel node:

cat /sys/module/printk/parameters/ignore_loglevel   # View the current status
echo 1 > /sys/module/printk/parameters/ignore_loglevel   # Set to true
echo 0 > /sys/module/printk/parameters/ignore_loglevel  # Set to false

For more kernel parameters, check the Documentation/admin-guide/kernel-parameters.txt file in the kernel source code.

2025-06-30T16:00:00Z
Original post: [linux 技术分享][启动调试][initcall_debug 与 ignore_loglevel] - 技术分享 - RUBIK Pi by Hongyang Zhao