Operating system kernels often like to be linked and run at very high virtual address, such as 0xf0100000
, in order to leave the lower part of the processor’s virtual address space for user programs to use. Many machines don’t have any physical memory at address 0xf0100000
, so we can’t count on being able to store the kernel there. Instead, we will use the processor’s memory management hardware to map virtual address 0xf0100000
(the link address at which the kernel code expects to run) to physical address 0x00100000
(where the boot loader loaded the kernel into physical memory).
Exercise 7
Pause the program at the kernel entry point:
Step through a few instructions till it hits the “mov %eax,%cr0”:
Apparently the memory content at 0x100000 was mapped to address 0xf0100000 after the instruction. The first instruction that would fail if the mapping wasn’t correct should be “mov $0x0,%ebp” at address 0xf010002f, which is the first instruction that should be executed in the mapped memory. As can be seen below, after deleting the instruction, the kernel code will jump to 0xf010002c instead of 0xf010002f. After it jumps there the kernel crashes and prints error message, “qemu: fatal: Trying to execute code outside RAM or ROM at 0xf010002c”.
Before deleting the instruction:
After deleting the instruction:
Exercise 8
Fill in the missing code segment to print octal numbers using patterns of the form “%o”:
The implementation of cprintf (in printf.c) console output for the kernel is based on the kernel console’s cputchar() function (in console.c), which output a character to the console.
The purpose of the following code chunk is explained by the comments:
For the below code snippet, in the call to cprintf(), fmt
points to the string literal “x %d, y %x, z %d\n”; ap
points to the second argument which is x
.
Exercise 9
The two lines in entry.S
below initialize the kernel’s stack:
According to the disassembled file kernel.asm
, the stack locates at 0xf0110000. The stack space is given by .space KSTKSIZE
in entry.S
.
Exercise 10
To understand how a stack frame is set up and taken down when a C function call is made, refer to C Function Call Conventions and the Stack. Each recursive nesting level of test_backtrace
pushes 8 32-bit words on the stack. The are the function’s return address, arguments, stack base pointer EBP
, etc., as illustrated below.
Exercise 11
The backtrack function mon_backtrace
in kern/monitor.c
is implmented as below:
Exercise 11
The implementation of debuginfo_eip
is completed by inserting the call to stab_binsearch
to find the line number for an address:
The implementation of mon_backtrace
is extended by calling debuginfo_eip
to print a line for each stack frame: