UbixOS V2 2.0

vmm_memory.c
Go to the documentation of this file.
1 /*-
2 * Copyright (c) 2002-2018 The UbixOS Project.
3 * All rights reserved.
4 *
5 * This was developed by Christopher W. Olsen for the UbixOS Project.
6 *
7 * Redistribution and use in source and binary forms, with or without modification, are permitted
8 * provided that the following conditions are met:
9 *
10 * 1) Redistributions of source code must retain the above copyright notice, this list of
11 * conditions, the following disclaimer and the list of authors.
12 * 2) Redistributions in binary form must reproduce the above copyright notice, this list of
13 * conditions, the following disclaimer and the list of authors in the documentation and/or
14 * other materials provided with the distribution.
15 * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to
16 * endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
24 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <vmm/vmm.h>
30 #include <sys/io.h>
31 #include <ubixos/kpanic.h>
32 #include <lib/kprintf.h>
33 #include <lib/kmalloc.h>
34 #include <ubixos/vitals.h>
35 #include <ubixos/spinlock.h>
36 #include <assert.h>
37
38 //MrOlsen (2016-01-11) NOTE: Need to Seperate Out CPU Specific Stuff Over Time
39 #include <i386/cpu.h>
40
41 static uint32_t freePages = 0;
42 static struct spinLock vmmSpinLock = SPIN_LOCK_INITIALIZER;
43 //static struct spinLock vmmCowSpinLock = SPIN_LOCK_INITIALIZER;
44
45 int numPages = 0x0;
46
47 mMap *vmmMemoryMap = (mMap *) VMM_MMAP_ADDR_RMODE;
48
49 /************************************************************************
50
51 Function: void vmm_memMapInit();
52 Description: This Function Initializes The Memory Map For the System
53 Notes:
54
55 02/20/2004 - Made It Report Real And Available Memory
56
57 ************************************************************************/
58 int vmm_memMapInit() {
59 int i = 0x0;
60 int memStart = 0x0;
61
62 /* Count System Memory */
63 numPages = countMemory();
64
65 /* Set Memory Map To Point To First Physical Page That We Will Use */
66 vmmMemoryMap = (mMap *) VMM_MMAP_ADDR_RMODE;
67
68 /* Initialize Map Make All Pages Not Available */
69 for (i = 0x0; i < numPages; i++) {
70 vmmMemoryMap[i].cowCounter = 0x0;
71 vmmMemoryMap[i].status = memNotavail;
72 vmmMemoryMap[i].pid = vmmID;
73 vmmMemoryMap[i].pageAddr = i * PAGE_SIZE;
74 }
75
76 /* Calculate Start Of Free Memory */
77 memStart = (0x101000 / 0x1000);
78
79 memStart += (((sizeof(mMap) * numPages) + (sizeof(mMap) - 1)) / 0x1000);
80
81 /* Initialize All Free Pages To Available */
82 vmmMemoryMap[(0x100000 / 0x1000)].status = memAvail;
83
84 freePages++;
85
86 for (i = memStart; i < numPages; i++) {
87 vmmMemoryMap[i].status = memAvail;
88 freePages++;
89 }
90
91 if (systemVitals)
92 systemVitals->freePages = freePages;
93
94 /* Print Out Amount Of Memory */
95 kprintf("Real Memory: %iKB\n", numPages * 4);
96 kprintf("Available Memory: %iKB\n", freePages * 4);
97
98 /* Return */
99 return (0);
100 }
101
102 /************************************************************************
103
104 Function: int countMemory();
105 Description: This Function Counts The Systems Physical Memory
106 Notes:
107
108 02/20/2004 - Inspect For Quality And Approved
109
110 ************************************************************************/
111 int countMemory() {
112 register uInt32 *mem = 0x0;
113 unsigned long memCount = -1, tempMemory = 0x0;
114 unsigned short memKb = 8;
115 unsigned char irq1State, irq2State;
116 unsigned long cr0 = 0x0;
117
118 /*
119 * Save The States Of Both IRQ 1 And 2 So We Can Turn Them Off And Restore
120 * Them Later
121 */
122 irq1State = inportByte(0x21);
123 irq2State = inportByte(0xA1);
124
125 /* Turn Off IRQ 1 And 2 To Prevent Chances Of Faults While Examining Memory */
126 outportByte(0x21, 0xFF);
127 outportByte(0xA1, 0xFF);
128
129 /* Save The State Of Register CR0 */
130 cr0 = rcr0();
131
132 /*
133 asm volatile (
134 "movl %%cr0, %%ebx\n"
135 : "=a" (cr0)
136 :
137 : "ebx"
138 );
139 */
140
141 asm volatile ("wbinvd");
142
143 load_cr0(cr0 | 0x00000001 | 0x40000000 | 0x20000000);
144
145 /*
146 asm volatile (
147 "movl %%ebx, %%cr0\n"
148 :
149 : "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000)
150 : "ebx"
151 );
152 */
153
154 while (memKb < 4096 && memCount != 0) {
155 memKb++;
156
157 if (memCount == -1)
158 memCount = 8388608;
159 else
160 memCount += 1024 * 1024;
161
162 mem = (uInt32 *) memCount;
163
164 tempMemory = *mem;
165
166 *mem = 0x55AA55AA;
167
168 asm("": : :"memory");
169
170 if (*mem != 0x55AA55AA) {
171 memCount = 0;
172 }
173 else {
174 *mem = 0xAA55AA55;
175 asm("": : :"memory");
176 if (*mem != 0xAA55AA55) {
177 memCount = 0;
178 }
179 }
180 asm("": : :"memory");
181 *mem = tempMemory;
182 }
183
184 asm("nop");
185
186 //MrOlsen (2016-01-10) NOTE: I don't like this but I start incrementing form the start.
187 memKb--;
188
189 asm("nop");
190
191 load_cr0(cr0);
192
193 /*
194 asm volatile (
195 "movl %%ebx, %%cr0\n"
196 :
197 : "a" (cr0)
198 : "ebx"
199 );
200 */
201
202 asm("nop");
203
204 /* Restore States For Both IRQ 1 And 2 */
205 outportByte(0x21, irq1State);
206 outportByte(0xA1, irq2State);
207
208 asm("nop");
209
210 /* Return Amount Of Memory In Pages */
211 return ((memKb * 1024 * 1024) / PAGE_SIZE);
212 }
213
214 /************************************************************************
215
216 Function: uInt32 vmm_findFreePage(pid_t pid);
217
218 Description: This Returns A Free Physical Page Address Then Marks It
219 Not Available As Well As Setting The PID To The Proccess
220 Allocating This Page
221 Notes:
222
223 ************************************************************************/
224 uint32_t vmm_findFreePage(pidType pid) {
225
226 int i = 0x0;
227
228 /* Lets Look For A Free Page */
229 if (pid < sysID)
230 kpanic("Error: invalid PID %i\n", pid);
231
232 spinLock(&vmmSpinLock);
233
234 for (i = 0; i <= numPages; i++) {
235
236 /*
237 * If We Found A Free Page Set It To Not Available After That Set Its Own
238 * And Return The Address
239 */
240 if ((vmmMemoryMap[i].status == memAvail) && (vmmMemoryMap[i].cowCounter == 0)) {
241 vmmMemoryMap[i].status = memNotavail;
242 vmmMemoryMap[i].pid = pid;
243 freePages--;
244 if (systemVitals)
245 systemVitals->freePages = freePages;
246
247 spinUnlock(&vmmSpinLock);
248 return (vmmMemoryMap[i].pageAddr);
249 }
250 }
251
252 /* If No Free Memory Is Found Return NULL */
253 kpanic("Out Of Memory!!!!");
254 return (0x0);
255 }
256
257 /************************************************************************
258
259 Function: int freePage(uInt32 pageAddr);
260
261 Description: This Function Marks The Page As Free
262
263 Notes:
264
265 ************************************************************************/
266 int freePage(uint32_t pageAddr) {
267
268 int pageIndex = 0x0;
269 assert((pageAddr & 0xFFF) == 0x0);
270
271 /* Find The Page Index To The Memory Map */
272 pageIndex = (pageAddr / 4096);
273
274 /* Check If Page COW Is Greater Then 0 If It Is Dec It If Not Free It */
275 if (vmmMemoryMap[pageIndex].cowCounter == 0) {
276
277 /* Set Page As Avail So It Can Be Used Again */
278 spinLock(&vmmSpinLock);
279 vmmMemoryMap[pageIndex].status = memAvail;
280 vmmMemoryMap[pageIndex].cowCounter = 0x0;
281 vmmMemoryMap[pageIndex].pid = -2;
282 freePages++;
283 systemVitals->freePages = freePages;
284 spinUnlock(&vmmSpinLock);
285
286 }
287 else {
288 /* Adjust The COW Counter */
289 adjustCowCounter(((uint32_t) vmmMemoryMap[pageIndex].pageAddr), -1);
290 }
291
292 /* Return */
293 return (0);
294 }
295
296 /************************************************************************
297
298 Function: int adjustCowCounter(uInt32 baseAddr,int adjustment);
299
300 Description: This Adjust The COW Counter For Page At baseAddr It Will
301 Error If The Count Goes Below 0
302
303 Notes:
304
305 08/01/02 - I Think If Counter Gets To 0 I Should Free The Page
306
307 ************************************************************************/
308 int adjustCowCounter(uInt32 baseAddr, int adjustment) {
309
310 int vmmMemoryMapIndex = (baseAddr / PAGE_SIZE);
311
312 assert((baseAddr & 0xFFF) == 0x0);
313
314 spinLock(&vmmSpinLock);
315 /* Adjust COW Counter */
316 vmmMemoryMap[vmmMemoryMapIndex].cowCounter += adjustment;
317
318 if (vmmMemoryMap[vmmMemoryMapIndex].cowCounter <= 0) {
319
320 if (vmmMemoryMap[vmmMemoryMapIndex].cowCounter < 0)
321 kprintf("ERROR: Why is COW less than 0");
322
323 vmmMemoryMap[vmmMemoryMapIndex].cowCounter = 0x0;
324 vmmMemoryMap[vmmMemoryMapIndex].pid = vmmID;
325 vmmMemoryMap[vmmMemoryMapIndex].status = memAvail;
326 freePages++;
327 systemVitals->freePages = freePages;
328 }
329
330 spinUnlock(&vmmSpinLock);
331 /* Return */
332 return (0);
333 }
334
335 /************************************************************************
336
337 Function: void vmm_freeProcessPages(pid_t pid);
338
339 Description: This Function Will Free Up Memory For The Exiting Process
340
341 Notes:
342
343 08/04/02 - Added Checking For COW Pages First
344
345 ************************************************************************/
346
347 /* TODO: This can be greatly improved for performance but it gets the job done */
348 void vmm_freeProcessPages(pidType pid) {
349 int i = 0, x = 0;
350 uint32_t *tmpPageTable = 0x0;
351 uint32_t *tmpPageDir = (uInt32 *) PD_BASE_ADDR;
352
353 spinLock(&vmmSpinLock);
354
355 /* Check Page Directory For An Avail Page Table */
356 //NOTE: This cleans all memory space up to kernel space
357 #ifdef _IGNORE
358 for (i = 0; i < (PAGE_SIZE - (PAGE_SIZE / 4)); i++) {
359
360 if (tmpPageDir[i] != 0) {
361
362 /* Set Up Page Table Pointer */
363 tmpPageTable = (uint32_t *) (PT_BASE_ADDR + (i * PAGE_SIZE));
364
365 /* Check The Page Table For COW Pages */
366 for (x = 0; x < PD_ENTRIES; x++) {
367
368 /* If The Page Is COW Adjust COW Counter */
369 if (((uint32_t) tmpPageTable[x] & PAGE_COW) == PAGE_COW) {
370 adjustCowCounter(((uint32_t) tmpPageTable[x] & 0xFFFFF000), -1);
371 }
372 }
373 }
374 }
375 #endif
376
377 /* Loop Through Pages To Find Pages Owned By Process */
378 for (i = 0; i < numPages; i++) {
379 if (vmmMemoryMap[i].pid == pid) {
380 /* Check To See If The cowCounter Is Zero If So We Can Ree It */
381 if (vmmMemoryMap[i].cowCounter == 0) {
382 vmmMemoryMap[i].status = memAvail;
383 vmmMemoryMap[i].cowCounter = 0x0;
384 vmmMemoryMap[i].pid = vmmID;
385 freePages++;
386 systemVitals->freePages = freePages;
387 }
388 else {
389 spinUnlock(&vmmSpinLock);
390 adjustCowCounter((i * PAGE_SIZE), -1);
391 spinLock(&vmmSpinLock);
392 }
393 }
394 }
395
396 /* Return */
397 spinUnlock(&vmmSpinLock);
398 return;
399 }
spinlock.h
mMap::pid
pid_t pid
Definition: vmm.h:106
uInt32
unsigned long int uInt32
Definition: objgfx30.h:49
mem
Definition: mem.c:264
PAGE_COW
#define PAGE_COW
Definition: paging.h:64
outportByte
void outportByte(unsigned int, unsigned char)
outputut one byte to specified port
Definition: io.c:72
memNotavail
#define memNotavail
Definition: vmm.h:42
assert
#define assert(e)
Definition: assert.h:64
assert.h
mMap::cowCounter
int cowCounter
Definition: vmm.h:107
spinUnlock
void spinUnlock(spinLock_t *lock)
Definition: spinlock.c:36
vmm.h
mMap::pageAddr
uint32_t pageAddr
Definition: vmm.h:103
SPIN_LOCK_INITIALIZER
#define SPIN_LOCK_INITIALIZER
Definition: spinlock.h:36
kpanic
void kpanic(const char *fmt,...)
print panic message and halt system
Definition: kpanic.c:41
mMap
Definition: vmm.h:102
adjustCowCounter
int adjustCowCounter(uInt32 baseAddr, int adjustment)
Definition: vmm_memory.c:303
spinLock
void spinLock(spinLock_t *lock)
Definition: spinlock.c:55
numPages
int numPages
Definition: vmm_memory.c:45
inportByte
unsigned char inportByte(unsigned int)
input one byte from specified port
Definition: io.c:38
countMemory
int countMemory()
Definition: vmm_memory.c:109
kpanic.h
freePage
int freePage(uint32_t pageAddr)
Definition: vmm_memory.c:262
systemVitals
vitalsNode * systemVitals
Definition: vitals.c:35
cpu.h
kprintf.h
vmm_findFreePage
uint32_t vmm_findFreePage(pidType pid)
Definition: vmm_memory.c:221
mMap::status
u_int16_t status
Definition: vmm.h:104
vitals.h
vmmMemoryMap
mMap * vmmMemoryMap
Definition: vmm_memory.c:47
PD_BASE_ADDR
#define PD_BASE_ADDR
Definition: paging.h:45
uint32_t
__uint32_t uint32_t
Definition: types.h:46
VMM_MMAP_ADDR_RMODE
#define VMM_MMAP_ADDR_RMODE
Definition: vmm.h:51
pidType
int pidType
Definition: types.h:75
vmm_freeProcessPages
void vmm_freeProcessPages(pidType pid)
Definition: vmm_memory.c:342
vitalsStruct::freePages
uint32_t freePages
Definition: vitals.h:43
spinLock
Definition: spinlock.h:41
io.h
vmmID
#define vmmID
Definition: vmm.h:43
PD_ENTRIES
#define PD_ENTRIES
Definition: paging.h:48
PAGE_SIZE
#define PAGE_SIZE
Definition: paging.h:37
memAvail
#define memAvail
Definition: vmm.h:41
vmm_memMapInit
int vmm_memMapInit()
Definition: vmm_memory.c:57
kprintf
int kprintf(const char *,...)
Definition: kprintf.c:259
PT_BASE_ADDR
#define PT_BASE_ADDR
Definition: paging.h:46
kmalloc.h
sysID
#define sysID
Definition: kmalloc.h:38