This lecture is the introduction to xv6, our re-implementation of Unix v6. Read the source code in the assigned files. You won't have to understand the details yet; we will focus on how the first user-level process comes into existence after the computer is turned on.
You are to turn in this homework during lecture. Please write up your answers to the exercises below and hand them in to a 6.828 staff member at the beginning of lecture.
Fetch and un-tar the xv6 source:
sh-3.00$ wget http://pdos.csail.mit.edu/6.828/2008/src/xv6-rev2.tar.gz sh-3.00$ tar xzvf xv6-rev2.tar.gz xv6/ xv6/asm.h xv6/bio.c xv6/bootasm.S xv6/bootmain.c ... $Build xv6:
$ cd xv6 $ make gcc -O -nostdinc -I. -c bootmain.c gcc -nostdinc -I. -c bootasm.S ld -N -e start -Ttext 0x7C00 -o bootblock.o bootasm.o bootmain.o objdump -S bootblock.o > bootblock.asm objcopy -S -O binary bootblock.o bootblock ... $Find the address of the
mainfunction by looking in
% grep main kernel.asm ... 00102454 <mpmain>: mpmain(void) 001024d0 <main>: 10250d: 79 f1 jns 102500 <main+0x30> 1025f3: 76 6f jbe 102664 <main+0x194> 102611: 74 2f je 102642 <main+0x172>In this case, the address is
Run the kernel inside Bochs, setting a breakpoint
at the beginning of
main (i.e., the address
you just found).
$ make bochs if [ ! -e .bochsrc ]; then ln -s dot-bochsrc .bochsrc; fi bochs -q ======================================================================== Bochs x86 Emulator 2.2.6 (6.828 distribution release 1) ======================================================================== 00000000000i[ ] reading configuration from .bochsrc 00000000000i[ ] installing x module as the Bochs GUI 00000000000i[ ] Warning: no rc file specified. 00000000000i[ ] using log file bochsout.txt Next at t=0 (0) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0 (1) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0 <bochs> b 0x1024d0 <bochs> c (0) Breakpoint 1, 0x0x001024d0 in ?? () Next at t=895814 (0) [0x001024d0] 0008:0x001024d0 (unk. ctxt): lea ecx, dword ptr ss:[esp+0x4] ; 8d4c2404 (1) [0xfffffff0] f000:fff0 (unk. ctxt): jmp far f000:e05b ; ea5be000f0 <bochs>The details of what you see are likely to differ from the above output. Look at the registers and the stack contents:
<bochs> info reg ... <bochs> print-stack ... <bochs>Which part of the stack printout is actually the stack? (Hint: not all of it.) Identify all the non-zero values on the stack.
Turn in: the output of print-stack with the valid part of the stack marked. Write a short (3-5 word) comment next to each non-zero value explaining what it is.
Make a copy of .bochsrc called uni, find the line that starts with cpu: count=2, and change the 2 to 1, and write out the file. Then run
bochs -q -f uni
This will run bochs with just one CPU. Set a breakpoint at segment 3, offset 0, and set it running:
<bochs> vb 0x1B:0 <bochs> c (0) Breakpoint 1, 0x0020b000 (0x001b:0x00000000) Next at t=5312876 (0) [0x0020b000] 001b:0x00000000 (unk. ctxt): push 0x00000024 ; 6824000000 <bochs>
The code that is running is from initcode.S; the push 0x00000024 is the first instruction of the first user-level process. 0x24 is the address of some data; the process is pushing the address so that the kernel can later fetch the data.
Turn in: What physical address does the 0x24 translate to? That is, if the code were at this point to load 32 bits from address 0x24, from what physical address would the data be fetched? What is the data at that address?
Hint: You can use info gdt to find out about segments. You can use the x command to look at physical memory.