Stash your changes from exercise 1 and do git pull before proceeding. You may also do a clean git clone.
In this exercise, you’ll extend lvisor to trap on more interesting cases.
Recall that the %cr3
register holds the physical address of a page table.
An OS kernel needs to change %cr3
during context switches to switch page tables.
Your job is to print out a message when a %cr3
change happens.
Skim Chapter 24: Virtual Machine Control Structures of the Intel SDM.
Focus on 24.6: VM-Execution Control Fields and find out what you need to intercept
writes to %cr3
.
Recall the steps you need in the booting exercise
in order to add a VM-exit handler.
Modify lvisor to intercept writes to %cr3
,
add a corresponding VM-exit handler,
and print the %cr3
value in the handler.
As for lv6, you should see something like the following in the output:
Run xv6 inside your lvisor. What are the first three %cr3
values printed out?
Can you guess what page tables they point to?
You may consult the source code of xv6 (see tests/xv6-src/
).
In an OS, user space may trap into the kernel upon exceptions or interrupts;
it can also choose to enter the kernel through system calls.
Similarly, in a hypervisor, a guest can choose to enter the hypervisor, through
hypercalls. In particular, you need the vmcall
instruction on VMX.
You may find a detailed description of vmcall
in 30.3: VMX Instructions of the Intel SDM.
Replace the two syscall
instructions in tests/lv6/user.S
with vmcall
.
You should see an unhandled VM-exit. Look up the exit reason, and
add a corresponding VM-exit handler for hypercalls.
In the VM-exit handler, implement the two system calls for lv6
(feel free to copy some code from tests/lv6/syscall.c
)
and make sure you see the same output as before.
Think carefully what registers hold the system call number and arguments in your VM-exit handler.
What do you think hypercalls are useful for? Briefly describe one possible application.
It is slightly annoying that we have to duplicate the same implementations
for hypercalls and system calls in lvisor/lv6.
Instead of duplicating the two system calls of lv6 in lvisor,
try to instead emulate the syscall
instruction, so that your lvisor
will jump back to lv6 and execute system calls there.
You may find a detailed description of the syscall
instruction from Intel SDM, Vol 2.
Using vmcall
is easier to trap into lvisor but requires code change.
Can you extend lvisor to work on the original lv6 code (i.e., using syscall
in user.S
)?
You need to configure lvisor to intercept syscall
instructions,
which requires some work. Feel free to search for online resources.
This completes the exercise. In answers.txt
,
write up your answers to the questions, along with a git-diff of your changes.
Upload the file through Canvas.