Removed excessive traces in loadelf.c
[marionette.git] / doc / mm.txt
blobc094faf8e19b5b8d10b9001dbb90dc4873f4bfb3
1 MM (Memory manager)
2 ===================
4 [[memory_layout]]
5 Memory layout
6 -------------
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
12 compile-time.
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
20 space,  is removed.
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.
29 Allocation
30 ----------
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
35 stands alone.
37 kernel/mm/allocation.c applies the buddy algoritm to allocating physical and
38 virtual pages.
40 Except the dubious initialisation functions, the functions in allocation.h work
41 in mostly the same way. Here's an example:
43 -----
44 size_t ppalloc(size_t min_pages, size_t max_pages, uintptr_t *start_addr);
45 -----
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
55 memory addresses.
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
59 below).
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.
74 kvmalloc
75 --------
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
84 and page tables.
86 Needless to say, `kvfree` frees the physical and virtual memory allocated with
87 `kvmalloc`.
89 malloc
90 ------
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.
96 Paging
97 ------
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
107 space.
109 Kernel address space
110 ~~~~~~~~~~~~~~~~~~~~
112 The `kvpd` array contains a `struct vpde` for each kernel page table.
114 User address space
115 ~~~~~~~~~~~~~~~~~~
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.
126 Performing mappings
127 ~~~~~~~~~~~~~~~~~~~
129 -----
130 int map_mem(struct pagedir *pd, uintptr_t physical, uintptr_t virtual, size_t n_pages, int flags);
131 -----
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.