From: Ben Pfaff Date: Tue, 28 Sep 2004 01:29:03 +0000 (+0000) Subject: Beginnings of tour. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a402d2cd93bf4432fcaa3f7a45d015290840ba08;p=pintos-anon Beginnings of tour. --- diff --git a/doc/tour.texi b/doc/tour.texi new file mode 100644 index 0000000..abbcb69 --- /dev/null +++ b/doc/tour.texi @@ -0,0 +1,120 @@ +@node Pintos Tour +@chapter A Tour Through Pintos + +This chapter is a brief tour through the Pintos code. It covers the +entire code base, but you'll only be using Pintos one part at a time, +so you may find that you want to read each part as you work on the +corresponding project. + +@node Pintos Loading +@section Loading + +This section covers the Pintos loader and basic kernel +initialization. + +@node Pintos Loader +@subsection The Loader + +The first part of Pintos that runs is the loader, in +@file{threads/loader.S}. The PC BIOS loads the loader into memory. +The loader, in turn, is responsible for initializing the CPU, loading +the rest of Pintos into memory, and then jumping to its start. It's +not important to understand exactly what the loader does, but if +you're interested, read on. You should probably read along with the +loader's source. You should also understand the basics of the +80@var{x}86 architecture as described by chapter 3 of +@bibref{IA32-v1}. + +Because the PC BIOS loads the loader, the loader has to play by the +BIOS's rules. In particular, the BIOS only loads 512 bytes (one disk +sector) into memory. This is a severe restriction and it means that, +practically speaking, the loader has to be written in assembly +language. + +Pintos' loader first initializes the CPU. The first important part of +this is to enable the A20 line, that is, the CPU's address line +numbered 20. For historical reasons, PCs start out with this address +line fixed at 0, which means that attempts to access memory beyond the +first 1 MB (2 raised to the 20th power) will fail. Pintos wants to +access more memory than this, so we have to enable it. + +Next, the loader asks the BIOS for the PC's memory size. Again for +historical reasons, the function that we call in the BIOS to do this +can only detect up to 64 MB of RAM, so that's the practical limit that +Pintos can support. The memory size is stashed away in a location in +the loader that the kernel can read after it boots. + +Third, the loader creates a basic page table. This page table maps +the 64 MB at the base of virtual memory (starting at virtual address +0) directly to the identical physical addresses. It also maps the +same physical memory starting at virtual address +@code{LOADER_PHYS_BASE}, which defaults to @t{0xc0000000} (3 GB). The +Pintos kernel only wants the latter mapping, but there's a +chicken-and-egg problem if we don't include the former: our current +virtual address is roughly @t{0x7c00}, the location where the BIOS +loaded us, and we can't jump to @t{0xc0007c00} until we turn on the +page table, but if we turn on the page table without jumping there, +then we've just pulled the rug out from under ourselves. At any rate, +it's necessary. + +After the page table is initialized, we load the CPU's control +registers to turn on protected mode and paging, and then we set up the +segment registers. We aren't equipped to handle interrupts in +protected mode yet, so we disable interrupts. + +Finally it's time to load the kernel from disk. We choose a simple, +although inflexible, method to do this: we program the IDE disk +controller directly. We assume that the kernel is stored starting +from the second sector of the first IDE disk (the first sector +contains the boot loader itself). We also assume that the BIOS has +already set up the IDE controller for us. We read +@code{KERNEL_LOAD_PAGES} 4 kB pages of data from the disk directly +into virtual memory starting @code{LOADER_KERN_BASE} bytes past +@code{LOADER_PHYS_BASE}, which by default means that we load the +kernel starting 1 MB into physical memory. + +Then we jump to the start of the compiled kernel image. Using the +``linker script'' in @file{threads/kernel.lds.S}, the kernel has +arranged that it begins with the assembly module +@file{threads/start.S}. This assembly module just calls +@code{main()}, which never returns. + +There's one more trick to the loader: the Pintos kernel command line +is stored in the boot loader. The @command{pintos} program actually +modifies the boot loader on disk each time it runs the kernel, putting +in whatever command line arguments the user supplies to the kernel, +and then the kernel at boot time reads those arguments out of the boot +loader in memory. This is something of a nasty hack, but it is simple +and effective. + +@node Kernel Initialization +@subsection Kernel Initialization + +The kernel proper starts with the @code{main()} function. The +@code{main()} function is written in C, as will be most of the code we +encounter in Pintos from here on out. + +When @code{main()} starts, the system is in a pretty raw state. We're +in protected mode with paging enabled, but hardly anything else is +ready. Thus, the @code{main()} function consists primarily of calls +into other Pintos modules' initialization functions, which are +typically named @code{@var{module}_init()}, where @var{module} is the +module's name. + +First we initialize kernel RAM in @code{ram_init()}. The first step +is to clear out the kernel's so-called ``BSS'' segment. The BSS is a +segment that should be initialized to all zeros. In C, whenever you +declare a variable outside a function without providing an +initializer, that variable goes into the BSS.@footnote{This isn't +actually required by the ANSI C standard, but it is the case with most +implementations of C on most machines.} Because it's all zeros, the +BSS isn't stored in the image that the loader brought into memory. We +just use @code{memset()} to zero it out. The other task of +@code{ram_init()} is to read out the machine's memory size from where +the loader stored it and put it into the @code{ram_pages} variable for +later use. + + + +@node Threads Tour +@section Threads