Compile Raspberry Pi (2/3) kernel from source with BFQ

Today we are going to learn how to compile the Raspberry Pi (2/3 only) kernel from source and then patch the kernel with BFQ IO scheduler support. As of today (8/18/16) the latest kernel is 4.4.17. I am using the latest (Jessie) Raspbian release.

So what is BFQ? More about BFQ

BFQ is a proportional-share storage-I/O scheduler that also supports hierarchical scheduling with a cgroups interface.

BFQ provides low latency for interactive and soft real-time applications, high throughput, and strong fairness guarantees. The code is fairly mature and it has been around for awhile. I especially prefer BFQ on mobile and embedded devices. Let’s dive in. (Note that this guide only covers native compiling, if you are cross-compiling from another arch, check out this article for more information.)


We’ll need to grab the latest kernel sources from the Raspberry Pi github:

git clone --depth=1 https://github.com/raspberrypi/linux

This will clone only the latest source from the default branch (which is currently 4.4.y)

We’ll need to install bc also.

sudo apt-get install bc

Now that we have our sources and dependencies met, we’ll want to grab our BFQ patches and apply them to our source:

cd linux/
VERSION=4.4.0-v7r11
wget -nd --no-parent --level 1 -r -R "*.html*" --reject $VERSION \
    http://algogroup.unimore.it/people/paolo/disk_sched/patches/$VERSION
git am *BFQ*.patch

You will see the patches applied, and if successful, no errors. Next we’ll need to modify the kernel configuration to enable BFQ and set it as the default IO scheduler.

KERNEL=kernel7
make bcm2709_defconfig

To modify the kernel configuration, there’s a number of options available. You can simply use your favorite text editor to edit the .config file, or you can use a tool like ‘make menuconfig’ (ncurses.) I’ll be using ‘make menuconfig’ which requires that libncurses5-dev is installed.

sudo apt-get install libncurses5-dev

and then I’ll run:

make menuconfig

menuconfig

We’ll need to navigate to ‘Enable the block layer’ and hit enter:

block layer config

From there, we’ll go down to ‘IO Schedulers’ and hit enter again:

IO Scheduler config

Here, we’ll highlight ‘BFQ I/O scheduler’ and hit space *twice*. We want an asterisk ‘<*>’ next to the BFQ option, and not an ‘<M>’. This means we are compiling BFQ into the kernel, instead of a module to be loaded separately.

Next we’ll choose the ‘Default I/O scheduler’ option and hit enter:

io_option

This will set BFQ as our default I/O scheduler. After choosing BFQ, we can hit ‘ESC’ to back up until we get back to the main menu from the first picture. We’re going to modify the local version to append to the kernel release. I do this on Raspberry Pis to prevent us from overwriting the original kernel modules in /lib.

We’ll choose ‘General setup’ and hit enter:

make menuconfig

Then we’ll select ‘Local version – append to kernel release’ and hit enter:

configure local version

You can set this to whatever you like, here’s what I did:

local version name

We can now use our arrow keys to scroll over to Save (we’ll leave the filename as .config) and then we’ll scroll over to exit (you might have to hit exit twice.) We’ve successfully modified our kernel configuration.

We now have our kernel sources patched and our configuration updated for BFQ. We’ll now compile the kernel (Note: Doing this on the Raspberry Pi will take a LONG time.)

make -j4 zImage modules dtbs

Once that is done, we’ll need to copy over our freshly compiled files to /boot/ and install our modules.

sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/

And finally, we’ll create our kernel image and copy it to /boot. To be safe, I like to backup the original kernel image first:

sudo cp /boot/kernel7.img /boot/kernel7.bak

Then make the kernel image:

sudo scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img

This will generate the kernel image and copy it to /boot/ with the filename kernel7.img and replace the old kernel. You can change ‘$KERNEL.img’ to anything you’d like, for example ‘movr0.img’ to avoid overwriting the original kernel and add a simple line to your /boot/config.txt

kernel=movr0.img

There’s one more thing we need to fix before rebooting, we’ll need to modify /boot/cmdline.txt by changing:

elevator=deadline

to

elevator=bfq

and that’s it! You’re done, enjoy!

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *