00001 /***************************************************************************************** 00002 Copyright (c) 2002-2004 The UbixOS Project 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are 00006 permitted provided that the following conditions are met: 00007 00008 Redistributions of source code must retain the above copyright notice, this list of 00009 conditions, the following disclaimer and the list of authors. Redistributions in binary 00010 form must reproduce the above copyright notice, this list of conditions, the following 00011 disclaimer and the list of authors in the documentation and/or other materials provided 00012 with the distribution. Neither the name of the UbixOS Project nor the names of its 00013 contributors may be used to endorse or promote products derived from this software 00014 without specific prior written permission. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 00017 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00019 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00021 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00022 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 00023 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00025 00026 $Id: vmm__memory_8c-source.html 88 2016-01-12 00:11:29Z reddawg $ 00027 00028 *****************************************************************************************/ 00029 00030 #include <vmm/vmm.h> 00031 #include <sys/io.h> 00032 #include <ubixos/kpanic.h> 00033 #include <lib/kprintf.h> 00034 #include <lib/kmalloc.h> 00035 #include <ubixos/vitals.h> 00036 #include <ubixos/spinlock.h> 00037 #include <assert.h> 00038 00039 static uInt32 freePages = 0; 00040 static spinLock_t vmmSpinLock = SPIN_LOCK_INITIALIZER; 00041 static spinLock_t vmmCowSpinLock = SPIN_LOCK_INITIALIZER; 00042 00043 00044 int numPages = 0x0; 00045 mMap *vmmMemoryMap = (mMap *) 0x101000; 00046 00047 00048 /************************************************************************ 00049 00050 Function: void vmmMemMapInit(); 00051 Description: This Function Initializes The Memory Map For the System 00052 Notes: 00053 00054 02/20/2004 - Made It Report Real And Available Memory 00055 00056 ************************************************************************/ 00057 int vmmMemMapInit() { 00058 int i = 0x0; 00059 int memStart = 0x0; 00060 00061 /* Count System Memory */ 00062 numPages = countMemory(); 00063 00064 /* Set Memory Map To Point To First Physical Page That We Will Use */ 00065 vmmMemoryMap = (mMap *) 0x101000; 00066 00067 /* Initialize Map Make All Pages Not Available */ 00068 for (i = 0x0; i < numPages; i++) { 00069 vmmMemoryMap[i].cowCounter = 0x0; 00070 vmmMemoryMap[i].status = memNotavail; 00071 vmmMemoryMap[i].pid = vmmID; 00072 vmmMemoryMap[i].pageAddr = i * 4096; 00073 } 00074 00075 /* Calculate Start Of Free Memory */ 00076 memStart = (0x101000 / 0x1000); 00077 memStart += (((sizeof(mMap) * numPages) + (sizeof(mMap) - 1)) / 0x1000); 00078 00079 /* Initialize All Free Pages To Available */ 00080 vmmMemoryMap[(0x100000 / 0x1000)].status = memAvail; 00081 freePages++; 00082 for (i = memStart; i < numPages; i++) { 00083 vmmMemoryMap[i].status = memAvail; 00084 freePages++; 00085 } 00086 00087 /* Print Out Amount Of Memory */ 00088 kprintf("Real Memory: %iKB\n", numPages * 4); 00089 kprintf("Available Memory: %iKB\n", freePages * 4); 00090 00091 /* Return */ 00092 return (0); 00093 } 00094 00095 /************************************************************************ 00096 00097 Function: int countMemory(); 00098 Description: This Function Counts The Systems Physical Memory 00099 Notes: 00100 00101 02/20/2004 - Inspect For Quality And Approved 00102 00103 ************************************************************************/ 00104 int countMemory() { 00105 register uInt32 *mem = 0x0; 00106 unsigned long memCount = -1, tempMemory = 0x0; 00107 unsigned short memKb = 0; 00108 unsigned char irq1State, irq2State; 00109 unsigned long cr0 = 0x0; 00110 00111 /* 00112 * Save The States Of Both IRQ 1 And 2 So We Can Turn Them Off And Restore 00113 * Them Later 00114 */ 00115 irq1State = inportByte(0x21); 00116 irq2State = inportByte(0xA1); 00117 00118 /* Turn Off IRQ 1 And 2 To Prevent Chances Of Faults While Examining Memory */ 00119 outportByte(0x21, 0xFF); 00120 outportByte(0xA1, 0xFF); 00121 00122 /* Save The State Of Register CR0 */ 00123 asm volatile ( 00124 "movl %%cr0, %%ebx\n" 00125 : "=a" (cr0) 00126 : 00127 : "ebx" 00128 ); 00129 00130 asm volatile ("wbinvd"); 00131 asm volatile ( 00132 "movl %%ebx, %%cr0\n" 00133 : 00134 : "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000) 00135 : "ebx" 00136 ); 00137 00138 while (memKb < 4096 && memCount != 0) { 00139 memKb++; 00140 if (memCount == -1) 00141 memCount = 0; 00142 memCount += 1024 * 1024; 00143 mem = (uInt32 *)memCount; 00144 tempMemory = *mem; 00145 *mem = 0x55AA55AA; 00146 asm("": : :"memory"); 00147 if (*mem != 0x55AA55AA) { 00148 memCount = 0; 00149 } 00150 else { 00151 *mem = 0xAA55AA55; 00152 asm("": : :"memory"); 00153 if (*mem != 0xAA55AA55) { 00154 memCount = 0; 00155 } 00156 } 00157 asm("": : :"memory"); 00158 *mem = tempMemory; 00159 } 00160 00161 asm volatile ( 00162 "movl %%ebx, %%cr0\n" 00163 : 00164 : "a" (cr0) 00165 : "ebx" 00166 ); 00167 00168 /* Restore States For Both IRQ 1 And 2 */ 00169 outportByte(0x21, irq1State); 00170 outportByte(0xA1, irq2State); 00171 00172 /* Return Amount Of Memory In Pages */ 00173 return ((memKb * 1024 * 1024) / 4096); 00174 } 00175 00176 /************************************************************************ 00177 00178 Function: uInt32 vmmFindFreePage(pid_t pid); 00179 00180 Description: This Returns A Free Physical Page Address Then Marks It 00181 Not Available As Well As Setting The PID To The Proccess 00182 Allocating This Page 00183 Notes: 00184 00185 ************************************************************************/ 00186 uInt32 vmmFindFreePage(pidType pid) { 00187 int i = 0x0; 00188 00189 /* Lets Look For A Free Page */ 00190 if (pid < sysID) 00191 kpanic("Error: invalid PID %i\n",pid); 00192 00193 spinLock(&vmmSpinLock); 00194 00195 for (i = 0; i <= numPages; i++) { 00196 00197 /* 00198 * If We Found A Free Page Set It To Not Available After That Set Its Own 00199 * And Return The Address 00200 */ 00201 if ((vmmMemoryMap[i].status == memAvail) && (vmmMemoryMap[i].cowCounter == 0)) { 00202 vmmMemoryMap[i].status = memNotavail; 00203 vmmMemoryMap[i].pid = pid; 00204 freePages--; 00205 if (systemVitals) 00206 systemVitals->freePages = freePages; 00207 00208 spinUnlock(&vmmSpinLock); 00209 return (vmmMemoryMap[i].pageAddr); 00210 } 00211 } 00212 00213 /* If No Free Memory Is Found Return NULL */ 00214 kpanic("Out Of Memory!!!!"); 00215 return (0x0); 00216 } 00217 00218 00219 /************************************************************************ 00220 00221 Function: int freePage(uInt32 pageAddr); 00222 00223 Description: This Function Marks The Page As Free 00224 00225 Notes: 00226 00227 ************************************************************************/ 00228 int freePage(uInt32 pageAddr) { 00229 int pageIndex = 0x0; 00230 assert((pageAddr & 0xFFF) == 0x0); 00231 spinLock(&vmmSpinLock); 00232 00233 /* Find The Page Index To The Memory Map */ 00234 pageIndex = (pageAddr / 4096); 00235 00236 /* Check If Page COW Is Greater Then 0 If It Is Dec It If Not Free It */ 00237 if (vmmMemoryMap[pageIndex].cowCounter == 0) { 00238 /* Set Page As Avail So It Can Be Used Again */ 00239 vmmMemoryMap[pageIndex].status = memAvail; 00240 vmmMemoryMap[pageIndex].cowCounter = 0x0; 00241 vmmMemoryMap[pageIndex].pid = -2; 00242 freePages++; 00243 systemVitals->freePages = freePages; 00244 } 00245 else { 00246 /* Adjust The COW Counter */ 00247 adjustCowCounter(((uInt32) vmmMemoryMap[pageIndex].pageAddr), -1); 00248 } 00249 spinUnlock(&vmmSpinLock); 00250 /* Return */ 00251 return (0); 00252 } 00253 00254 /************************************************************************ 00255 00256 Function: int adjustCowCounter(uInt32 baseAddr,int adjustment); 00257 00258 Description: This Adjust The COW Counter For Page At baseAddr It Will 00259 Error If The Count Goes Below 0 00260 00261 Notes: 00262 00263 08/01/02 - I Think If Counter Gets To 0 I Should Free The Page 00264 00265 ************************************************************************/ 00266 int adjustCowCounter(uInt32 baseAddr, int adjustment) { 00267 int vmmMemoryMapIndex = (baseAddr / 4096); 00268 assert((baseAddr & 0xFFF) == 0x0); 00269 spinLock(&vmmCowSpinLock); 00270 /* Adjust COW Counter */ 00271 vmmMemoryMap[vmmMemoryMapIndex].cowCounter += adjustment; 00272 00273 if (vmmMemoryMap[vmmMemoryMapIndex].cowCounter == 0) { 00274 vmmMemoryMap[vmmMemoryMapIndex].cowCounter = 0x0; 00275 vmmMemoryMap[vmmMemoryMapIndex].pid = vmmID; 00276 vmmMemoryMap[vmmMemoryMapIndex].status = memAvail; 00277 freePages++; 00278 systemVitals->freePages = freePages; 00279 } 00280 spinUnlock(&vmmCowSpinLock); 00281 /* Return */ 00282 return (0); 00283 } 00284 00285 /************************************************************************ 00286 00287 Function: void vmmFreeProcessPages(pid_t pid); 00288 00289 Description: This Function Will Free Up Memory For The Exiting Process 00290 00291 Notes: 00292 00293 08/04/02 - Added Checking For COW Pages First 00294 00295 ************************************************************************/ 00296 void vmmFreeProcessPages(pidType pid) { 00297 int i=0,x=0; 00298 uInt32 *tmpPageTable = 0x0; 00299 uInt32 *tmpPageDir = (uInt32 *)parentPageDirAddr; 00300 spinLock(&vmmSpinLock); 00301 /* Check Page Directory For An Avail Page Table */ 00302 for (i=0;i<=0x300;i++) { 00303 if (tmpPageDir[i] != 0) { 00304 /* Set Up Page Table Pointer */ 00305 tmpPageTable = (uInt32 *)(tablesBaseAddress + (i * 0x1000)); 00306 /* Check The Page Table For COW Pages */ 00307 for (x=0;x<pageEntries;x++) { 00308 /* If The Page Is COW Adjust COW Counter */ 00309 if (((uInt32)tmpPageTable[x] & PAGE_COW) == PAGE_COW) { 00310 adjustCowCounter(((uInt32)tmpPageTable[x] & 0xFFFFF000),-1); 00311 } 00312 } 00313 } 00314 } 00315 00316 /* Loop Through Pages To Find Pages Owned By Process */ 00317 for (i=0;i<numPages;i++) { 00318 if (vmmMemoryMap[i].pid == pid) { 00319 /* Check To See If The cowCounter Is Zero If So We Can Ree It */ 00320 if (vmmMemoryMap[i].cowCounter == 0) { 00321 vmmMemoryMap[i].status = memAvail; 00322 vmmMemoryMap[i].cowCounter = 0x0; 00323 vmmMemoryMap[i].pid = vmmID; 00324 freePages++; 00325 systemVitals->freePages = freePages; 00326 } 00327 } 00328 } 00329 /* Return */ 00330 spinUnlock(&vmmSpinLock); 00331 return; 00332 } 00333 00334 /*** 00335 $Log: vmm__memory_8c-source.html,v $ 00335 Revision 1.7 2006/12/15 17:47:08 reddawg 00335 Updates 00335 00336 Revision 1.1 2006/12/01 18:46:19 reddawg 00337 renaming files 00338 00339 Revision 1.2 2006/12/01 05:12:35 reddawg 00340 We're almost there... :) 00341 00342 Revision 1.1.1.1 2006/06/01 12:46:13 reddawg 00343 ubix2 00344 00345 Revision 1.5 2006/06/01 12:42:09 reddawg 00346 Getting back to the basics 00347 00348 Revision 1.4 2006/06/01 04:15:32 reddawg 00349 Woot 00350 00351 Revision 1.3 2006/06/01 03:58:33 reddawg 00352 wondering about this stuff here 00353 00354 Revision 1.2 2005/10/12 00:13:38 reddawg 00355 Removed 00356 00357 Revision 1.1.1.1 2005/09/26 17:24:51 reddawg 00358 no message 00359 00360 Revision 1.15 2004/09/11 23:39:31 reddawg 00361 ok time for bed 00362 00363 Revision 1.14 2004/09/11 16:39:19 apwillia 00364 Fix order in adjustCowCounter to prevent potential race condition 00365 00366 Revision 1.13 2004/08/14 11:23:03 reddawg 00367 Changes 00368 00369 Revision 1.12 2004/08/01 20:51:33 reddawg 00370 adjustCowCounter: we no longer need to debug unhandled adjustments they are normal situations now 00371 00372 Revision 1.11 2004/07/28 00:17:05 reddawg 00373 Major: 00374 Disconnected page 0x0 from the system... Unfortunately this broke many things 00375 all of which have been fixed. This was good because nothing deferences NULL 00376 any more. 00377 00378 Things affected: 00379 malloc,kmalloc,getfreepage,getfreevirtualpage,pagefault,fork,exec,ld,ld.so,exec,file 00380 00381 Revision 1.10 2004/07/26 19:15:49 reddawg 00382 test code, fixes and the like 00383 00384 Revision 1.9 2004/07/24 23:04:44 reddawg 00385 Changes... mark let me know if you fault at pid 185 when you type stress 00386 00387 Revision 1.8 2004/07/24 17:47:28 reddawg 00388 vmm_pageFault: deadlock resolved thanks to a propper solution suggested by geist 00389 00390 Revision 1.7 2004/07/19 02:04:32 reddawg 00391 memory.c: added spinlocks to vmmFindFreePage and vmmFreePage to prevent two tasks from possibly allocating the same page 00392 00393 Revision 1.6 2004/06/14 12:20:54 reddawg 00394 notes: many bugs repaired and ld works 100% now. 00395 00396 Revision 1.5 2004/05/21 15:34:23 reddawg 00397 Fixed a couple of typo 00398 00399 Revision 1.4 2004/05/21 14:50:10 reddawg 00400 Cleaned up 00401 00402 Revision 1.3 2004/05/19 17:28:28 reddawg 00403 Added the correct endTask Procedure 00404 00405 Revision 1.2 2004/04/30 14:16:04 reddawg 00406 Fixed all the datatypes to be consistant uInt8,uInt16,uInt32,Int8,Int16,Int32 00407 00408 Revision 1.1.1.1 2004/04/15 12:06:52 reddawg 00409 UbixOS v1.0 00410 00411 Revision 1.27 2004/04/13 16:36:34 reddawg 00412 Changed our copyright, it is all now under a BSD-Style license 00413 00414 00415 END 00416 ***/