next up previous contents index
Next: 5. Boot Memory Allocator Up: 4. Page Table Management Previous: 4.5 Allocating and Freeing   Contents   Index

Subsections

4.6 Initializing Kernel Page Tables

When the system first starts, paging is not enabled as page tables do not magically initialize themselves. Each architecture implements this differently so only the x86 case will be discussed which is divided into two phase. The bootstrap phase sets up page tables for just 8MiB so the paging unit can be enabled. The second phase initialize the rest of the page tables.

4.6.1 Bootstrapping

The assembler function startup_32() is responsible for enabling the paging unit in arch/i386/kernel/head.S. While all the normal kernel code in vmlinuz is compiled with the base address at PAGE_OFFSET + 1MiB but the kernel is actually loaded beginning at the first megabyte (0x00100000) of memory4.1. The bootstrap code in this file treats 1MiB as its base address by subtracting __PAGE_OFFSET from any address until the paging unit is enabled so before the paging unit is enabled, a page table mapping has to be established which translates the 8MiB of physical memory at the beginning of physical memory to the correct place after PAGE_OFFSET.



\includegraphics[width=5cm]{graphs/paging_init.ps}
Figure: Call Graph: paging_init


It begins with statically defining an array called swapper_pg_dir() which is placed using directives at 0x00101000. It then established page table entries for 2 pages pg0 and pg1. As the PSE bit is set in the cr4 register, pages translated are 4MiB pages, not 4KiB as is the normal case. The first pointers to pg0 and pg1 are placed to cover the region 1-9MiB and the second pointers to pg0 and pg1 are placed at PAGE_OFFSET+1MiB. This means that when paging is enabled, they will be mapping to the correct pages using either physical or virtual addressing.

Once this mapping has been established, the paging unit is turned on by setting a bit in the cr0 register and a jmp takes places immediately to ensure the EIP register is correct.

4.6.2 Finalizing

The function responsible for Finalizing the page tables is called paging_init(). The call graph for this function on the x86 can be seen on Figure 4.4.

For each pgd_t used by the kernel, the boot memory allocator is called to allocate a page for the PMD. Similarly, a page will be allocated for each pmd_t allocator. If the CPU has the PSE flag available, it will be set to enabled extended paging. This means that each page table entry in the kernel paging tables will be 4MiB instead of 4KiB. If the CPU supports the PGE flag, it also will be set so that the page table entry will be global. Lastly, the page tables from PKMAP_BASE are set up with the function fixrange_init(). Once the page table has been fully setup, swapper_pg_dir is loaded again into the cr3 register and the TLB is flushed.


Footnotes

... memory4.1
The first megabyte is used by some devices so is skipped

next up previous contents index
Next: 5. Boot Memory Allocator Up: 4. Page Table Management Previous: 4.5 Allocating and Freeing   Contents   Index
Mel 2003-01-14