The figure shows the structure of the page table entries used to manage the fourth gigabyte of virtual address space It indicates the purpose of each area of virtual address space and this has nothing to do with the assignment of physical RAM

The first section of the address space is used to map all physical pages of the system into the virtual address space of the kernel. Because this address space begins at an offset of 0xC0000000 — the frequently mentioned 3 GiB — each virtual address x corresponds to the physical address x — 0xC0000000, and is therefore a simple linear shift.

As the figure shows, the direct mapping area extends from 0xC0000000 to the high_memory address whose exact value I discuss shortly. As intimated in Chapter 1, there is a problem with this scheme. Because the virtual address space of the kernel comprises only 1 GiB, a maximum of 1 GiB of RAM memory can be mapped. The fact that the maximum memory configuration on IA-32 systems (without PAE) can be up to 4 GiB raises the question of what to do with the remaining memory.

Here's the bad news. The kernel cannot map the whole of physical memory at once if it is larger than 896 MiB.13 This value is even less than the previously stated maximum limit of 1 GiB because

13It would also be possible to get rid of the split completely by introducing two 4 GiB address spaces, one for the kernel and one for each userspace program. However, context switches between kernel and user mode are more costly in this case.

the kernel must reserve the last 128 MiB of its address space for other purposes which I explain shortly. Adding these 128 MiB to the 896 MiB of direct RAM mapping results in a total virtual kernel address space of 1,024 MiB = 1 GiB. The kernel uses the two frequently employed abbreviations "normal" and "highmem"to distinguish between pages that can be mapped directly and those than cannot.

The kernel port must provide two macros for each architecture to translate between physical and virtual addresses in the identity-mapped part of virtual kernel memory (ultimately this is a platform-dependent task).14

□ _pa(vaddr) returns the physical address associated with the virtual address vaddr.

□ _va(paddr) yields the virtual address corresponding to the physical address paddr.

Both functions operate with void pointers and with unsigned longs because both data types are equally valid for the representation of memory addresses.

Caution: The functions are not valid to deal with arbitrary addresses from the virtual address space, but only work for the identity-mapped part! This is why they can usually be implemented with simple linear transformations and do not require a detour over the page tables.

IA-32 maps the page frames into the virtual address space starting from page_offset, and correspondingly the following simple transformation is sufficient:


#define _va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))

For what purpose does the kernel use the last 128 MiB of its address space? As Figure 3-15 shows, it is put to three uses:

1. Virtually contiguous memory areas that are not contiguous in physical memory can be reserved in the vmalloc area. While this mechanism is commonly used with user processes, the kernel itself tries to avoid non-contiguous physical addresses as best it can. It usually succeeds because most of the large memory blocks are allocated for the kernel at boot time when RAM is not yet fragmented. However, on systems that have been running for longer periods, situations can arise in which the kernel requires physical memory but the space available is not contiguous. A prime example of such a situation is when modules are loaded dynamically.

2. Persistent mappings are used to map non-persistent pages from the highmem area into the kernel. Section 3.5.8 takes a close look at this topic.

3. Fixmaps are virtual address space entries associated with a fixed but freely selectable page in physical address space. In contrast to directly mapped pages that are associated with RAM memory by means of a fixed formula, the association between a virtual fixmap address and the position in RAM memory can be freely defined and is then always observed by the kernel.

14The kernel places only two conditions on the functions that must remain as invariants; xi < x2 ^ __va(xi) < vail'2 ) must be valid (for any physical addresses li ), and va(_pa(x)) = x must be valid for any addresses x within the direct mapping.

Two pre-processor symbols are important in this context: vmalloc reserve sets the size of the vmalloc area, and maxmem denotes the maximum possible amount of physical RAM that can be directly addressed by the kernel.

The splitting of memory into the individual areas is controlled by means of the constants shown in Figure 3-15. The constants may have different values depending on the kernel and system configuration. The bound of the direct mappings is specified by high_memory.

Continue reading here: Archx86kernelsetup32c

Was this article helpful?

0 0