8 The virtual address space is split up into two sections: the user address space
9 and the kernel address space ('kernel virtual address space'). Traditionally, the user address space occupies
10 virtual addresses from zero to 0xC0000000 (3 GiB), and the kernel address space
11 occupies the remaining 1 GiB, although this boundary should be moveable at
14 At boot-time, kernel/start.S creates a 1:1 mapping for the first 4 MiB of
15 memory, and creates a mapping at 0xC0000000 to point to the kernel at 0x00100000
16 (1 MiB, where the kernel is first loaded). The page directory of this
17 preliminary mapping is referred to as the 'initial page table'. Later on, (in
18 `create_init_pagedir`), a corresponding `struct pagedir` is created, and the
19 initial 1:1 mapping, which sits in the would-be user portion of the address
22 The portion of each page directory that represents the kernel address space
23 points to the same page tables, and all page directories are kept synchronised.
24 This means that although creating a new kernel page table will require an
25 iteration through all page directories (hopefully this will not be often), it
26 allows the kernel to switch between address spaces freely, and be certain that
27 everything the kernel needs is always available.
32 Physical and virtual page allocation is done using a buddy allocator. The
33 implementation of the actual buddy algorithm is in kernel/mm/buddy.c, and is
34 completely independent from the application of memory management. I.e., buddy.c
37 kernel/mm/allocation.c applies the buddy algoritm to allocating physical and
40 Except the dubious initialisation functions, the functions in allocation.h work
41 in mostly the same way. Here's an example:
44 size_t ppalloc(size_t min_pages, size_t max_pages, uintptr_t *start_addr);
47 This function will allocate between min_pages and max_pages pages of physical
48 memory, place the start address of the allocated region in *start_addr, and
49 return the number of pages allocated. This interface is designed for
50 circumstances where consecutive pages are desired, but not essential.
52 For allocating an exact number of pages, min_pages can equal max_pages.
54 On the inside, `ppalloc` calls buddy_alloc and scales the output onto physical
57 The function `ppfree` frees the pages allocated by `ppalloc`. Similarly, `vpalloc` and
58 `vpfree` allocate and free virtual pages, but these have an extra parameter (see
61 Virtual page allocation
62 -----------------------
64 The `struct vpallocator` represents a virtual page allocator, and is passed to
65 `vpalloc` and `vpfree`. A vpallocator (virtual page allocator) is created with
66 `vpcreate`, and manages a region of virtual memory.
68 There is one vpallocator for the kernel virtual address space, and one
69 vpallocator for each user address space.
71 For kernel virtual address space allocations, the `struct vpallocator` parameter
72 to `vpalloc` and `vpfree` is ignored.
77 kernel/mm/kvmalloc.c contains `kvmalloc` and `kvfree`, which provide an
78 interface similar to `ppalloc` and `ppfree`. `kvmalloc` allocates n physical
79 pages and n contiguous virtual pages in the kernel virtual address space, and
80 maps the two. This is a useful alternative to `malloc`, for page-size
81 structures, where page alignment is required.
83 The prime example of where `kvmalloc` is used, is when creating page directories
86 Needless to say, `kvfree` frees the physical and virtual memory allocated with
92 kernel/mm/malloc.c provides the standard `malloc`, `realloc` and `free`
93 functions, for small data structures in the kernel. They call `kvmalloc` and
94 `kvfree` for their memory.
99 kernel/mm/paging.c keeps track of two similar data structures. The first is the
100 page directory/table structure, which the CPU sees. The second is the 'vpde'
101 structure, which is used to keep track of where page tables are mapped into the
102 kernel virtual address space. These two structures allow mappings to be
103 efficiently modified in non-active address spaces.
105 Each `struct vpde` corresponds to a page directory entry, and contains the
106 virtual address of the corresponding page table, in the kernel virtual address
112 The `kvpd` array contains a `struct vpde` for each kernel page table.
117 Each page directory is represented by a `struct pagedir`, which contains:
119 - Linked list links, so that all page directories can be synchronised (see
120 <<memory_layout,memory layout>>).
121 - The physical address of the page directory (this is loaded into cr3)
122 - The virtual address of the page directory
123 - An array of `struct vpde`: one for each page directory entry in the user
124 address space. I.e. there are fewer than 1024 entries in this array.
130 int map_mem(struct pagedir *pd, uintptr_t physical, uintptr_t virtual, size_t n_pages, int flags);
133 This is the main mapping function. It maps n_pages at `virtual` to point to
134 `physical`. The values for `flags` correspond to the CPU page table flags. The
135 notable flags include:
137 - `PTE_PRESENT` - the page is/pages are present. Without this flag, `map_mem`
138 will perform an *unmap*.
139 - `PTE_WRITABLE` - the page is writable.
140 - `PTE_USER` - the page is readable by user (ring 3) code. If PTE_WRITABLE is
141 set, the page is also writable by user code.
143 NOTE: for mappings in the kernel virtual address space, the `pd` parameter is
144 ignored, and can be set to NULL.