CS 134 Homework Assignment #1

The purpose of this assignment is to familiarize you with OS/161, System/161 and the build environment you'll be using. Mostly you'll be reading code. It is intended as an easy assignment, but you should take care to do it well, and if possible go beyond what it asks of you. Time invested in understanding OS/161 now will pay off later.

Overview

This assignment has three parts: a somewhat lengthy preliminary, a written component, and a coding component. You may wish to skip ahead to those two components to get a feel for the work you have to do.

Due Dates

The written component is due at the beginning of class on Tuesday, September 18th, 2012. The coding component is due at 11:59 PM on the same day, Tuesday, September 18th.

Preliminaries

Read the AssignmentsSetup Wiki page; you must have your path correctly set before you undertake each CS 134 assignment. If you haven't done so already, put the appropriate line(s) in your .bash_login or .zlogin. Do it now!

Checking Out the Repository for Your Group

The URL for your pair's CS 134 repository is

https://svn.cs.hmc.edu/cs134/fall12/ours/<group>

where <group> is the name of your group. Your group name is formed by joining together each of your Knuth usernames, in alphabetical order and lower case, with a hypen. Thus, if Mary Jones (mjones) and John Smith (jsmith) were working together, their group name would be jsmith-mjones.

When you work with someone for the first time, your first step is to check out a working copy of your shared directory. You each only have to do this step once (unless you decide to completely delete your working copy and check out a fresh copy, or you choose to work on two unrelated machines, such as your dorm computer and one of the lab machines).

Have each partner log in to their own account and check out their own working copy of your shared repository by running the following commands:

mkdir -p ~/courses/cs134
chmod go-rwx ~/courses/cs134
cd ~/courses/cs134
svn checkout https://svn.cs.hmc.edu/cs134/fall12/ours/<group>

The Subversion server requires a username and password. These are simply your Knuth username and password.

Copying the Assignment to Your Repository and Working Copies

You now have a shared directory space, but you don't yet have any of the files for the assignment—you need to copy them from my distribution area in the CS 134 repository.

To make your own copy of the assignment code, one of you should run:

cd ~/courses/cs134/<group>
svn copy https://svn.cs.hmc.edu/cs134/fall12/given/hw1 hw1
svn commit -m "Copied over Assignment 1 files"

(The -m option to svn commit provides a quick way to provide a log message for the commit.)

The other person should then run the following commands for their working copy:

cd ~/courses/cs134/<group>
svn update

You might want to try running svn update before the other person commits just to see what happens, which should be nothing. You won't ever see changes until they have been committed to the repository.

Building the OS/161 Userspace Tools

Now run the following commands

cd ~/courses/cs134/<group>/hw1
./setup

