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