vmm_memory.c

Go to the documentation of this file.
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$
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 <sys/kern_sysctl.h>
00036 #include <ubixos/spinlock.h>
00037 #include <assert.h>
00038 
00042 static uInt32          freePages = 0;
00043 static spinLock_t vmmSpinLock    = SPIN_LOCK_INITIALIZER;
00044 static spinLock_t vmmCowSpinLock = SPIN_LOCK_INITIALIZER;
00045 
00046 
00047 int             numPages = 0x0;
00048 mMap           *vmmMemoryMap = (mMap *) 0x101000;
00049 
00050 
00060 int vmmMemMapInit() {
00061   int i        = 0x0;
00062   int memStart = 0x0;
00063 
00064   /* Count System Memory */
00065   numPages = countMemory();
00066 
00067   /* Set Memory Map To Point To First Physical Page That We Will Use */
00068   vmmMemoryMap = (mMap *) 0x101000;
00069 
00070   /* Initialize Map Make All Pages Not Available */
00071   for (i = 0x0; i < numPages; i++) {
00072     vmmMemoryMap[i].cowCounter = 0x0;
00073     vmmMemoryMap[i].status     = memNotavail;
00074     vmmMemoryMap[i].pid        = vmmID;
00075     vmmMemoryMap[i].pageAddr   = i * 4096;
00076     }
00077 
00078   /* Calculate Start Of Free Memory */
00079   memStart  = (0x101000 / 0x1000);
00080   memStart += (((sizeof(mMap) * numPages) + (sizeof(mMap) - 1)) / 0x1000);
00081 
00082   /* Initialize All Free Pages To Available */
00083   vmmMemoryMap[(0x100000 / 0x1000)].status = memAvail;
00084   freePages++;
00085   for (i = memStart; i < numPages; i++) {
00086     vmmMemoryMap[i].status = memAvail;
00087     freePages++;
00088     }
00089 
00090   /* Print Out Amount Of Memory */
00091   kprintf("Real Memory:      %iKB\n", numPages * 4);
00092   kprintf("Available Memory: %iKB\n", freePages * 4);
00093 
00094   /* Return */
00095   return (0);
00096   }
00097 
00107 int countMemory() {
00108   register uInt32 *mem = 0x0;
00109   unsigned long    memCount = -1, tempMemory = 0x0;
00110   unsigned short   memKb = 0;
00111   unsigned char    irq1State, irq2State;
00112   unsigned long    cr0 = 0x0;
00113 
00114   /*
00115    * Save The States Of Both IRQ 1 And 2 So We Can Turn Them Off And Restore
00116    * Them Later
00117    */
00118   irq1State = inportByte(0x21);
00119   irq2State = inportByte(0xA1);
00120 
00121   /* Turn Off IRQ 1 And 2 To Prevent Chances Of Faults While Examining Memory */
00122   outportByte(0x21, 0xFF);
00123   outportByte(0xA1, 0xFF);
00124 
00125   /* Save The State Of Register CR0 */
00126   asm volatile (
00127     "movl %%cr0, %%ebx\n"
00128     :               "=a" (cr0)
00129     :
00130     :               "ebx"
00131     );
00132 
00133   asm volatile ("wbinvd");
00134   asm volatile (
00135     "movl %%ebx, %%cr0\n"
00136     :
00137     :               "a" (cr0 | 0x00000001 | 0x40000000 | 0x20000000)
00138     :               "ebx"
00139     );
00140 
00141   while (memKb < 4096 && memCount != 0) {
00142     memKb++;
00143     if (memCount == -1)
00144       memCount = 0;
00145     memCount += 1024 * 1024;
00146     mem = (uInt32 *)memCount;
00147     tempMemory = *mem;
00148     *mem = 0x55AA55AA;
00149     asm("": : :"memory");
00150     if (*mem != 0x55AA55AA) {
00151       memCount = 0;
00152       }
00153     else {
00154       *mem = 0xAA55AA55;
00155       asm("": : :"memory");
00156       if (*mem != 0xAA55AA55) {
00157         memCount = 0;
00158         }
00159       }
00160     asm("": : :"memory");
00161     *mem = tempMemory;
00162     }
00163 
00164   asm volatile (
00165     "movl %%ebx, %%cr0\n"
00166     :
00167     :               "a" (cr0)
00168     :               "ebx"
00169     );
00170 
00171   /* Restore States For Both IRQ 1 And 2 */
00172   outportByte(0x21, irq1State);
00173   outportByte(0xA1, irq2State);
00174 
00175   /* Return Amount Of Memory In Pages */
00176   return ((memKb * 1024 * 1024) / 4096);
00177   }
00178 
00189 uInt32 vmmFindFreePage(pidType pid) {
00190   int i = 0x0;
00191 
00192   /* Lets Look For A Free Page */
00193   if (pid < sysID)
00194     kpanic("Error: invalid PID %i\n",pid);
00195 
00196   spinLock(&vmmSpinLock);
00197 
00198   for (i = 0; i <= numPages; i++) {
00199 
00200     /*
00201      * If We Found A Free Page Set It To Not Available After That Set Its Own
00202      * And Return The Address
00203      */
00204     if ((vmmMemoryMap[i].status == memAvail) && (vmmMemoryMap[i].cowCounter == 0)) {
00205       vmmMemoryMap[i].status = memNotavail;
00206       vmmMemoryMap[i].pid = pid;
00207       freePages--;
00208       if (sysctl_enabled == TRUE) {
00209         systemVitals->freePages = freePages;
00210         }
00211 
00212       spinUnlock(&vmmSpinLock);
00213       return (vmmMemoryMap[i].pageAddr);
00214       }
00215     }
00216 
00217   /* If No Free Memory Is Found Return NULL */
00218   kpanic("Out Of Memory!!!!");
00219   return (0x0);
00220   }
00221 
00222 
00232 int freePage(uInt32 pageAddr) {
00233   int pageIndex = 0x0;
00234   assert((pageAddr & 0xFFF) == 0x0);
00235   spinLock(&vmmSpinLock);
00236 
00237   /* Find The Page Index To The Memory Map */
00238   pageIndex = (pageAddr / 4096);
00239 
00240   /* Check If Page COW Is Greater Then 0 If It Is Dec It If Not Free It */
00241   if (vmmMemoryMap[pageIndex].cowCounter == 0) {
00242     /* Set Page As Avail So It Can Be Used Again */
00243     vmmMemoryMap[pageIndex].status = memAvail;
00244     vmmMemoryMap[pageIndex].cowCounter = 0x0;
00245     vmmMemoryMap[pageIndex].pid = -2;
00246     freePages++;
00247     systemVitals->freePages = freePages;
00248     }
00249   else {
00250     /* Adjust The COW Counter */
00251     adjustCowCounter(((uInt32) vmmMemoryMap[pageIndex].pageAddr), -1);
00252     }
00253   spinUnlock(&vmmSpinLock);
00254   /* Return */
00255   return (0);
00256   }
00257 
00270 int adjustCowCounter(uInt32 baseAddr, int adjustment) {
00271   int vmmMemoryMapIndex = (baseAddr / 4096);
00272   assert((baseAddr & 0xFFF) == 0x0);
00273   spinLock(&vmmCowSpinLock);
00274   /* Adjust COW Counter */
00275   vmmMemoryMap[vmmMemoryMapIndex].cowCounter += adjustment;
00276 
00277   if (vmmMemoryMap[vmmMemoryMapIndex].cowCounter == 0) {
00278     vmmMemoryMap[vmmMemoryMapIndex].cowCounter = 0x0;
00279     vmmMemoryMap[vmmMemoryMapIndex].pid = vmmID;
00280     vmmMemoryMap[vmmMemoryMapIndex].status = memAvail;
00281     freePages++;
00282     systemVitals->freePages = freePages;
00283     }
00284   spinUnlock(&vmmCowSpinLock);
00285   /* Return */
00286   return (0);
00287   }
00288 
00300 void vmmFreeProcessPages(pidType pid) {
00301   int i=0,x=0;
00302   uInt32 *tmpPageTable = 0x0;
00303   uInt32 *tmpPageDir   = (uInt32 *)parentPageDirAddr;
00304   spinLock(&vmmSpinLock);
00305   /* Check Page Directory For An Avail Page Table */
00306   for (i=0;i<=0x300;i++) {
00307     if (tmpPageDir[i] != 0) {
00308       /* Set Up Page Table Pointer */
00309       tmpPageTable = (uInt32 *)(tablesBaseAddress + (i * 0x1000));
00310       /* Check The Page Table For COW Pages */
00311       for (x=0;x<pageEntries;x++) {
00312         /* If The Page Is COW Adjust COW Counter */
00313         if (((uInt32)tmpPageTable[x] & PAGE_COW) == PAGE_COW) {
00314           adjustCowCounter(((uInt32)tmpPageTable[x] & 0xFFFFF000),-1);
00315           }
00316         }
00317       }
00318     }
00319 
00320   /* Loop Through Pages To Find Pages Owned By Process */
00321   for (i=0;i<numPages;i++) {
00322     if (vmmMemoryMap[i].pid == pid) {
00323       /* Check To See If The cowCounter Is Zero If So We Can Ree It */
00324       if (vmmMemoryMap[i].cowCounter == 0) {
00325         vmmMemoryMap[i].status = memAvail;
00326         vmmMemoryMap[i].cowCounter = 0x0;
00327         vmmMemoryMap[i].pid = vmmID;
00328         freePages++;
00329         systemVitals->freePages = freePages;
00330         }
00331       }
00332     }
00333   /* Return */
00334   spinUnlock(&vmmSpinLock);
00335   return;
00336   }
00337 
00338 /***
00339  END
00340  ***/
00341 

Generated on Sun Dec 3 02:38:05 2006 for UbixOS V2 by  doxygen 1.4.7