(svn checkout may wrongly guess the username; just press return and it'll ask.)

If the above command is done in less than fifteen seconds, check over the compilation output for errors. If something went wrong at this stage, something is up with the fundamentals. Perhaps you didn't set your path?

Running ./setup can take several minutes depending on the speed of the machine you are using. Remember that you can skip ahead to some of the reading parts of the assignment while you are waiting for parts to compile.

When ./setup finishes, it will have built all of the user-level commands (such as /sbin/reboot) and libraries for OS/161, but not the kernel itself. You can check that it has compiled one of these files by running:

file root/sbin/reboot

which should print something along the lines of

root/sbin/reboot: ELF 32-bit MSB mips-1 executable, MIPS R3000_BE,
version 1, statically linked, not stripped

Okay, now you're ready to work…

Building the Kernel

The OS/161 kernel uses a fairly complex but powerful build system. It uses a configuration file to specify which parts of the kernel need to be built, and provides separate build areas for each configuration.

Our first step in building a kernel is thus to configure the build using a configuration file. Make sure your current directory is ~/cs134/<group>/hw1, and then run

cd src/kern/conf
./config INTRO

Now that the kernel is configured, we can build it. Type

cd ../compile/INTRO
make install

Once it's built, change directory to your virtual root directory and test the kernel, as follows

cd ~/cs134/<group>/hw1/root
sys161 kernel

You can't do much with the kernel at this point. Two things you can do are initiate a kernel panic with the panic command, and run a user level program that performs the “reboot” system call by typing p /sbin/reboot. Try both of these now.

You can also use gdb. Open another terminal window, and ensure both are in the directory ~/cs134/<group>/hw1/root. Then proceed as follows:

First Window           Second Window
Run the command:
sys161 -w kernel Run the command:
os161-gdb kernel
The system should pause with a message that it is waiting for the debugger.
Once gdb has started, give the following commands to gdb:
connect
break panic
continue
OS161 should now start up. Enter the command:
panic
Gdb should have now stopped at the breakpoinit you set for panic. Type the following commands:
backtrace
continue
Execution should resume, and the kerenel should exit with its panic message and shut down the machine.
Quit gdb.

Code Reading

In this course, you may be getting your first taste of understanding and carefully modifying a large body of code that you did not write yourself. It is imperative that you take the time to read through the important parts of the code to get an understanding of the overall structure of the code, and what each part of the code does. The code-reading component of this assignment aims to guide you through the code base to help you comprehend its contents, identify what functionality is implemented where, and be able to make intelligent decisions on how to modify the code base to achieve the goals of this and later assignments. You don't need to understand every line of code, but you should have a rough idea of what each file does.

The Top-Level Directory

The src directory is the top-level directory of OS/161. It contains a few files, along with subdirectories that hold distinct parts of OS/161. The files are
Makefile
Used to build the OS/161 base system, including all the provided utilities. It does not build the operating system kernel.
configure
A configuration script, similar to the configuration scripts used in many open source programs (although it is not one of the impenetrable scripts generated by GNU autoconf). You shouldn't need to understand or tamper with it. It is run by our setup program.
defs.mk
Definitions read in by the Makefile, and generated by the configure program.
defs.mk.sample
A sample defs.mk file in case something goes wrong with configure. The idea is that to allow developers to fix defs.mk using the comments in this file. For us, configure is run by our setup script and should never fail.

In addition to these files, the src directory contains the following subdirectories:

bin
Contains the source code for the user-level utilities available on OS/161. They are a subset of the typical unix /bin tools; for example, cat, cp, ls.
include
Contains include files used to build user-level programs on OS/161; they are not the kernel include files. Among other things, these files contain appropriate definitions for using the C library available on OS/161.
kern
Contains the sources to the OS/161 kernel itself. We will cover this code in more detail below.
lib
Contains the user-level library code for libc, the C library.
sbin
Contains the source code for the user-level system management utilities found in /sbin on a UNIX machine (e.g. halt, reboot, etc.).
testbin
these are pieces of test code. They are most relevant to the course given at Harvard, but are included here for your perusal and potential use.

Your focus during this code walkthrough should be on the kernel sources. You won't need a detailed understanding of the utilities in bin and sbin, but you should have a general idea of how they work and where things are is useful. The same is true of the lib and include directories.

The kern Subdirectory

This directory and its subdirectories are where most (if not all) of the action takes place. The only plain file in this directory is a Makefile, which only installs various header files. It does not actually build anything.

We strongly recommend that you set up and use CScope to explore the kernel; it will save you tons of time.

We will now examine the various subdirectories in detail. (The parenthetical comments provide hints on which directories are relvant for which written questions. However, they are only hints; sometimes the answer is elsewhere.)

kern/arch
This directory contains architecture-dependent code, which means code that is dependent on the architecture OS/161 runs on. Different machine architectures have their own specific architecture-dependent directory. Currently, there is only one supported architecture, mips.
kern/arch/mips/conf/conf.arch (W1)
Tells the kernel config script where to find the machine-specific, low-level functions it needs (see mips/mips).
kern/arch/mips/conf/Makefile.mips
Kernel Makefile; copied when you run the config script to configure a kernel.
kern/arch/mips/include (W2-W6,W8)
Contains include files for the machine-specific constants and functions.
kern/arch/mips/mips (W7,W9)
Contains the low-level machine-dependent functions.
kern/asst1
This directory contains framework code for one of the assignments at Harvard, not this assignment. You can safely ignore it.
kern/compile
Where you built your kernel. Remember…?
kern/conf (W10-W16)
Where you configured your kernel. Hopefully you remember that too…
kern/include
Contains include files that the kernel needs.
kern/include/kern (W17-W19)
Contains include files that the kernel and user-level code needs.
kern/main (W20-W21)
Contains code to initialize the kernel. Guess which function you'll find defined here…
kern/thread (W22-W23)
Contains code implementing threads. Threads are the fundamental abstraction on which the kernel is built.
kern/lib (W24)
Contains library routines used throughout the kernel; for example, managing sleep queues, run queues, kmalloc, and so forth.
kern/userprog
Will contain code to create and manage user-level processes. As it stands now, OS/161 runs only kernel threads; there is essentially no support for user-level code.
kern/vm
Also fairly vacant. Virtual memory would be mostly implemented in here.
kern/fs/vfs (W25-W28)
Contains code implementing a file-system abstraction layer (vfs stands for “Virtual File System”). It establishes a framework into which you can add new file systems easily. You will want to review vfs.h and vnode.h before looking at this directory.
kern/fs/sfs
Contains code implementing the simple file system that OS/161 contains by default. You don't need to worry too much about this directory for now.
kern/dev
Where all the low-level device-management code resides. You can safely ignore most of this directory.

Written Component

Work together as a pair to find the answers to the questions below. You are not required to share a single machine pair-programming style, but that may be the easiest way to work on this part. You must make sure that you both know how each answer was found, have read through the relevant source file, and know why your answer is “the right answer”. Legibly write or print your pair's answers on letter-sized paper and bring them to Tuesday's class. You do not need to use the submission system for your answers to this section. In class I may ask you individually about the answers you gave as a pair, or ask you closely related questions whose answers you should know from answering the questions below.
  1. The kernel for this assignment is configured to use a particular VM (virtual memory) system. What is this VM system called?
  2. Which register number is used for the stack pointer (sp) in OS/161?
  3. What bus/busses does OS/161 support?
  4. What is the difference between splhigh and spl0?
  5. Why do we use typedefs like u_int32_t instead of simply saying int?
  6. What must be the first thing in the process-control block?
  7. What does splx return?
  8. What is the highest interrupt level?
  9. What function is called when user-level code generates a fatal fault?
  10. How frequently are “hardclock” interrupts generated?
  11. What functions comprise the standard interface to a VFS device?
  12. How many characters are allowed in an SFS volume name?
  13. What is the standard interface to a file system (i.e., what functions must you implement to implement a new file system)?
  14. What function puts a thread to sleep?
  15. How large are OS/161 pids?
  16. What operations can you perform on a vnode?
  17. What is the maximum path length in OS/161?
  18. What is the system call number for a reboot?
  19. Where is STDIN_FILENO defined?
  20. What does kmain() do?
  21. Is it okay to initialize the thread system before the scheduler? Why or why not?
  22. What is a zombie?
  23. How large is the initial run queue?
  24. Can an array represented by a struct array be resized?
  25. What does a device name in OS/161 look like?
  26. What does a raw device name in OS/161 look like?
  27. What lock protects the vnode reference count?
  28. What device types are currently supported?
Remember to bring your answers with you to class on Tuesday.

Coding Component

In this portion of the assignment, we make a small modification to the OS/161 and debug it.

  1. Find the place in the code that prints Put-your-group-name-here and edit it to print your group's name.
  2. Recompile and test your kernel.
  3. Submit your code by running svn commit.
  4. In src/kern/main there is an extra file, hello.c, which is currently not compiled or used. It defines a function complex_hello that is intended to print “Hello World”. (The code in this file is more complex than strictly necessary, but you should not replace it with a simple call to kprintf.)
  5. Edit one of the kernel source files to add a call to complex_hello so that “Hello World” will be printed once, just before the prompt appears.
  6. Edit src/kern/conf/conf.kern appropriately to include hello.c.
  7. Since you've changed a kernel configuration file, rerun the configure program in kern/conf (using the same steps you used on page 2).
  8. Change directory into src/kern/compile/INTRO and rebuild the kernel (again, using the same steps as you used on page 2).
  9. Run the kernel. It will panic.
  10. Use gdb to find the bug.
  11. Fix the bug.
  12. Submit your code by running svn commit.