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