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