CSE 422S: Studio 1

Welcome To Linux


"A crash reduces
your expensive computer
to a simple stone."

—Anonymous, GNU error message haiku page

Welcome to the first meeting of the Operating Systems Organization course! Today we're going to configure and compile a Linux kernel from source code. Even if you've done this kind of thing before, this studio will introduce the source code and resources that this class depends on, along with giving you additional experience working with the Raspberry Pi platform.

In this studio and the next studio, and throughout the semester, you will use a two-stage cross-compilation approach:

  1. In this studio, on other machines besides your Raspberry Pi you will
    The configuration options differ slightly from those in CSE 422S, so pay careful attention to the instructions in Exercise 5.
  2. In the next studio, you will download the kernel image you've built onto your Raspberry Pi, install it, and begin using it.

Having the code and the build process on other machines has some key advantages besides probably building faster than on your Pi. First, if you get locked out of your Pi, or at some point a (modified) kernel crashes (see the error message haiku above :-) most of the work you have done is safe in another location which allows you to start over efficiently by re-imaging your Pi to the default setup, fixing whatever bugs may have caused the crash, recompiling the kernel, installing it, and proceeding from there. Second, the Linux lab machines (e.g., those reached by issuing the qlogin command on shell.cec.wustl.edu) give you a place to create backup copies of any code before you modify it - or even to run version control software such as svn or git so that if a change you make goes awry you can quickly recover to a previous (working) version of your code.


Please complete the required exercises below, as well as any optional enrichment exercises that you wish to complete. We encourage you to please work in groups of 2 or 3 people on each studio (and the groups are allowed to change from studio to studio) though if you would prefer to complete any studio by yourself that is allowed.

As you work through these exercises, please record your answers, and when finished upload them along with the relevant source code to the appropriate spot on Canvas. If you work in a group with other people, only one of you should please upload the answers (and any other files requested) for the studio, and if you need to resubmit (e.g., if a studio were to be marked incomplete when we grade it) the same person who submitted the studio originally should please do that.

Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.


