Linux kernel

From indicium
Jump to navigation Jump to search

Kernel drivers


Building the kernel

Configure

config using defconfig

To configure using a specified defconfig for a specified architecture

make ARCH=x86 i386_defconfig
menuconfig using defconfig

To menuconfig starting from a specified defconfig for a specified architecture

make menuconfig ARCH=x86 i386_defconfig

Be sure to explicitly save the configuration.

menuconfig using .config

To menuconfig starting from a .config for a specified architecture

make menuconfig ARCH=x86

When inside menuconfig, choose "Load" and specify path to your .config Then edit the configuration as you see fit, then choose "Save" and save it as ".config" only. Then you can exit menuconfig and do:

make savedefconfig ARCH=x86

to save your updated, minimal defconfig. Be sure to specify your architecture at all times (if it is not the default x86).

Build

make -j4 ARCH=x86 CROSS_COMPILE=/bin/i686-linux- all

Various kernel information

New Linux network names

https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/

Tips for booting the kernel on a new ARM board

Step 1 - Uncompressing

Do you get the "Uncompressing Linux... done, booting the kernel." print? If not and you are on an ARM architecture, you can enable:

CONFIG_EARLY_PRINTK=y
CONFIG_DEBUG_LL=y
CONFIG_DEBUG_LL_UART_PL01X=y
CONFIG_DEBUG_UART_PHYS=0xF7800000
CONFIG_DEBUG_UART_VIRT=0xF7800000

If you are working on a arm64 architecture, DEBUG_LL is no longer available. The new way to do the same thing is to append something like the following to your kernel cmdline:

earlycon=pl011,mmio32,0xF7800000

More info on earlycon and other kernel cmdline options: https://www.kernel.org/doc/html/v4.14/admin-guide/kernel-parameters.html

In both cases you have to adjust the UART config according to your platform! Now you should get the Uncompressing Linux... print, otherwise your bootloader has either:

  • Not uploaded the kernel to RAM.
  • Not jumped to the correct place in RAM to execute it.

Good places to check out:

arch/arm/boot/compressed/head.S
arch/arm/boot/compressed/misc.c

Step 2 - First assembly files

The kernel will boot in two different ways:

  • Without device tree support (old style). Your bootloader should have set up register r1 to contain the machine ID and register r2 to contain a pointer to the ATAGS area.
  • With device tree support (new style). Your bootloader should have set up register r2 to contain a pointer to the DTB (device tree blob).

Do you get "Error: unrecognized/unsupported processor variant (0x414fc091)."? Then you have set your defconfig flags in your kernel to the wrong CPU type. Make sure to check if your CPU is an ARMv5, ARMv7 or whatever and set the correct defconfig flags (such as CONFIG_ARCH_ and CONFIG_CPU_).

Good places to check out:

arch/arm/kernel/head-common.S

Step 3 - early c code

You should now be able to reach the function start_kernel() in file init/main.c. This is great place to start off. prints are working differently here, the CONFIG_DEBUG_LL and EARLY_PRINTK is not working here, but once you reach the setup_arch() function in arch/arm/kernel/setup.c, you can use the early_print() function to print stuff using the CONFIG_DEBUG_LL stuff again!

Hack to get something on the serial line

If you have trouble getting the regular pr_xxxx-prints going, then you can replace them all in this file with early_print() instead.

Another good hack is to copy the function early_print() from file arch/arm/kernel/setup.c, and replace the function printk() in file kernel/prink/printk.c with the implementation from early_print(). Now all printk:s will be redirected to be output by the early assembler routines enabled by CONFIG_DEBUG_LL.

Good places to start with are:

init/main.c
arch/arm/kernel/setup.c
arch/arm/kernel/devtree.c

Step 4 - interrupts and timers

If the board hangs at calibrate_delay() (you may see "Calibrating delay loop..." in the console), then your interrupts are not working. Check that the correct driver for your IRQ block has been enabled by defconfigs and that you have added correct configuration in your devicetree.

Step 5 - getting the serial running the proper way

Make sure you have enabled the correct drivers for your serial HW block and added configuration for them in the devicetree if applicable.

Then make sure you have set up the kernel command line to contain a console keyword with a suitable UART configuration, either in your device tree file (*.dts) or in your defconfig (CONFIG_CMDLINE="console=ttyAMA0,115200 earlyprintk init=/linuxrc") or that it is given from your bootloader. Make sure it is set up to the correct UART and speed.

Step 6 - debugging initcalls

If your kernel just stops or crashes in the later stages of kernel boot, it might be good to add the following option to the kernel command line: initcall_debug

Note however that the prints are printed at DEBUG log level, so if you want to see them, you have to make sure that also DEBUG prints are printed. It might be worthwhile to also add ignore_loglevel

Other options that might be added can be found here: https://github.com/torvalds/linux/blob/master/Documentation/admin-guide/kernel-parameters.txt

Other logging tips

If you want to dump out a buffer or a bunch of registers, then you can use the excellent:

print_hex_dump_bytes("HEX: ", DUMP_PREFIX_OFFSET, buf, size);