安装 QEMU
使用 Ubuntu 16.04.
1 | sudo apt install libglib2.0-dev libgcrypt20-dev zlib1g-dev gcc-multilib autoconf automake bison flex |
Software Setup
下载实验材料:
1 | athena% mkdir ~/6.828 |
Part 1: PC Bootstrap
这一部分不需要编码,只为了让我们了解 PC bootstrap 的过程。并且让我们熟悉 QEMU 和 QEMU/GDB 的 debug 过程。
1 | cd lab |
这会 build 一个 boot loader 和 kernel : kernel.img
。
Simulating the x86
1 | parallels@parallels-vm:~/Desktop/mit/lab$ make |
kernel.img
包含了 boot loader (obj/boot/boot
) 和 kernel (obj/kernel
)。
然后使用命令:
1 | make qemu |
为了退出,使用命令 Ctrl+a x
在当前的 kernel 里面,可以使用如下两个命令:
1 | K> help |
The PC’s Physical Address Space
1 | +------------------+ <- 0xFFFFFFFF (4GB) |
The first PCs, which were based on the 16-bit Intel 8088 processor, were only capable of addressing 1MB of physical memory. The physical address space of an early PC would therefore start at 0x00000000 but end at 0x000FFFFF instead of 0xFFFFFFFF. The 640KB area marked
"Low Memory"
was the only random-access memory (RAM) that an early PC could use; in fact the very earliest PCs only could be configured with 16KB, 32KB, or 64KB of RAM!
The 384KB area from 0x000A0000 through 0x000FFFFF was reserved by the hardware for special uses such as video display buffers and firmware held in non-volatile memory. The most important part of this reserved area is the
Basic Input/Output System
(BIOS), which occupies the 64KB region from 0x000F0000 through 0x000FFFFF. In early PCs the BIOS was held in true read-only memory (ROM), but current PCs store the BIOS in updateable flash memory. The BIOS is responsible forperforming basic system initialization
such as activating the video card and checking the amount of memory installed. After performing this initialization, the BIOSloads the operating system
from some appropriate location such as floppy disk, hard disk, CD-ROM, or the network, andpasses control
of the machineto the operating system
.
When Intel finally “broke the one megabyte barrier” with the 80286 and 80386 processors, which supported 16MB and 4GB physical address spaces respectively, the PC architects nevertheless preserved the original layout for the low 1MB of physical address space in order to ensure backward compatibility with existing software. Modern PCs therefore have a
"hole"
in physical memory from0x000A0000 to 0x00100000
, dividing RAM into “low” or “conventional memory” (the first 640KB) and “extended memory” (everything else). In addition, some space at the very top of the PC’s 32-bit physical address space, above all physical RAM, is now commonly reserved by the BIOS for use by 32-bit PCI devices.
Recent x86 processors can support more than 4GB of physical RAM, so RAM can extend further above 0xFFFFFFFF. In this case the BIOS must arrange to leave a
second hole
in the system’s RAM at the top of the 32-bit addressable region, to leave room for these 32-bit devices to be mapped. Because of design limitations JOS will use only the first 256MB of a PC’s physical memory anyway, so for now we will pretend that all PCs have “only” a 32-bit physical address space. But dealing with complicated physical address spaces and other aspects of hardware organization that evolved over many years is one of the important practical challenges of OS development.
The ROM BIOS
这部分用来探索 IA-32 兼容的电脑是怎么启动的。
首先进入 lab 目录,打开两个 terminal。
- In one, enter
make qemu-gdb
(ormake qemu-nox-gdb
). This starts up QEMU, butQEMU stops
just before the processor executesthe first instruction
and waits for a debugging connection from GDB. - In the second terminal, from the same directory you ran make, run
make gdb
. You should see something like this:
1 | parallels@parallels-vm:~/Desktop/mit/lab$ make gdb |
我们来看下PC boot 时候的这个第一条指令:
1 | [f000:fff0] 0xffff0: ljmp $0xf000,$0xe05b |
从这条指令可以看出如下几点:
- The IBM PC starts executing at physical address 0x000ffff0, which is at the very top of the 64KB area reserved for the ROM BIOS.
- The PC starts executing with CS = 0xf000 and IP = 0xfff0.
- The first instruction to be executed is a jmp instruction, which jumps to the segmented address CS = 0xf000 and IP = 0xe05b.
On processor reset, the (simulated) processor enters real mode and sets CS to 0xf000 and the IP to 0xfff0, so that execution begins at that (CS:IP) segment address.
Part 2: The Boot Loader
After initializing the PCI bus and all the important devices the BIOS knows about, it searches for a bootable device
such as a floppy, hard drive, or CD-ROM.
If the disk is bootable
, the first sector
of the disk is called the boot sector
, since this is where the boot loader code resides.
When the BIOS finds a bootable floppy or hard disk, it loads the 512-byte boot sector
into memory at physical addresses 0x7c00
through 0x7dff
, and then uses a jmp instruction to set the CS:IP to 0000:7c00, passing control to the boot loader.
For 6.828, the bootload code is in boot/boot.s
and boot/main.c
. The bootloader perform two main functions:
- switch from
real mode
to32bit protected mode
, so the software can access memory above 1MB. And the segmented addresses change from 16bit to 32bit. - boot loader reads kernel from hard disk.