Xv6

Overview

Xv6 is an instructional OS consisting of a stripped down version of unix. To get ready to work within xv6, please start reading the xv6 book as well as the other xv6 resources listed below.

Resources

Getting Started (SSH)

Since the lab sessions will be online, you will need an SSH client to connect to sledge or a VM. If you are using Linux or macOS, you should already have a ssh client installed by default. If you are Windows 10, the best option would be the Windows Subsystem for Linux (WSL). You can follow the installation guide and the tutorial. I would also recommend the Windows Terminal.

If you are using an earlier version of Windows, you can use PuTTY.

Getting Started (sledge)

In sledge, most software is pre-installed, so you only need to download xv6.

[sledge] $ cd ~
[sledge] $ git clone https://github.com/mit-pdos/xv6-public.git xv6
...
[sledge] $ cd xv6
[sledge] $ make
[sledge] $ echo "add-auto-load-safe-path $HOME/xv6/.gdbinit" > ~/.gdbinit

Getting Started (VM)

If you are using macOS, an earlier version of Windows, or your Linux distribution has trouble compiling xv6, you can use a Linux virtual machine (VM). To save the time of installing Linux in the VM, you can use Vagrant.

  1. Download and install Virtualbox/Vagrant/SSH client

Note: Ubuntu users may want to use the following commands to install Virtualbox and Vagrant

[host] $ sudo apt-get install virtualbox
[host] $ sudo apt-get install vagrant
  1. Add guest OS and run the VM
# download a 64-bit VM
[host] $ vagrant box add ubuntu/xenial64
==> box: Loading metadata for box 'ubuntu/xenial64'
    box: URL: https://atlas.hashicorp.com/ubuntu/xenial64
==> box: Adding box 'ubuntu/xenial64' (v20170331.0.0) for provider: virtualbox
    box: Downloading: https://atlas.hashicorp.com/ubuntu/boxes/xenial64/versions/20170331.0.0/providers/virtualbox.box
==> box: Successfully added box 'ubuntu/xenial64' (v20170331.0.0) for 'virtualbox'!

# move to your working directory
[host] $ mkdir cs153
[host] $ cd cs153

# initialize the VM
[host] $ vagrant init ubuntu/xenial64
A `Vagrantfile` has been placed in this directory. You are now
ready to `vagrant up` your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
`vagrantup.com` for more information on using Vagrant.

# launch!
[host] $ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'ubuntu/xenial64'...
...

[host] $ vagrant ssh
Welcome to Ubuntu 16.04.2 LTS (GNU/Linux 4.4.0-71-generic x86_64)
...
ubuntu@ubuntu-xenial:~$
  1. Once you have the VM up and running, let’s initialize your VM for this course, following the same steps as in WSL section.

Getting Started (WSL)

If you are using WSL or Linux (VM), install a customized QEMU (for better debugging support) and xv6.

# in the VM, install toolchain
[wsl|vm] $ sudo apt-get update
[wsl|vm] $ sudo apt-get install -y build-essential gdb git gcc-multilib

# install the patched QEMU
#
[wsl|vm] $ cd ~
[wsl|vm] $ git clone https://github.com/mit-pdos/6.828-qemu.git qemu
[wsl|vm] $ sudo apt-get install -y libsdl1.2-dev libtool-bin libglib2.0-dev libz-dev libpixman-1-dev
[wsl|vm] $ cd qemu
[wsl|vm] $ ./configure --disable-kvm --disable-werror --target-list="i386-softmmu x86_64-softmmu"
[wsl|vm] $ make
[wsl|vm] $ sudo make install

# finally it's time for setting up xv6
#
[wsl|vm] $ cd ~
[wsl|vm] $ git clone https://github.com/mit-pdos/xv6-public.git xv6
...
[wsl|vm] $ cd xv6
[wsl|vm] $ make

# NOTE: allow local gdbinit to be loaded (only done once)
#
[wsl|vm] $ echo "add-auto-load-safe-path $HOME/xv6/.gdbinit" > ~/.gdbinit

Debugging

Get familiar with development environment. Open two terminal windows (and enter the VM if not on sledge). Alternatively, you can also try screen (shortcut) or byobu (not on sledge).

# in window one
[wsl|vm|sledge] $ cd ~/xv6
[wsl|vm|sledge] $ make qemu-nox-gdb

# this starts up QEMU, but QEMU stops just before the processor
# executes the first instruction and waits for a debugging
# connection from GDB.

# in window two
#
# NOTE: -q removes the annoying init message
#
[wsl|vm|sledge] $ cd xv6
[wsl|vm|sledge] $ gdb -q
+ target remote localhost:26000
warning: A handler for the OS ABI "GNU/Linux" is not built into this configuration
of GDB.  Attempting to continue with the default i8086 settings.

The target architecture is assumed to be i8086
[f000:fff0]    0xffff0:     ljmp   $0xf000,$0xe05b
0x0000fff0 in ?? ()
+ symbol-file kernel

# to terminate, for now, in window 2
[wsl|vm] $ killall qemu-system-i386

# for sledge
[sledge] kill $(pgrep qemu)

Read more on how to use gdb with QEMU/JOS.

Tips:

  • You can use cprintf() to print debugging information to the console. For example, you can check whether values of certain variables match your expectations.

  • When error happens, xv6 will output error messages like follows:

    lapicid: 0: panic: trap
    80483231 80d48a34 80033423 0 0 0 0 0 0 0
    

    in this message:

    • 0 is the number of the CPU that was running when the panic occurred.
    • trap is the message that was passed to the panic function. Usually, the xv6 code is written so that there is only one call to panic with a particular message, so this will precisely identify where the panic occurred.
    • 8048323, 80d48a34, etc. are the hexadecimal addresses of the code that was running when the panic() was called. You can look up these addresses in kernel.asm, which contains the full assembly of the xv6 kernel, interleaved with its machine code, the addresses of each instruction, and the corresponding C code.