copyvirtualspace.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: copyvirtualspace_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
00027 
00028 *****************************************************************************************/
00029 
00030 #include <vmm/vmm.h>
00031 #include <sys/kern_sysctl.h>
00032 #include <ubixos/spinlock.h>
00033 #include <ubixos/kpanic.h>
00034 #include <string.h>
00035 
00036 static spinLock_t cvsSpinLock = SPIN_LOCK_INITIALIZER;
00037 
00038 /************************************************************************
00039 
00040 Function: void *vmmCopyVirtualSpace(pidType pid);
00041 
00042 Description: Creates A Copy Of A Virtual Space And Set All NON Kernel
00043              Space To COW For A Fork This Will Also Alter The Parents
00044              VM Space To Make That COW As Well
00045 
00046 Notes:
00047 
00048 08/02/02 - Added Passing Of pidType pid So We Can Better Keep Track Of
00049            Which Task Has Which Physical Pages
00050 
00051 ************************************************************************/
00052 void           *
00053 vmmCopyVirtualSpace(pidType pid)
00054 {
00055   void           *newPageDirectoryAddress = 0x0;
00056   uInt32         *parentPageDirectory = 0x0, *newPageDirectory = 0x0;
00057   uInt32         *parentPageTable = 0x0, *newPageTable = 0x0;
00058   uInt32         *parentStackPage = 0x0, *newStackPage = 0x0;
00059   uInt16          x = 0, i = 0, s = 0;
00060 
00061   spinLock(&cvsSpinLock);
00062   
00063   /* Set Address Of Parent Page Directory */
00064   parentPageDirectory = (uInt32 *) parentPageDirAddr;
00065   /* Allocate A New Page For The New Page Directory */
00066   if ((newPageDirectory = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0)
00067     kpanic("Error: newPageDirectory == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
00068     
00069   /* Set newPageDirectoryAddress To The Newly Created Page Directories Page */
00070   newPageDirectoryAddress = (void *)vmm_getPhysicalAddr((uInt32) newPageDirectory);
00071   
00072   /* First Set Up A Flushed Page Directory */
00073   memset(newPageDirectory,0x0,0x1000);
00074 
00075   /* Map The Top 1GB Region Of The VM Space */
00076   for (x = 768; x < pageEntries; x++) {
00077     newPageDirectory[x] = parentPageDirectory[x];
00078     }
00079     
00080   /*
00081    * Now For The Fun Stuff For Page Tables 1-766 We Must Map These And Set
00082    * The Permissions On Every Mapped Pages To COW This Will Conserve Memory
00083    * Because The Two VM Spaces Will Be Sharing Some Pages
00084    */
00085   for (x = 0x1; x <= 766; x++) {
00086     /* If Page Table Exists Map It */
00087     if (parentPageDirectory[x] != 0) {
00088       /* Set Parent  To Propper Page Table */
00089       parentPageTable = (uInt32 *) (tablesBaseAddress + (0x1000 * x));
00090       /* Allocate A New Page Table */
00091       if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0)
00092         kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
00093 
00094       /* Set Parent And New Pages To COW */
00095       for (i = 0; i < pageEntries; i++) {
00096       
00097         /* If Page Is Mapped */
00098         if ((parentPageTable[i] & 0xFFFFF000) != 0x0) {
00099           /* Check To See If Its A Stack Page */
00100           if (((uInt32) parentPageTable[i] & PAGE_STACK) == PAGE_STACK) {
00101             /* Alloc A New Page For This Stack Page */
00102             if ((newStackPage = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0)
00103               kpanic("Error: newStackPage == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
00104               
00105             /* Set Pointer To Parents Stack Page */
00106             parentStackPage = (uInt32 *) (((1024 * 4096) * x) + (4096 * i));
00107             
00108             /* Copy The Tack Byte For Byte (I Should Find A Faster Way) */
00109             for (s = 0x0; s < pageEntries; s++) {
00110               newStackPage[s] = parentStackPage[s];
00111               }
00112             /* Insert New Stack Into Page Table */
00113             newPageTable[i] = (vmm_getPhysicalAddr((uInt32) newStackPage) | PAGE_DEFAULT | PAGE_STACK);
00114             /* Unmap From Kernel Space */
00115             vmmUnmapPage((uInt32) newStackPage, 1);
00116             }
00117           else {
00118             /* Set Page To COW In Parent And Child Space */
00119             newPageTable[i] = (((uInt32) parentPageTable[i] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW));
00120             /* Increment The COW Counter For This Page */
00121             if (((uInt32) parentPageTable[i] & PAGE_COW) == PAGE_COW) {
00122               adjustCowCounter(((uInt32) parentPageTable[i] & 0xFFFFF000), 1);
00123               }
00124             else {
00125               adjustCowCounter(((uInt32) parentPageTable[i] & 0xFFFFF000), 2);
00126               parentPageTable[i] = newPageTable[i];
00127               }
00128             }
00129           }
00130         else {
00131           newPageTable[i] = (uInt32) 0x0;
00132           }
00133         }
00134 
00135       /* Put New Page Table Into New Page Directory */
00136       newPageDirectory[x] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT);
00137       /* Unmap Page From Kernel Space But Keep It Marked As Not Avail */
00138       vmmUnmapPage((uInt32) newPageTable, 1);
00139     } else {
00140       newPageDirectory[x] = (uInt32) 0x0;
00141     }
00142   }
00143   /*
00144    * Allocate A New Page For The The First Page Table Where We Will Map The
00145    * Lower Region
00146    */
00147   if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0)
00148     kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
00149     
00150   /* Flush The Page From Garbage In Memory */
00151   memset(newPageTable,0x0,0x1000);
00152 
00153   /* Map This Into The Page Directory */
00154   newPageDirectory[0] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT);
00155   /* Set Address Of Parents Page Table */
00156   parentPageTable = (uInt32 *) tablesBaseAddress;
00157   /* Map The First 1MB Worth Of Pages */
00158   for (x = 0; x < (pageEntries / 4); x++) {
00159     newPageTable[x] = parentPageTable[x];
00160   }
00161   /* Map The Next 3MB Worth Of Pages But Make Them COW */
00162   for (x = (pageEntries / 4) + 1; x < pageEntries; x++) {
00163     /* If Page Is Avaiable Map It */
00164     if ((parentPageTable[x] & 0xFFFFF000) != 0x0) {
00165       /* Set Pages To COW */
00166       newPageTable[x] = (((uInt32) parentPageTable[x] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW));
00167       /* Increment The COW Counter For This Page */
00168       if (((uInt32) parentPageTable[x] & PAGE_COW) == PAGE_COW) {
00169         adjustCowCounter(((uInt32) parentPageTable[x] & 0xFFFFF000), 1);
00170       } else {
00171         adjustCowCounter(((uInt32) parentPageTable[x] & 0xFFFFF000), 2);
00172         parentPageTable[x] = newPageTable[x];
00173       }
00174     } else {
00175       newPageTable[x] = (uInt32) 0x0;
00176     }
00177   }
00178   /* Set Virtual Mapping For Page Directory */
00179   newPageTable[256] = (vmm_getPhysicalAddr((uInt32) newPageDirectory) | PAGE_DEFAULT);
00180 
00181   /*
00182    * Now The Fun Stuff Build The Initial Virtual Page Space So We Don't Have
00183    * To Worry About Mapping Them In Later How Ever I'm Concerned This May
00184    * Become A Security Issue
00185    */
00186   /* First Lets Unmap The Previously Allocated Page Table */
00187   vmmUnmapPage((uInt32) newPageTable, 1);
00188   /* Allocate A New Page Table */
00189   if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0)
00190     kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
00191   /* First Set Our Page Directory To Contain This */
00192   newPageDirectory[767] = vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT;
00193   /* Now Lets Build The Page Table */
00194   for (x = 0; x < pageEntries; x++) {
00195     newPageTable[x] = newPageDirectory[x];
00196   }
00197   /* Now We Are Done So Lets Unmap This Page */
00198   vmmUnmapPage((uInt32) newPageTable, 1);
00199   /* Now We Are Done With The Page Directory So Lets Unmap That Too */
00200   vmmUnmapPage((uInt32) newPageDirectory, 1);
00201   
00202   spinUnlock(&cvsSpinLock);
00203   
00204   /* Return Physical Address Of Page Directory */
00205   return (newPageDirectoryAddress);
00206 }
00207 
00208 /***
00209  $Log: copyvirtualspace_8c-source.html,v $
00209  Revision 1.7  2006/12/15 17:47:04  reddawg
00209  Updates
00209 
00210  Revision 1.4  2006/12/05 14:10:21  reddawg
00211  Workign Distro
00212 
00213  Revision 1.3  2006/12/01 05:12:35  reddawg
00214  We're almost there... :)
00215 
00216  Revision 1.2  2006/11/06 19:10:12  reddawg
00217  Lots Of Updates... Still having issues with brk();
00218 
00219  Revision 1.1.1.1  2006/06/01 12:46:13  reddawg
00220  ubix2
00221 
00222  Revision 1.2  2005/10/12 00:13:38  reddawg
00223  Removed
00224 
00225  Revision 1.1.1.1  2005/09/26 17:24:49  reddawg
00226  no message
00227 
00228  Revision 1.7  2004/07/28 15:05:43  reddawg
00229  Major:
00230    Pages now have strict security enforcement.
00231    Many null dereferences have been resolved.
00232    When apps loaded permissions set for pages rw and ro
00233 
00234  Revision 1.6  2004/07/26 19:15:49  reddawg
00235  test code, fixes and the like
00236 
00237  Revision 1.5  2004/07/25 06:04:00  reddawg
00238  Last of my fixes for the morning
00239 
00240  Revision 1.4  2004/07/20 22:29:55  reddawg
00241  assert: remade assert
00242 
00243  Revision 1.3  2004/07/19 01:58:12  reddawg
00244  vmmCopyVirtualSpace: cleaned up one full page memory leak we were still using old sysID over pid
00245 
00246  Revision 1.2  2004/06/15 12:35:05  reddawg
00247  Cleaned Up
00248 
00249  Revision 1.1.1.1  2004/04/15 12:06:51  reddawg
00250  UbixOS v1.0
00251 
00252  Revision 1.14  2004/04/13 16:36:34  reddawg
00253  Changed our copyright, it is all now under a BSD-Style license
00254 
00255  END
00256  ***/

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