# Lec 2 Notes ## Bootstrapping demo ### Stepping through JOS ~~~ $ cd lab $ make qemu-gdb ~~~ - The Reset vector is at 0xfffffff0 in x86 and contains an instruction that jumps to the start of the BIOS at 0xfe05b. ~~~ The target architecture is assumed to be i8086 [f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b 0x0000fff0 in ?? () + symbol-file obj/kern/kernel (gdb) b bootstack bootstack bootstacktop (gdb) x/li 0xfffffff0 0xfffffff0: ljmp $0xf000,$0xe05b (gdb) info reg eax 0x0 0 ecx 0x0 0 edx 0x663 1635 ebx 0x0 0 esp 0x0 0x0 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0xfff0 0xfff0 eflags 0x2 [ ] cs 0xf000 61440 ss 0x0 0 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 (gdb) ~~~ - Jumping to the BIOS ~~~ (gdb) si [f000:e05b] 0xfe05b: cmpl $0x0,%cs:0x6574 0x0000e05b in ?? () (gdb) info reg eax 0x0 0 ecx 0x0 0 edx 0x663 1635 ebx 0x0 0 esp 0x0 0x0 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0xe05b 0xe05b eflags 0x2 [ ] cs 0xf000 61440 ss 0x0 0 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 ~~~ - At this point you should see the start of bootmain. ### Stepping through SeaBIOS ~~~ $ make qemu-gdb dd if=/dev/zero of=xv6.img count=10000 10000+0 records in 10000+0 records out 5120000 bytes (5.1 MB) copied, 0.0195182 s, 262 MB/s dd if=bootblock of=xv6.img conv=notrunc 1+0 records in 1+0 records out 512 bytes (512 B) copied, 0.000576036 s, 889 kB/s dd if=kernel of=xv6.img seek=1 conv=notrunc 350+1 records in 350+1 records out 179495 bytes (179 kB) copied, 0.000774211 s, 232 MB/s *** Now run 'gdb'. qemu-system-i386 -serial mon:stdio -bios bios.bin -drive file=fs.img,index=1,media=disk,format=raw -drive file=xv6.img,index=0,media=disk,format=raw -smp 2 -m 512 -S -gdb tcp::26000 ~~~ - In another terminal run ~~~ $ gdb (gdb) symbol-file ../seabios-git/out/src/romfile.o Load new symbol table from "../seabios-git/out/src/romfile.o"? (y or n) y Reading symbols from ../seabios-git/out/src/romfile.o...done. (gdb) symbol-file ../seabios-git/out/rom.o Load new symbol table from "../seabios-git/out/rom.o"? (y or n) y Reading symbols from ../seabios-git/out/rom.o...done. (gdb) br do_boot Breakpoint 1 at 0xf2a34: file ./src/boot.c, line 718. (gdb) c Continuing. The target architecture is assumed to be i386 => 0xf2a34 : push %edi Breakpoint 1, do_boot (seq_nr=0) at ./src/boot.c:718 718 { (gdb) layout split ~~~ - This will let you step through the BIOS. - GDB crashes sometimes so be careful! ### Stepping through xv6 ~~~ $ cd xv6 $ make qemu-gdb ~~~ ### Stepping through the bootloader for xv6. - In another terminal in the same directory, ~~~ $ gdb (gdb) symbol-file bootblock.o (gdb) br bootmain (gdb) c (gdb) layout split ~~~ ### QEMU monitor - Change the makefile, replace -serial mon:stdio with -monitor stdio in QEMUOPTS. - Run make qemu-gdb ~~~ (qemu) help (qemu) info registers ~~~ ### Info Registers info registers Display a full dump of the machine's internal register state. In particular, this includes the machine's hidden segment state for the segment selectors and the local, global, and interrupt descriptor tables, plus the task register. This hidden state is the information the virtual CPU read from the GDT/LDT when the segment selector was loaded. Here's the CS when running in the JOS kernel in lab 1 and the meaning of each field: CS =0008 10000000 ffffffff 10cf9a00 DPL=0 CS32 [-R-] CS =0008 The visible part of the code selector. We're using segment 0x8. This also tells us we're referring to the global descriptor table (0x8&4=0), and our CPL (current privilege level) is 0x8&3=0. 10000000 The base of this segment. Linear address = logical address + 0x10000000. ffffffff The limit of this segment. Linear addresses above 0xffffffff will result in segment violation exceptions. 10cf9a00 The raw flags of this segment, which QEMU helpfully decodes for us in the next few fields. DPL=0 The privilege level of this segment. Only code running with privilege level 0 can load this segment. CS32 This is a 32-bit code segment. Other values include DS for data segments (not to be confused with the DS register), and LDT for local descriptor tables. [-R-] This segment is read-only.