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: 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  ***/

Generated on Fri Dec 15 11:18:55 2006 for UbixOS V2 by  doxygen 1.4.7