My first contribution to Linux Kernel: Step by step
*This post is under construction. I am in the process of trying to contribute to the Linux Kernel. This post is not finished and will get updated as I go*
I use a MacBook Pro (mid-2014) with macOS, so I need to have a virtual machine for running a linux system with my kernel. I will also be doing the coding on this linux virtual machine as building the kernel is easier in a linux system than macOS.
Setting up the Virtual Machine (Archlinux)
I create a virtual machine with Archlinux on my macOS using QEMU:
- Download the Archlinux iso image
- Create a qemu disk
- Start the machine and install Archlinux
- Start the machine after installing (note I forward 2222 to 22 so I can SSH/SCP to the virtual machine. I also set 4 CPUs so I can use threads for faster builds in the VM)
- Install dependencies for building the kernel
- Clone linux
- Install the necessary dependencies for building the kernel
- Copy configuration of archlinux (optional: also use modprobed-db to remove unnecessary modules)
- Make sure you enable debugging configurations
- Make! The
-j8parameter specifies the number of threads to be used by the build. My CPU has 8 threads and so I use it all.
- Install the newly built Kernel. I create this as a script file and run it after every build from the root of repository.
- Reboot and choose the new kernel (might be under “Advanced” in the bootloader)
Setup your environment for development. Mine consists of setting up tmux so I can have multiple terminals and neovim.
In the guest machine:
And in the host:
One thing I found necessary, due to limited storage, is a script to cleanup each linux version after I’m done with them, since they create a couple of files in different places. I call this
There is a
pr_debug function used over the code, in order to enable those logs in
dmesg for a specific module, you can do this:
Note that, this works if you have dynamic debug enabled in your
You can then look at
dmesg while running the code to see those logs:
Kernel Oops, Bug and Panic
If you get a Kernel Oops, Kernel Bug or similar, here are some good resources on how to read and understand the output:
- Understanding a Kernel Oops!
- How to read, understand, analyze and debug a linux kernel panic
- Kernel Debugging
Reading The Call Trace
For example, I wanted to be able to understand the call trace of this Kernel Bug: bug-207773
The call trace section starts with:
[226832.533889] Call Trace: [226832.534377] <IRQ> [226832.534776] recent_entry_update+0x52/0xa0 [xt_recent] [226832.535690] recent_mt+0x167/0x328 [xt_recent] [226832.536488] ? set_match_v4+0x96/0xb0 [xt_set] [226832.537407] ipt_do_table+0x24f/0x610 [ip_tables] [226832.538277] ? ipt_do_table+0x33e/0x610 [ip_tables] [226832.539146] ? l4proto_manip_pkt+0xde/0x440 [nf_nat] [226832.540049] ? ip_route_input_rcu+0x40/0x280 [226832.540831] nf_hook_slow+0x40/0xb0 [226832.541477] ip_forward+0x424/0x450 [226832.542116] ? ip_defrag.cold+0x37/0x37 [226832.542814] ip_rcv+0x9c/0xb0
The way I did it was to run
gdb on the
vmlinux file in the root of the repository after build, and then load the symbol files of each module that is relevant:
Creating your patch
Here are some good guidelines on how to prepare and send your patch:
What did I work on?
The first issue I was interested in turned out to be an invalid bug: I found that out by investigating the script the user was testing and measuring how much time each part of the script took to find out the main culprit: bug-214851. But I learned a lot during this alone, mostly about how to build things quickly, where to look for modules, how to enable debugging for them, etc.
Next, I found bug-