- Obtain a copy of a VM or another Linux environment (most likely not OS X, see below) with:
- a working C and C++ compiler
- a recent copy of qemu installed (configured to support full 32-bit x86 emulation).
Download and get xv6 to boot in an emulated machine. For how to do this, see the instructions below. Run it and make sure you can run some simple commands in a shell in the emulated machine.
Add a new system call
writecount()that takes no arguments and returns the number of times the
writesystem call has been called across all processes. See below for hints about how to do this.
We do not care how your
writecount()system call counts calls to
writethat fail, such as from having invalid arguments. We also don’t care how it treats simulataneous calls to write() and/or writecount().
Write a program that uses and tests this new system call. See below for hints on how to do this.
make submitto create a
.tar.gzarchive and upload it to the submission site.
Getting xv6 running
Download our version of xv6 using git:
git clone https://github.com/uva-reiss-cs4414/xv6.git
In the newly created
Boot xv6 in an emulator using one of the following methods:
To boot the OS in an emulator with a graphical user interface, run
To boot the OS in an emulator without a graphical user interface, run
make qemu-nox. (
noxprobably standards for “no X”; X is short for the X windowing system, the primary graphics system on Unix-like operating systems.)
Adding the system call
For this task, you might want to read
how system call dispatching is implemented in
syscall.h, and how the handlers for individual system calls are implemented in
Basic steps for adding system calls:
sys_writecountfunction based on an existing simple system call function like
sys_uptime. (For this assignment, you do not need to (but are allowed to) use a spinlock and
uptimedoes since we do not care how your code works with multiple processors.)
Add a system call number for your new system call to
sys_writecountto the table in
sys_write. You can use a command like
grep sys_write *.cto find out where it is.
user.hto create a system call wrapper function that invokes your system call from a normal user program.
Testing your system call
echo.cas a template, create a new program to run your writecount system call and print the results.
Makefileby adding your program to
UPROGS, similar to how
echois included on this list.
make qemuto boot the OS with your new program included.
If your test program crashes after finishing, you may have forgotten to
exit()at the end. (Returning from
main()will not work.)
You could run other programs that call
write()(e.g. by outputting anything to the console) and/or have your test program make writes (using the
write()system call wrapping function directly or by taking advantage of
printf()calling write) to verify that the count make sense.
- The built-in xv6
printf()implementation, whose source code is in
printf.c, is implemented by calling
write(), but it often calls write more than one time per call to
Locks not required
sys_uptimeuses a spinlock, which it uses to handle the case where xv6 is running on multiple processors or when the system call is interrupted by a timer interrupt. For this assignment, we do not care if you handle this problem. (We will ensure only one process is calling
write()at a time when testing.)
An implementation of
writecountthat correctly handled multiple concurrent calls to
writecount()would probably use a spinlock around accesses to the counter (from both
In the kernel, you can use
cprintf()to output messages to the console. This is my primary mechanism for debugging. Outside the kernel you can use
printf()to output debug messages.
You can run xv6 under debugger
gdbusing the instructions below.
The xv6 kernel contains many situations where it asserts that some condition that should always be true is true, and if not, it deliberately crashes the system in what is called a panic. For example,
trap.ccontains code that panics when an unexpected type of exception occurs while code is running in kernel mode, such as the equivalent of a segmentation fault in kernel code. When this happens, xv6 prints out a message like the following:
lapicid 0: panic: trap 80483231 80d48a34 80033423 0 0 0 0 0 0 0
in this message:
0is the number of the CPU that was running when the panic occured. Since we always run xv6 in single-core mode, this will generally be 0.
trapis the message that was passed to the panic function. Usually, the
xv6code is written so that there is only one call to panic with a particular message, so this will precisely identify where the panic occured.
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.
xv6 book: note on terminology
CS 3330 and the xv6 book and source code use slightly different terminology related to exceptions:
|CS 3330 Term||most common xv6 term||description|
|exception||trap||any event in which the processor transfers control from whatever program was running to the OS (to the “kernel”) at a location chosen by the OS|
|fault||exception||a program performs an illegal action, causing control to be transferred to the OS to decide what to do|
|interrupt||interrupt||an event external to the program, such as a timer or an input/output device needs the OS’s attention|
|trap||(specific kind) trap||an exception deliberately triggered by an instruction; on x86 this is via the
a note on GDB
- It is possible to use GDB with xv6. To do this instead of running
make qemu-nox, run
make qemu-nox-gdbrespectively. Then, in another window, run
gdbfrom the xv6 directory, and then run the command
source .gdbinitwithin GDB. Then, within GDB, you can set breakpoints with
break function_name(and various similar commands) and start execution of the OS with
a note on OS X
Because xv6 expects ELF format binaries, xv6 will require a cross-compiler on OS X. We recommend (and will support) using a Linux environment instead (such as through a VM) instead, but if you can get it working natively on OS X using a cross-compiler, that’s great (and your fellow students would probably appreciate the information).
This assignment is based loosely on Arpaci-Dusseau’s initial-xv6 assignment.