Required Exercises

  1. As the answer to the first exercise, list the names of the people who worked together on this studio.
  2. To save time, and to avoid potential freezing of your Raspberry Pi during long-running local compiles, we will be cross-compiling the kernel using dedicated Linux lab machines (e.g., those reached by issuing the qlogin command on shell.cec.wustl.edu).

    First, ssh into shell.cec.wustl.edu using your WUSTL Key id and password. On a Mac or Linux computer, you can just run ssh directly from within a terminal window. On newer versions of Windows, you can run ssh directly from the command prompt. If the command is not recognized, you will need to install and use an SSH client, such as Putty or WinSCP.

    Be careful! When you connect with ssh, you must specify your username, e.g. ssh username@shell.cec.wustl.edu or you risk getting locked out of the server. If you connect with the wrong username or password 5 times in 30 minutes, your IP address will be blacklisted for 4 weeks.

    To help prevent lockouts due to incorrect password attempts, you may want to log in using an SSH key instead of a password, as detailed on this page.

    Because kernel compiles are computationally intensive, you should not run them on the shell.cec.wustl.edu server, and instead you should run:

    qlogin

    which will let you log into a dedicated Linux host using your WUSTL Key id and password.

    You must remember the hostname of the machine you are now running on. To determine the hostname, execute the hostname command. The result should look something like:

    linuxlab{id}.engr.wustl.edu

    You must remember this hostname. It will store your linux kernel as well as other files you implement as part of this and future studios and labs.

    As the answer to this exercise, write down the hostname of the linuxlab machine you're using, as well as the CPU model name and number of (logical) CPUs. Note: the hostname can and likely will be different for all students in your group

    Determine the hostname of the machine you are now running on by issuing the hostname command. Additionally, execute the lscpu command to get information about the CPU(s) on the server. As the answer to this exercise, write down the hostname of the linuxlab machine you're using, as well as the CPU model name and number of (logical) CPUs.

  3. Now, exit out of the machine you were issued via qlogin by typing exit. You are now running on the shell.cec.wustl.edu machine. Now, use ssh to log back into the linuxlab machine you wrote down by issuing the ssh command:

    ssh linuxlab{id}.engr.wustl.edu

    replacing {id} with the specific ID found in your hostname.

    Now, you are just about ready to start downloading and compiling the Linux kernel. However, in order to ensure that your compilation does not interfere with others using the machine, you must first create a private directory on the local networked filesystem that is isolated from the traffic created by other users.

    To do so, issue the following commands:
    cd /project/scratch01/compile
    mkdir "your username"
    chmod 700 "your username"
    cd "your username"

    replacing "your username" with your actual username.

    These commands created a directory that you should use to store your linux kernel. Whenever you log into the machine via ssh, you must first change your directory to this location by typing:

    cd /project/scratch01/compile/"your username"

    As the answer to this exercise, please issue the command cd /project/scratch01/compile to navigate to the directory containing the one you just created.

    Then issue the command ls -ld "your username" and give the complete output from that command.
    Additionally, please write what the above chmod command accomplished, including what the octal value 700 denotes.
    (Hint: look at the manual page loaded from the command man 1 chmod.)

    Note that this directory only exists on the linuxlab machine that you are currently using. You must always ssh to this specific machine, as you did at the beggining of this step.

  4. Now it's time to download the Linux kernel source code. For a general-purpose project, you would go to kernel.org and download the Linux source from there. However, since we're using the Raspberry Pi we'll be starting with a version that is designed for our platform. The Raspberry Pi project maintains it's own distribution on GitHub, at https://github.com/raspberrypi. We'll be modifying the kernel based on the building guide that you can find here.

    From your specific /project/scratch01/compile/user-name/ directory, create a folder called linux_source in which to keep all of your source code and build files organized. Use the cd command to move into your new folder and issue the following commands, each of which may take a while to finish: the second of which may take over 20 minutes to complete:

    wget https://github.com/raspberrypi/linux/archive/raspberrypi-kernel_1.20210527-1.tar.gz

    WARNING: This step could take 20-30 minutes. Do not start it unless you have time to let it run to completion.

    tar -xzf raspberrypi-kernel_1.20210527-1.tar.gz

    This has the effect of downloading a specific version of the Raspberry Pi Linux distribution, which is the version that this course was developed with. Newer versions exist, which we won't use for this class but you can pursue on your own time if you'd like. Once the files finish unpacking you'll have a new directory, which we suggest renaming as something simpler with the mv command. We renamed ours linux, which is what the rest of these instructions will assume you've done as well.

    To save space, please delete the .tar.gz file once it is unpacked.

    Move into your new linux directory, and issue the command make kernelversion, which will tell you which Linux kernel version you've just checked out. As the answer to this exercise, give the output from that command.

    Additionally, open the Makefile in a text editor (e.g. emacs, vim, or nano) and look at the first several lines that define constants related to the kernel version. Write the name of this version of the kernel (as defined by the NAME constant).

    If you are using the Raspberry Pi 4 or 4B, you will need to modify the arm-pmu entry in the device tree for the Pi 4's BCM2711 board, which will allow the Linux kernel to load the hw perfevents driver. To do so, open the file arch/arm/boot/dts/bcm2711.dtsi, find the entry for the arm-pmu, then set the "compatible" line as follows:

    compatible = "arm,cortex-a72-pmu", "arm,cortex-a15-pmu", "arm,armv8-pmuv3";

  5. Now it's time to configure the Linux kernel. There are thousands of possible configuration options- many quite interesting and many quite dull. Rather than setting all these options manually, we'll create the default Raspberry Pi configuration and then tweak it. Issue the following two commands:

    module add arm-rpi (this adds the cross-compiler to your PATH variable)

    module add gcc-8.3.0 (this adds an updated C compiler to your PATH variable)

    Please also add the two commands above as individual lines at the end of the file ~/.bashrc to ensure they are executed the next time you log in.

    Now, issue the following command if you are using a Raspberry Pi 3B+:

    make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

    If you are using the Raspberry Pi 4 or 4B, instead use the following command:

    make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig

    To reiterate, if you were building a general purpose kernel, you wouldn't use the previous commands, which set up a default configuration for the Raspberry Pi.

    Next, we want to set custom configuration options. Issue the command:

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

    After a moment, you'll get a kernel configuration menu. As you can see, there are a lot of options. For now, we're just going to do three things.

    First, you'll add your own unique identifier to the kernel you build. Navigate to "General setup", then select "Local version." The local version string you specify here will be appended to the output of the uname command. If you applied the default Raspberry Pi configuration correctly, this currently should be set to:

    "-v7" if you are using a Raspberry Pi 3B+, or to

    "-v7l" if you are using a Raspberry Pi 4 or 4B.

    Go ahead and append your own unique identifier to that string, though recall that uname already gives you the kernel version number, the day and time the kernel was compiled, as well as other info. Warning: do not include any spaces in the local version string - this will break the build script when you run sudo make modules_install in the future.

    Next, we will change the kernel's preemption model. While still in "General setup," select "Preemption Model," and then select the "Preemptible Kernel (Low-Latency Desktop)" option.

    Now, enable the ARM Performance Monitor Unit driver. This will enable you to use the hardware counters provided by the Raspberry Pi. While still in "General setup," select "Kernel Performance Events and Counters." Make sure "Kernel performance events and counters" is enabled. Then, return to "General setup" and ensure that "Profiling support" is enabled. Exit "General setup" to return to the main configuration menu.

    First, we will choose the kernel's preemption model. Go into "Kernel Features", select "Preemption Model", and then select the "Preemptible Kernel (Low-Latency Desktop)" option.

    Next you'll add your own unique identifier to the kernel you build. Exit "Kernel Features" and navigate to "Local version" under "General setup". The local version string you specify here will be appended to the output of the uname command. If you applied the default Raspberry Pi configuration correctly, this currently should be set to "-v7". Go ahead and append your own unique identifier to that string, though recall that uname already gives you the kernel version number, the day and time the kernel was compiled, as well as other info.Warning: do not include any spaces in the local version string - this will break the build script when you run sudo make modules_install in the future.

    Choose an interesting sounding option and use the "H" key to bring up a short description. As the answer to this exercise, give the option's name, a short summary, and the option's symbol. Additionally, please describe why you think we have chosen the "Preemptible Kernel (Low-Latency Desktop)" preemption model. (Hint: look at the corresponding configuration option in the kernel code here.)

    Once you're done, exit the configurator and be sure to answer "Yes" when asked to save your changes.

  6. Finally, we're ready to start compiling the kernel. This will likely take several minutes; though it could take even longer if we were building the kernel locally on your Raspberry Pi instead of cross-compiling.

    To track how long the compilation step takes, issue the following command, which compiles the kernel, while writing start and end times to a file:

    date>>time.txt; make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs; date>>time.txt

    The compile may take a while (possibly an hour or more, depending on the machine you're compiling on). Once it's done, issue the following command:

    mkdir ../modules

    This will create a directory that the cross-compiler will use to store the kernel modules that it creates. You will later transfer these files to your Raspberry Pi. Then issue the command:

    make -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=../modules modules_install

    As the answer to this exercise please indicate the time it took to compile the kernel (by running cat time.txt and comparing the start and end times). Additionally, please describe (in a sentence or two) why we have to use the cross-compiler to compile the kernel on the linuxlab server.

    Note the time again, and as the answer to this exercise please indicate approximately how long it took to complete it.

    Congratulations! You've just compiled an operating system from source!

Things to Turn In:

For this studio, please turn in the following:


Page updated Thursday August 31, 2023, by James Orr.