comparison cos/kernel/mm.c @ 29:7e3bdcb391dc

Added get_page function to mm
author windel
date Thu, 29 Dec 2011 19:34:01 +0100
parents 47b7df514243
children 0148f55bfe24
comparison
equal deleted inserted replaced
28:47b7df514243 29:7e3bdcb391dc
1
2 /* Memory manager functions, 1 /* Memory manager functions,
3 * 2 *
4 * Uses a bitmap to keep track of 4k pages that are in use. 3 * Uses a bitmap to keep track of 4k pages that are in use.
5 * 4 *
6 * */ 5 * */
7 6
8 #include "kernel.h" 7 #include "kernel.h"
9 8
10 uint64_t *frames = 0; 9 static uint64_t *frames = 0;
11 uint64_t nframes = 0; 10 static uint64_t nframes = 0;
12 11
13 void set_frame(uint64_t frame) 12 memmap_t* kernel_map = 0; // kernel memory mapping
13 memmap_t* current_map = 0; // The currently active memory mapping
14
15 static void set_frame(uint64_t frame)
14 { 16 {
15 uint64_t idx = frame / 64; 17 uint64_t idx = frame / 64;
16 uint64_t off = frame % 64; 18 uint64_t off = frame % 64;
17 frames[idx] |= (0x1 << off); 19 frames[idx] |= (0x1 << off);
18 } 20 }
19 21
20 void clear_frame(uint64_t frame) 22 static void clear_frame(uint64_t frame)
21 { 23 {
22 uint64_t idx = frame / 64; 24 uint64_t idx = frame / 64;
23 uint64_t off = frame % 64; 25 uint64_t off = frame % 64;
24 frames[idx] &= ~(0x1 << off); 26 frames[idx] &= ~(0x1 << off);
25 } 27 }
29 uint64_t idx = frame / 64; 31 uint64_t idx = frame / 64;
30 uint64_t off = frame % 64; 32 uint64_t off = frame % 64;
31 return (frames[idx] & (0x1 << off)); 33 return (frames[idx] & (0x1 << off));
32 } 34 }
33 35
34 uint64_t first_frame() 36 static uint64_t first_frame()
35 { 37 {
36 uint64_t i, j; 38 uint64_t i, j;
37 for (i = 0; i < nframes / 64; i++) 39 for (i = 0; i < nframes / 64; i++)
38 { 40 {
39 if (frames[i] != 0xFFFFFFFFFFFFFFFF) 41 if (frames[i] != 0xFFFFFFFFFFFFFFFF)
46 return i*64+j; 48 return i*64+j;
47 } 49 }
48 } 50 }
49 } 51 }
50 } 52 }
51 return 0xFFFFFFFFFFFFFFFF; 53
54 // No frame found:
55 return (uint64_t) -1;
52 } 56 }
53 57
54 // Memory manager functions: 58 // Memory manager functions:
55 void init_memory(uint64_t total_mem_size) 59 void init_memory(uint64_t total_mem_size)
56 { 60 {
57 frames = (uint64_t*)kmalloc_int( ( total_mem_size / 4096 ) / 8 ); 61 // Allocate and clear bits to remember which 4kb-frames are in use:
58 } 62 nframes = (total_mem_size / 0x1000);
59 63 frames = (uint64_t*)kmalloc_int( (nframes / 64) * sizeof(uint64_t) );
60 void alloc_frame() 64 memset(frames, 0, (nframes / 64) * sizeof(uint64_t));
61 { 65
66 // Create kernel map:
67 kernel_map = (memmap_t*)kmalloc_aligned_int(sizeof(memmap_t));
68 memset(kernel_map, 0, sizeof(memmap_t));
69
70 // Identity map lower memory and mark as used by the kernel.
71 // Mark as used by the kernel:
72 uint64_t i;
73 i = 0;
74 while ( i <= placement_address)
75 {
76 page_t *page;
77
78 page = get_page(i, kernel_map); // Get page for address
79 page->address = i >> 12; // Set the address of this page.
80 page->present = 1;
81 page->rw = 1;
82 page->us = 1; // Make all things accessable for users for now.
83
84 set_frame(i / 0x1000);
85
86 i += 0x1000; // Increase a 4 k frame
87 }
88
89 // Set the created mapping as active:
90 // switch_mapping(kernel_map);
91 // TODO: debug crash after enable of new memory map
92 // TODO: set the use of placement malloc to invalid after here.
93 }
94
95 void alloc_frame(page_t *page)
96 {
97 if (page->address != 0)
98 {
99 return;
100 }
62 uint64_t idx = first_frame(); 101 uint64_t idx = first_frame();
63 if (idx == (uint64_t) -1) 102 if (idx == (uint64_t) -1)
64 { 103 {
65 panic("No more memory!"); 104 panic("No more memory!");
66 } 105 }
67 set_frame(idx); 106 set_frame(idx);
107
108 page->present = 1;
109 page->rw = 1;
110 page->us = 0;
111 page->address = idx; // set address in frame number, the byte address is 0x1000 times this value.
68 } 112 }
69 113
70 void free_frame(page_t *page) 114 void free_frame(page_t *page)
71 { 115 {
72 clear_frame(page->frame / 0x1000); 116 clear_frame(page->address / 0x1000);
73 page->frame = 0; 117 page->address = 0;
74 } 118 page->present = 0;
75 119 }
120
121 void switch_mapping(memmap_t* mapping)
122 {
123 current_map = mapping;
124 printf("Switching to use of other at %x\n", &mapping->table);
125
126 asm volatile("mov %0, %%cr3" :: "r"(&mapping->table));
127
128 // Enable paging (and flush cache):
129 uint64_t cr0;
130 asm volatile("mov %%cr0, %0": "=r"(cr0));
131 cr0 |= 0x80000000;
132 asm volatile("mov %0, %%cr0":: "r"(cr0));
133 }
134
135 /* Get a page for a virtual address, and create other tables if required */
136 page_t* get_page(uint64_t address, memmap_t *mapping)
137 {
138 // Retrieve the correct PDP (page dir pointer table):
139 uint64_t pml4index = (address >> 39) & 0x1FF;
140 PDPT_t *pdpt = 0;
141 if (mapping->table[pml4index].present == 1)
142 {
143 pdpt = (PDPT_t*)((uint64_t)mapping->table[pml4index].address << 12);
144 }
145 else
146 {
147 // Create new table:
148 pdpt = (PDPT_t*)kmalloc_aligned_int(sizeof(PDPT_t));
149 printf("Creating PDPT %x\n", pdpt);
150 memset(pdpt, 0, sizeof(PDPT_t));
151
152 // TODO: get function like virt2phys or something here
153 uint64_t address = (uint64_t)pdpt; // get the physical address
154 mapping->table[pml4index].address = address >> 12; // shift right
155 mapping->table[pml4index].rw = 1;
156 mapping->table[pml4index].us = 1;
157 mapping->table[pml4index].present = 1;
158 }
159
160 uint64_t pdptindex = (address >> 30) & 0x1FF;
161 // Retrieve the correct page directory:
162 PD_t *pd = 0;
163 if (pdpt->table[pdptindex].present == 1)
164 {
165 pd = (PD_t*)((uint64_t)pdpt->table[pdptindex].address << 12);
166 }
167 else
168 {
169 printf("Creating PD\n");
170 // Create a new table:
171 pd = (PD_t*)kmalloc_aligned_int(sizeof(PD_t));
172 memset(pd, 0, sizeof(PD_t));
173
174 // Enter table into PDPT:
175 // TODO: make virt2phys function:
176 uint64_t address = (uint64_t)pd;
177 pdpt->table[pdptindex].address = address >> 12;
178 pdpt->table[pdptindex].rw = 1;
179 pdpt->table[pdptindex].us = 1;
180 pdpt->table[pdptindex].present = 1;
181 }
182
183 // Retrieve the correct page table:
184 uint64_t pdindex = (address >> 21) & 0x1FF;
185 PT_t *pt = 0;
186 if (pd->table[pdindex].present == 1)
187 {
188 pt = (PT_t*)((uint64_t)pd->table[pdindex].address << 12);
189 }
190 else
191 {
192 printf("Creating PT\n");
193 // Create table:
194 pt = (PT_t*)kmalloc_aligned_int(sizeof(PD_t));
195 memset(pt, 0, sizeof(PT_t));
196
197 // Enter PT into PD:
198 uint64_t address = (uint64_t)pt;
199 pd->table[pdindex].address = address >> 12;
200 pd->table[pdindex].rw = 1;
201 pd->table[pdindex].us = 1;
202 pd->table[pdindex].present = 1;
203 }
204
205 // Finally get the page from the directory:
206 // TODO: convert from physical address to virtual address:
207 uint64_t ptindex = (address >> 12) & 0x1FF;
208 return &pt->table[ptindex];
209 }
210