In this assignment, you will learn how to:
getcount
system call (15 points)The first system call you'll add is one we'll name getcount
, which, when
passed a valid system call number (listed in the file "syscall.h
") as an
argument, will return the number of times the referenced system call was invoked
by the calling process.
E.g., the following test program:
#include "types.h"
#include "user.h"
#include "syscall.h"
int
main(int argc, char *argv[])
{
printf(1, "initial fork count %d\n", getcount(SYS_fork));
if (fork() == 0) {
printf(1, "child fork count %d\n", getcount(SYS_fork));
printf(1, "child write count %d\n", getcount(SYS_write));
} else {
wait();
printf(1, "parent fork count %d\n", getcount(SYS_fork));
printf(1, "parent write count %d\n", getcount(SYS_write));
}
printf(1, "wait count %d\n", getcount(SYS_wait));
exit();
}
should produce the following output (note that each character is output with a
separate call to write
in xv6):
initial fork count 0
child fork count 0
child write count 19
wait count 0
parent fork count 1
parent write count 41
wait count 1
You will need to modify a number of different files for this exercise, though
the total number of lines of code you'll be adding is quite small. At a minimum,
you'll need to alter syscall.h
, syscall.c
, user.h
, and usys.S
to
implement your new system call (try tracing how some other system call is
implemented, e.g., uptime
, for clues). You will likely also need to update
struct proc
, located in proc.h
, to add a syscall-count tracking data
structure for each process. To re-initialize your data structure when a process
terminates, you may want to look into the functions found in proc.c
.
Chapter 3 of the xv6 book contains details on traps and system calls (though most of the low level details won't be necessary for you to complete this exercise).
To test your implementation, you'll run the getcount
executable (when booted
into xv6), which is based on the program above. Because the program depends on
your implementation, however, it isn't compiled into xv6 by default. When you're
ready to test, you should uncomment the line in the Makefile
following the
UPROGS
declaration that builds getcount
(delete the '#' character in front
of the string "_getcount
").
Note that while getcount
only prints out counts for three different system
calls, your implementation should support all the system calls listed in
syscall.h
. Feel free to add tests to the test program, located in
getcount.c
, for other system calls.
v2paddr
system call (25 points)Now that you've gotten the hang of how to add a system call to xv6, we'll tackle
something a bit more interesting. The v2paddr
system call will accept a
virtual address (in the calling process's address space), and return the
corresponding physical address. If the virtual address given is invalid, the
system call should return -1.
For this exercise we are not providing a test program, so you'll have to write
your own and add it to the Makefile (so that it gets compiled and added to the
xv6 disk image). Make sure the executable for your test program is named
"v2ptest
". For help, see how the getcount
program used in exercise 1 was
added. Your test program should demonstrate that the system call works on
virtual addresses of user-level instructions and both local and global data. It
should also demonstrate that it fails gracefully (returning -1) when an invalid
virtual address is specified.
You should carefully read through walkpgdir
in the vm.c
file --- it contains
just about all the logic you need to implement the meat of the system call. It
would also be a good idea to check out the macros defined in mmu.h
which deal
with paging details.
To submit your work, make sure to git add
any new source files you created
(there will likely only be one -- the test program that you wrote for exercise
2), then commit and push your work to the BitBucket repository, just as you did
for MP1.