This lab will let you dive into and become familiar with xv6 and system calls.
Install QEMU and gcc for RISC-V following the directions on the tools page.
Clone the base xv6 repository and set up a branch for this lab by following the directions on the git page.
Now we can build and boot xv6 by running the following commands:
$ make
riscv64-unknown-elf-gcc -c -o kernel/entry.o kernel/entry.S
...
$ make qemu
gcc -Werror -Wall -I. -o mkfs/mkfs mkfs/mkfs.c
...
xv6 kernel is booting
hart 1 starting
hart 2 starting
init: starting sh
$
If you type ls at the prompt, you should see output similar to the following:
$ ls
. 1 1 1024
.. 1 1 1024
README 2 2 2226
xargstest.sh 2 3 93
lazytests 2 4 27672
cat 2 5 23496
echo 2 6 22352
forktest 2 7 13104
grep 2 8 26664
init 2 9 23160
kill 2 10 22280
These are the programs/files that mkfs
includes in the initial
file system. You just ran one of them: ls
.
To quit QEMU, type Ctrl-a x, which means:
Implement the Unix program sleep
for xv6. This program pauses for a user-specified number of ticks before exiting. A tick is a notion of time defined by the xv6 kernel, namely the time between two interrupts from the timer chip. Your implementation should be placed in the file user/sleep.c
.
Some hints:
user/
((e.g., user/echo.c
, user/grep.c
, and user/rm.c
)) to see how you can obtain the command-line arguments passed to a program.atoi
(see user/ulib.c
).sleep
, which is already implemented by xv6.kernel/sysproc.c
for the xv6 kernel code that implements the sleep
syscall (i.e., sys_sleep
), user/user.h
for the C definition of sleep
callable from a user program, and user/usys.S
for the assembler code that jumps into the kernel.exit()
in order to exit your program.UPROGS
in Makefile
; once you’ve done that, make qemu will compile your program and you’ll be able to run it from the xv6 shell.Run the program from the xv6 shell:
$ make qemu
...
init: starting sh
$ sleep 10
(nothing happens for a little while)
$
Your solution is correct if your program pauses when run as shown above. However, you should test it using the grading script to make sure it operates correctly. You can see the exact tests that are run by inspecting the grading script code.
Implement a program countsys
, which prints the total number of syscalls invoked thus far. This program will rely on the introduction of a new syscall, which may also be named countsys
, to return the information tracked in the kernel to the user-space program. You must implement your syscall in the file kernel/sysproc.c and make neccesary modifications to kernel/syscall.c and kernel/syscall.h in order to make it work. You must also implement the user space program for countsys
in the file user/countsys.c (similar to what you did for the sleep
program).
Some hints:
countsys
does not require any arguments and it should print an error message if invalid arguments are presented.extern
across multiple files.sleep
program. Add countsys callable definition in user/user.h. To generate assembler code that jumps into the kernel for countsys, look at user/usys.pl.\n
at the end of your printf
call, as the number of characters correlates with the number of syscalls made.Run the program from the xv6 shell:
$ make qemu
...
init: starting sh
$ countsys
43
$
You can run python3 grade_lab_util.py to test your solutions with the grading script. The same grading script is used by the Gradescope autograding process.
When you are ready to submit your work to Gradescope to be automatically graded, you can run make gradescope which generates a submission.zip
file that can be uploaded to Gradescope. This file should only contain the files that were changed as a result of completing the lab assignment. If this command does not work for some reason, you can use make gradescope-all instead, which will include all possible files that could have been modified.
If you are using the remote VCM infrastructure, you can use scp
or rsync
to download the zip file.