Archive for July, 2017

What are the xxx_initcall() in linux kernel source codes?

Searching through some of the linux kernel source for xxxx_initcall() (master list I have compiled is here:   tthtlc.wordpress.com/a-compilation-of-the-xxx_initcall-initialization-routines-in-linux-kernel/):

./kernel/apic/apic.c:
early_initcall(validate_x2apic);
core_initcall(init_lapic_sysfs);
late_initcall(lapic_insert_resource);

./kernel/apic/io_apic.c:
device_initcall(ioapic_init_ops);

./kernel/apic/vector.c:
late_initcall(print_ICs);

./kernel/apic/probe_32.c:
late_initcall(print_ipi_mode);

./kernel/apic/x2apic_uv_x.c:
late_initcall(uv_init_heartbeat);

./kernel/apic/apic_numachip.c:
early_initcall(numachip_system_init);

./kernel/pcspeaker.c:
device_initcall(add_pcspkr);

./kernel/devicetree.c:
device_initcall(add_bus_probe);

./kernel/sysfb.c:
device_initcall(sysfb_init);

./xen/p2m.c:
fs_initcall(xen_p2m_debugfs);

./xen/grant-table.c:
core_initcall(xen_pvh_gnttab_setup);

./pci/broadcom_bus.c:
postcore_initcall(broadcom_postcore_init);

./pci/amd_bus.c:
postcore_initcall(amd_postcore_init);

You can see that there are many different types of xxx_initcall():

Going to the definition part:

./include/linux/init.h:

#define core_initcall(fn) __define_initcall(fn, 1)
#define core_initcall_sync(fn) __define_initcall(fn, 1s)
#define postcore_initcall(fn) __define_initcall(fn, 2)
#define postcore_initcall_sync(fn) __define_initcall(fn, 2s)
#define arch_initcall(fn) __define_initcall(fn, 3)
#define arch_initcall_sync(fn) __define_initcall(fn, 3s)
#define subsys_initcall(fn) __define_initcall(fn, 4)
#define subsys_initcall_sync(fn) __define_initcall(fn, 4s)
#define fs_initcall(fn) __define_initcall(fn, 5)
#define fs_initcall_sync(fn) __define_initcall(fn, 5s)
#define rootfs_initcall(fn) __define_initcall(fn, rootfs)
#define device_initcall(fn) __define_initcall(fn, 6)
#define device_initcall_sync(fn) __define_initcall(fn, 6s)
#define late_initcall(fn) __define_initcall(fn, 7)
#define late_initcall_sync(fn) __define_initcall(fn, 7s):

And so what are these initcall()?

Essentially these are to indicate to the kernel the name of the functions that does the initialization for each part of the kernel the developer is writing.   Different parts of kernel will have the initialization function called in different order.

When are they called?

Inside Linux kernel –> init/main.c:start_kernel():

And then start_kernel() eventually called rest_init():

So rest_init() will call kernel_thread() to start kernel_init() function which then call kernel_init_freeable(), which eventually called do_pre_smp_initcalls():

And later – after do_pre_smp_initcalls(), do_basic_setup() will also be calling the initcall() (via do_initcalls()):

As shown below:

And now the do_initcalls() actually traversed through all the different levels of initcalls():

How to debug these initcall()?
Image result for calling sequence of initcall in linux kernel

References:

  1. http://linuxgazette.net/157/amurray.html
  2. http://blog.techveda.org/kernel__initcalls/
  3. https://stackoverflow.com/questions/18605653/linux-module-init-vs-core-initcall-vs-early-initcall
  4. https://stackoverflow.com/questions/10368837/how-does-linux-determine-the-order-of-module-init-calls
  5. https://stackoverflow.com/questions/10540008/how-kernel-determine-the-sequence-of-init-calls
  6. https://lwn.net/Articles/141730/
  7. http://www.compsoc.man.ac.uk/~moz/kernelnewbies/documents/initcall/kernel.html
  8. https://0xax.gitbooks.io/linux-insides/content/Concepts/initcall.html
Advertisements

HUGE memory copy

This is from mm/memory.c: copy_huge_page_from_user(), which is to copy memory from userspace to kernel, where the kernel is setup with HUGE page as the page table.

Look at the cond_resched() in the last few lines.

What does that mean? It means the the kernel has voluntarily schedule itself out, and if there are other more urgent process that need to be executed, it will take over the ownership of the CPU to continue execution.

In general, any long or large operation: always introduce cond_resched() to ensure the kernel will not be hijacked by these long running process.

%d bloggers like this: