CS 528 - Linux Kernel Development

William (BJ) Blair



Downloaded base kernel from git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git , following chapter 2 of the the textbook


Downloaded ubuntu base kernel using this guide - was getting build errors from yesterdays source and this seemed easier. Build is taking forever! paused it partway through (saved virtual machine state)


Build finished - had to install libssl-dev, other than that the above guide seemed to work fine. Trying Torvald's base kernel again to see if build issues were just dependencies... and it worked! The build was much faster this time than the ubuntu kernel. Kernel build was 4.19-rc1, installed with

make defconfig 
make -j2
make -j2 modules 
make modules install 
make install 
(as root). To verify I was booting the new kernel, I went into 'Advance options for Ubuntu' in the grub menu.


Semi-following chapter 5, trying to implement the author's example system call. Updated information found here: link

Added the following to syscall_64.tbl in arch/x86/entry/syscalls/ after entry 334 rseq (the last one before _x32_compats):

335	common	bjfunc	__x64_sys_bjcall
and for the actual code in kernel/sys.c:

#include <asm/page.h>
 * BJ added dummy sys call test
 * returns the size of the per-process kernel stack
    printk(KERN_INFO "Someone called bjcall!\n");
    printk(KERN_INFO "Thread size is: %ld\n", THREAD_SIZE);
    return THREAD_SIZE;
Then recompile the kernel like earlier, reboot. The code to test the call:

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>

/* The system call entry number added to the table */
#define SYS_bjfunc 335

int main(int argc, char *argv[])
    /* syscall(long number, ...) */
    int thread_size = syscall(SYS_bjfunc);

    printf("Thread size: %d\n", thread_size);

    return 0;
and compile with gcc test_syscall.c -o test_syscall. Then run, and for me returns "Thread size is: 16384". Then, to view the `printk` messages run `dmesg` and there it is:

[  504.023916] Someone called bjcall!
[  504.023923] Thread size is: 16384
Alternatively, (and I think this is cooler) you can make the system call using inline assembly:

#include <stdio.h>

#define SYS_bjfunc 335

int main(int argc, char *argv[])
    /* A system call stores the return value in eax according
     * to the book */
    register int call_return asm("eax");
    printf("Call return before: %d\n", call_return);
    /* Call the system call via assembly,
     * howto from here:
     * https://jamesfisher.com/2018/02/19/how-to-syscall-in-c.html */
    register int syscall_no asm("rax") = SYS_bjfunc;

    /* Call return is already linked to $eax so it was
     * updated on the above assembly syscall */
    printf("Thread size: %d\n", call_return);
    return 0;


Decided my class project would be exploring the Rasberry PI's kernel; and perhaps to build some sort of kernel-userspace system for GPIO access.

Followed guide for cross-compiling the Raspberry PI kernel here: link


# Get the required build tools
git clone https://github.com/raspberrypi/tools ~/tools

# Add the tools to PATH
source ~/.bashrc

# Get the kernel source
git clone --depth=1 https://github.com/raspberrypi/linux

# make the config for my raspi version (B+ v1.2)
cd linux
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcmrpi_defconfig

# build the kernel, with 2 processes
make -j2 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs


Continued with above mentioned kernel build tutorial - now need to install the modules and copy files over to the PI.

Since I'm running linux in a VM and I don't have guest additions installed (was getting guest additions build errors - maybe it's because I'm on the same VM that's running the custom kernel?), I had to deviate from the guide.

Instead, I created two directories (ext4 and fat32) in my home directory and installed to there. Then I'll copy from there onto the raspberry pi through scp and a live linux image (hopefully...)


Trying to install Raspbian on the RPI's SD card from windows, for some reason Win32DiskImager which is reccomended from the RPI website isn't working, going to try formatting the SD card clean first...

Was able to install Raspbian through linux using `dd`. Copying kernel build to raspberry pi:

Created /boot/config.txt backup
Copied /ext4 (lib) files to rasbperry pi:
    scp -r blairw@gaben.cs.sunyit.edu:~/rpi_kernel/ext4/* ./
(From root directory (/))


Finished copying built kernel files to the pi:

Created /boot/kernel.img backup
cd /boot
sudo scp blairw@gaben.cs.sunyit.edu:~/rpi_build/fat32/kernel.img ./bj-kernel.img
sudo scp blairw@gaben.cs.sunyit.edu:~/rpi_build/fat32/*.dtb ./
sudo scp blairw@gaben.cs.sunyit.edu:~/rpi_build/fat32/overlays/*.dtb* ./overlays
sudo scp blairw@gaben.cs.sunyit.edu:~/rpi_build/fat32/overlays/README ./overlays

add `kernel=bj-kernel.img` to end of /boot/config.txt file on RPI

Now you can verify the new kernel is booting by comparing the output of `uname -a`:

Managing GPIO through sysfs:

Pins are numbered based on BCM (their pin number in the diagrams, as opposed to their physical number)

cd /sys/class/gpio

# Tell the system which pin we want to work with
echo 21 > export

# Tell the system we're going to output to this pin
echo out > gpio21/direction

# Turn the pin on
echo 1 > gpio21/value

# Turn the pin off
echo 0 > gpio21/value

# Tell the system we're done using this pin
echo 21 > unexport

Info was from this video: https://www.youtube.com/watch?v=Si1R2gaqE64


Got a system call compiled and running for ARM on the raspberry pi. Some info/inspiration taken from here But it seemed to be a bit outdated (I didn't have a `calls.S` file).

However, thanks to earlier implementing the system call earlier/above, I found a file `syscall.tbl` in `linux/arch/arm/tools/` and added my syscall name and shortcut like I did earlier.

398 common  bj_helloworld        sys_bj_helloworld

I added the code to `linux/arch/arm/kernel/sys_arm.c`.

asmlinkage long sys_bj_helloworld(void)
    printk("Somebody called bj helloworld!\n");

    return 0;


Found a way to emulate the raspberry pi using QEMU; see project page for details

Moved the system calls to their own file, `bj_gpio.c`, and added 3 system calls: bj_initpin, bj_setpin, and bj_freepin. See the project page for more details.


Hello world device driver for Raspberry PI; See project page for details


Integrated GPIO pin setting to the device driver for project