Homework 2: Make QEMU, boot xv6, understand page tables

To start working on this homework follow the xv6 setup instructions. After you're done with them, you'll be ready to start working on the assignment.

Exercise 1: Finding and breaking at an address

Find the address of _start, the entry point of the kernel:
vagrant@odin$ nm kernel | grep _start
8010b50c D _binary_entryother_start
8010b4e0 D _binary_initcode_start
0010000c T _start
vagrant@odin$
In this case, the address is 0010000c.

Run the kernel inside QEMU GDB, setting a breakpoint at _start (i.e., the address you just found).

vagrant@odin$ make qemu-nox-gdb
...
Now open another terminal (you do that on your openlab host machine, i.e., odin or tristram, whichever you're using). Change to the folder where Vagrant is configured, and connect to the same Vagrant VM, i.e.:
odin$ cd ~/ics143a/xv6-vagrant-master/
odin$ vagrant ssh
In this new terminal (but now inside your vagrant VM) change to the folder where you've built xv6, and start GDB:
vagrant@odin$ cd /vagrant/ics143a/xv6-public
vagrant@odin$ gdb
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
+ target remote localhost:26000
The target architecture is assumed to be i8086
[f000:fff0]    0xffff0:	ljmp   $0xf000,$0xe05b
0x0000fff0 in ?? ()
+ symbol-file kernel
Set a breakpoint at the address of _start, e.g.
(gdb) br * 0x0010000c
Breakpoint 1 at 0x10000c
(gdb) c
Continuing.
The target architecture is assumed to be i386
=> 0x10000c:	mov    %cr4,%eax

Breakpoint 1, 0x0010000c in ?? ()
(gdb)
The details of what you see are likely to differ from the above output.

Question 1: What is on the stack?

Look at the registers and the stack contents:
(gdb) info reg
...
(gdb) x/24x $esp
...
(gdb)

Write a short (3-5 word) comment next to each zero and non-zero value on the stack explaining what is. Which part of the stack printout is actually the stack? (Hint: not all of it.)

You might find it convenient to consult the files bootasm.S, bootmain.c, and bootblock.asm (which contains the output of the compiler/assembler). The reference page has pointers to x86 assembly documentation, if you are wondering about the semantics of a particular instruction. Here are some questions to help you along:

  • Start by setting a break-point at 0x7c00, the start of the boot block (bootasm.S). Single step through the instructions (type si to the gdb prompt). Where in bootasm.S is the stack pointer initialized?
  • Single step through the call to bootmain; what is on the stack now?
  • What do the first assembly instructions of bootmain do to the stack? Look for bootmain in bootblock.asm.
  • Look in bootmain in bootblock.asm for the call that changes eip to 0x10000c. What does that call do to the stack?

Tip

Since we're running QEMU in headless mode (`make clean qemu-nox`) you don't have a GUI window to close whenever you want. There are two ways to exit QEMU.
  1. First, you can exit the xv6 QEMU session by killing the QEMU process from another terminal. A useful shortcut is to define an `alias` in your local machine as follows:
    alias kill-qemu='vagrant ssh -c "killall qemu-system-i386"'
    
    Add this to your `~/.bash_profile` or `~/.zshrc` file to make it persistant This will send the `killall qemu-system-i386` command over ssh to your vagrant machine. Notice this command will only work if you're running it from somewhere in the directory path of the Vagrantfile running this machine
  2. Alternatively you can send a Ctrl-a x command to the QEMU emulator forcing it to exit (here is a list of QEMU shortcuts and commands).

Exercise 2: Understanding page tables

Question 1: Explain how virtual to physical address translation works

This question asks you to illustrate organization of the x86, 4K, 32bit page table through a simple example. Assume that the hardware translates the virtual address '0xc02005' into the physical address '0x4005'. The physical addresses of the page table directory and the page table (Level 2) involved in the translation of this virtual address are respectively 0x1000 and 0x0. Draw a diagram (hand drawn figures are sufficient, but need to be clear) representing the state of the page table in physical memory and the process of translation (similar to Figure 2-1 in the xv6 book but using concrete physical and virtual addresses and page table entries). Provide a short explanation. Use Chapter 2 of the xv6 book to review how page tables work.

You can find more information about QEMU monitor and GDB debugger here, feel free to explore them.

Submit

Submit your answers on Canvas HW2 Boot xv6 (as a PDF file).

Updated: February, 2017