diff --git a/src/sys/include/vmm/paging.h b/src/sys/include/vmm/paging.h index 944f3e2..d44bea8 100644 --- a/src/sys/include/vmm/paging.h +++ b/src/sys/include/vmm/paging.h @@ -34,14 +34,15 @@ #include #include -#define VM_THRD 0 -#define VM_TASK 1 +#define VM_THRD 0 +#define VM_TASK 1 -#define pageLength 0x00000400 -#define pageSize 4096 -#define pageEntries (pageSize/4) +#define pageLength 0x00000400 +#define pageSize 4096 +#define pageEntries (pageSize/4) #define tablesBaseAddress 0xBFC00000 #define parentPageDirAddr 0x100000 +#define PARENT_PAGEDIR_ADDR 0x100000 /* Address at which the page directory is stored */ #define PAGE_COW 0x00000200 #define PAGE_STACK 0x00000400 @@ -52,14 +53,14 @@ #define PAGE_DEFAULT (PAGE_PRESENT|PAGE_WRITE|PAGE_USER) #define KERNEL_PAGE_DEFAULT (PAGE_PRESENT|PAGE_WRITE) -#define PAGE_SHIFT 12 /* LOG2(PAGE_SIZE) */ -#define PAGE_SIZE (1<>PAGE_SHIFT) +#define trunc_page(x) ((x) & ~PAGE_MASK) +#define round_page(x) (((x) + PAGE_MASK) & ~PAGE_MASK) +#define ctob(x) ((x)<>PAGE_SHIFT) int vmmClearVirtualPage(uInt32 pageAddr); diff --git a/src/sys/include/vmm/vmm.h b/src/sys/include/vmm/vmm.h index 5d9fa86..dfc8a00 100644 --- a/src/sys/include/vmm/vmm.h +++ b/src/sys/include/vmm/vmm.h @@ -60,31 +60,5 @@ #endif /*** - $Log$ - Revision 1.2 2006/12/05 14:10:21 reddawg - Workign Distro - - Revision 1.1.1.1 2006/06/01 12:46:13 reddawg - ubix2 - - Revision 1.2 2005/10/12 00:13:37 reddawg - Removed - - Revision 1.1.1.1 2005/09/26 17:23:59 reddawg - no message - - Revision 1.6 2004/07/21 17:39:04 reddawg - removed device - - Revision 1.5 2004/07/19 02:08:28 reddawg - Cleaned out the rest of debuging code also temporarily disabled the ip stack to improve boot time - - Revision 1.4 2004/07/09 12:18:19 reddawg - Updating Initialization Procedures - - Revision 1.3 2004/05/21 15:21:04 reddawg - Cleaned up - - END ***/ diff --git a/src/sys/vmm/Makefile b/src/sys/vmm/Makefile index 7dc426c..87a81a5 100644 --- a/src/sys/vmm/Makefile +++ b/src/sys/vmm/Makefile @@ -6,7 +6,7 @@ include ../Makefile.inc # Objects -OBJS = page_fault.o pagefault.o getfreevirtualpage.o copyvirtualspace.o setpageattributes.o unmappage.o getphysicaladdr.o getfreepage.o createvirtualspace.o vmm_memory.o paging.o vmm_init.o +OBJS = page_fault.o pagefault.o setpageattributes.o unmappage.o getphysicaladdr.o getfreepage.o vmm_memory.o paging.o vmm_init.o vmm_virtual.o all: $(OBJS) diff --git a/src/sys/vmm/copyvirtualspace.c b/src/sys/vmm/copyvirtualspace.c deleted file mode 100644 index fd8046f..0000000 --- a/src/sys/vmm/copyvirtualspace.c +++ /dev/null @@ -1,256 +0,0 @@ -/***************************************************************************************** - Copyright (c) 2002-2004 The UbixOS Project - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, are - permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this list of - conditions, the following disclaimer and the list of authors. Redistributions in binary - form must reproduce the above copyright notice, this list of conditions, the following - disclaimer and the list of authors in the documentation and/or other materials provided - with the distribution. Neither the name of the UbixOS Project nor the names of its - contributors may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - $Id$ - -*****************************************************************************************/ - -#include -#include -#include -#include -#include - -static spinLock_t cvsSpinLock = SPIN_LOCK_INITIALIZER; - -/************************************************************************ - -Function: void *vmmCopyVirtualSpace(pidType pid); - -Description: Creates A Copy Of A Virtual Space And Set All NON Kernel - Space To COW For A Fork This Will Also Alter The Parents - VM Space To Make That COW As Well - -Notes: - -08/02/02 - Added Passing Of pidType pid So We Can Better Keep Track Of - Which Task Has Which Physical Pages - -************************************************************************/ -void * -vmmCopyVirtualSpace(pidType pid) -{ - void *newPageDirectoryAddress = 0x0; - uInt32 *parentPageDirectory = 0x0, *newPageDirectory = 0x0; - uInt32 *parentPageTable = 0x0, *newPageTable = 0x0; - uInt32 *parentStackPage = 0x0, *newStackPage = 0x0; - uInt16 x = 0, i = 0, s = 0; - - spinLock(&cvsSpinLock); - - /* Set Address Of Parent Page Directory */ - parentPageDirectory = (uInt32 *) parentPageDirAddr; - /* Allocate A New Page For The New Page Directory */ - if ((newPageDirectory = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) - kpanic("Error: newPageDirectory == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); - - /* Set newPageDirectoryAddress To The Newly Created Page Directories Page */ - newPageDirectoryAddress = (void *)vmm_getPhysicalAddr((uInt32) newPageDirectory); - - /* First Set Up A Flushed Page Directory */ - memset(newPageDirectory,0x0,0x1000); - - /* Map The Top 1GB Region Of The VM Space */ - for (x = 768; x < pageEntries; x++) { - newPageDirectory[x] = parentPageDirectory[x]; - } - - /* - * Now For The Fun Stuff For Page Tables 1-766 We Must Map These And Set - * The Permissions On Every Mapped Pages To COW This Will Conserve Memory - * Because The Two VM Spaces Will Be Sharing Some Pages - */ - for (x = 0x1; x <= 766; x++) { - /* If Page Table Exists Map It */ - if (parentPageDirectory[x] != 0) { - /* Set Parent To Propper Page Table */ - parentPageTable = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); - /* Allocate A New Page Table */ - if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) - kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); - - /* Set Parent And New Pages To COW */ - for (i = 0; i < pageEntries; i++) { - - /* If Page Is Mapped */ - if ((parentPageTable[i] & 0xFFFFF000) != 0x0) { - /* Check To See If Its A Stack Page */ - if (((uInt32) parentPageTable[i] & PAGE_STACK) == PAGE_STACK) { - /* Alloc A New Page For This Stack Page */ - if ((newStackPage = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) - kpanic("Error: newStackPage == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); - - /* Set Pointer To Parents Stack Page */ - parentStackPage = (uInt32 *) (((1024 * 4096) * x) + (4096 * i)); - - /* Copy The Tack Byte For Byte (I Should Find A Faster Way) */ - for (s = 0x0; s < pageEntries; s++) { - newStackPage[s] = parentStackPage[s]; - } - /* Insert New Stack Into Page Table */ - newPageTable[i] = (vmm_getPhysicalAddr((uInt32) newStackPage) | PAGE_DEFAULT | PAGE_STACK); - /* Unmap From Kernel Space */ - vmmUnmapPage((uInt32) newStackPage, 1); - } - else { - /* Set Page To COW In Parent And Child Space */ - newPageTable[i] = (((uInt32) parentPageTable[i] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW)); - /* Increment The COW Counter For This Page */ - if (((uInt32) parentPageTable[i] & PAGE_COW) == PAGE_COW) { - adjustCowCounter(((uInt32) parentPageTable[i] & 0xFFFFF000), 1); - } - else { - adjustCowCounter(((uInt32) parentPageTable[i] & 0xFFFFF000), 2); - parentPageTable[i] = newPageTable[i]; - } - } - } - else { - newPageTable[i] = (uInt32) 0x0; - } - } - - /* Put New Page Table Into New Page Directory */ - newPageDirectory[x] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT); - /* Unmap Page From Kernel Space But Keep It Marked As Not Avail */ - vmmUnmapPage((uInt32) newPageTable, 1); - } else { - newPageDirectory[x] = (uInt32) 0x0; - } - } - /* - * Allocate A New Page For The The First Page Table Where We Will Map The - * Lower Region - */ - if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) - kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); - - /* Flush The Page From Garbage In Memory */ - memset(newPageTable,0x0,0x1000); - - /* Map This Into The Page Directory */ - newPageDirectory[0] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT); - /* Set Address Of Parents Page Table */ - parentPageTable = (uInt32 *) tablesBaseAddress; - /* Map The First 1MB Worth Of Pages */ - for (x = 0; x < (pageEntries / 4); x++) { - newPageTable[x] = parentPageTable[x]; - } - /* Map The Next 3MB Worth Of Pages But Make Them COW */ - for (x = (pageEntries / 4) + 1; x < pageEntries; x++) { - /* If Page Is Avaiable Map It */ - if ((parentPageTable[x] & 0xFFFFF000) != 0x0) { - /* Set Pages To COW */ - newPageTable[x] = (((uInt32) parentPageTable[x] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW)); - /* Increment The COW Counter For This Page */ - if (((uInt32) parentPageTable[x] & PAGE_COW) == PAGE_COW) { - adjustCowCounter(((uInt32) parentPageTable[x] & 0xFFFFF000), 1); - } else { - adjustCowCounter(((uInt32) parentPageTable[x] & 0xFFFFF000), 2); - parentPageTable[x] = newPageTable[x]; - } - } else { - newPageTable[x] = (uInt32) 0x0; - } - } - /* Set Virtual Mapping For Page Directory */ - newPageTable[256] = (vmm_getPhysicalAddr((uInt32) newPageDirectory) | PAGE_DEFAULT); - - /* - * Now The Fun Stuff Build The Initial Virtual Page Space So We Don't Have - * To Worry About Mapping Them In Later How Ever I'm Concerned This May - * Become A Security Issue - */ - /* First Lets Unmap The Previously Allocated Page Table */ - vmmUnmapPage((uInt32) newPageTable, 1); - /* Allocate A New Page Table */ - if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) - kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); - /* First Set Our Page Directory To Contain This */ - newPageDirectory[767] = vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT; - /* Now Lets Build The Page Table */ - for (x = 0; x < pageEntries; x++) { - newPageTable[x] = newPageDirectory[x]; - } - /* Now We Are Done So Lets Unmap This Page */ - vmmUnmapPage((uInt32) newPageTable, 1); - /* Now We Are Done With The Page Directory So Lets Unmap That Too */ - vmmUnmapPage((uInt32) newPageDirectory, 1); - - spinUnlock(&cvsSpinLock); - - /* Return Physical Address Of Page Directory */ - return (newPageDirectoryAddress); -} - -/*** - $Log$ - Revision 1.4 2006/12/05 14:10:21 reddawg - Workign Distro - - Revision 1.3 2006/12/01 05:12:35 reddawg - We're almost there... :) - - Revision 1.2 2006/11/06 19:10:12 reddawg - Lots Of Updates... Still having issues with brk(); - - Revision 1.1.1.1 2006/06/01 12:46:13 reddawg - ubix2 - - Revision 1.2 2005/10/12 00:13:38 reddawg - Removed - - Revision 1.1.1.1 2005/09/26 17:24:49 reddawg - no message - - Revision 1.7 2004/07/28 15:05:43 reddawg - Major: - Pages now have strict security enforcement. - Many null dereferences have been resolved. - When apps loaded permissions set for pages rw and ro - - Revision 1.6 2004/07/26 19:15:49 reddawg - test code, fixes and the like - - Revision 1.5 2004/07/25 06:04:00 reddawg - Last of my fixes for the morning - - Revision 1.4 2004/07/20 22:29:55 reddawg - assert: remade assert - - Revision 1.3 2004/07/19 01:58:12 reddawg - vmmCopyVirtualSpace: cleaned up one full page memory leak we were still using old sysID over pid - - Revision 1.2 2004/06/15 12:35:05 reddawg - Cleaned Up - - Revision 1.1.1.1 2004/04/15 12:06:51 reddawg - UbixOS v1.0 - - Revision 1.14 2004/04/13 16:36:34 reddawg - Changed our copyright, it is all now under a BSD-Style license - - END - ***/ diff --git a/src/sys/vmm/createvirtualspace.c b/src/sys/vmm/createvirtualspace.c deleted file mode 100644 index 6402bb3..0000000 --- a/src/sys/vmm/createvirtualspace.c +++ /dev/null @@ -1,148 +0,0 @@ -/***************************************************************************************** - Copyright (c) 2002 The UbixOS Project - All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of -conditions, the following disclaimer and the list of authors. Redistributions in binary -form must reproduce the above copyright notice, this list of conditions, the following -disclaimer and the list of authors in the documentation and/or other materials provided -with the distribution. Neither the name of the UbixOS Project nor the names of its -contributors may be used to endorse or promote products derived from this software -without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT -OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR -TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - $Log$ - Revision 1.1.1.1 2006/06/01 12:46:13 reddawg - ubix2 - - Revision 1.2 2005/10/12 00:13:38 reddawg - Removed - - Revision 1.1.1.1 2005/09/26 17:24:50 reddawg - no message - - Revision 1.2 2004/07/28 15:05:43 reddawg - Major: - Pages now have strict security enforcement. - Many null dereferences have been resolved. - When apps loaded permissions set for pages rw and ro - - Revision 1.1.1.1 2004/04/15 12:06:51 reddawg - UbixOS v1.0 - - Revision 1.8 2004/04/13 16:36:34 reddawg - Changed our copyright, it is all now under a BSD-Style license - - - - $Id$ - -*****************************************************************************************/ - -#include - - -/************************************************************************ - -Function: void *vmmCreateVirtualSpace(pid_t); -Description: Creates A Virtual Space For A New Task -Notes: - -07/30/02 - This Is Going To Create A New VM Space However Its Going To - Share The Same Top 1GB Space With The Kernels VM And Lower - 1MB Of VM Space With The Kernel - -07/30/02 - Note This Is Going To Get The Top 1Gig And Lower 1MB Region - From The Currently Loaded Page Directory This Is Safe Because - All VM Spaces Will Share These Regions - -07/30/02 - Note I Realized A Mistake The First Page Table Will Need To Be - A Copy But The Page Tables For The Top 1GB Will Not Reason For - This Is That We Just Share The First 1MB In The First Page Table - So We Will Just Share Physical Pages. - -08/02/02 - Added Passing Of pid_t pid For Better Tracking Of Who Has Which - Set Of Pages - -************************************************************************/ -void * -vmmCreateVirtualSpace(pid_t pid) -{ - void *newPageDirectoryAddress = 0x0; - uInt32 *parentPageDirectory = 0x0, *newPageDirectory = 0x0; - uInt32 *parentPageTable = 0x0, *newPageTable = 0x0; - int x = 0; - - /* Set Address Of Parent Page Directory */ - parentPageDirectory = (uInt32 *) parentPageDirAddr; - /* Allocate A New Page For The New Page Directory */ - newPageDirectory = (uInt32 *) vmmGetFreePage(pid); - /* Set newPageDirectoryAddress To The Newly Created Page Directories Page */ - newPageDirectoryAddress = (void *)vmm_getPhysicalAddr((uInt32) newPageDirectory); - /* First Set Up A Flushed Page Directory */ - for (x = 0; x < pageEntries; x++) { - (uInt32) newPageDirectory[x] = (uInt32) 0x0; - } - /* Map The Top 1GB Region Of The VM Space */ - for (x = 768; x < pageEntries; x++) { - newPageDirectory[x] = parentPageDirectory[x]; - } - /* - * Allocate A New Page For The The First Page Table Where We Will Map The - * Lower Region - */ - newPageTable = (uInt32 *) vmmGetFreePage(pid); - /* Flush The Page From Garbage In Memory */ - for (x = 0; x < pageEntries; x++) { - (uInt32) newPageTable[x] = (uInt32) 0x0; - } - /* Map This Into The Page Directory */ - newPageDirectory[0] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT); - /* Set Address Of Parents Page Table */ - parentPageTable = (uInt32 *) tablesBaseAddress; - /* Map The First 1MB Worth Of Pages */ - for (x = 0; x < (pageEntries / 4); x++) { - newPageTable[x] = parentPageTable[x]; - } - /* Set Virtual Mapping For Page Directory */ - newPageTable[256] = (vmm_getPhysicalAddr((uInt32) newPageDirectory) | PAGE_DEFAULT); - - /* - * Now The Fun Stuff Build The Initial Virtual Page Space So We Don't Have - * To Worry About Mapping Them In Later How Ever I'm Concerned This May - * Become A Security Issue - */ - /* First Lets Unmap The Previously Allocated Page Table */ - vmmUnmapPage((uInt32) newPageTable, 1); - /* Allocate A New Page Table */ - newPageTable = (uInt32 *) vmmGetFreePage(pid); - /* First Set Our Page Directory To Contain This */ - newPageDirectory[767] = vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT; - /* Now Lets Build The Page Table */ - for (x = 0; x < pageEntries; x++) { - newPageTable[x] = newPageDirectory[x]; - } - /* Now We Are Done So Lets Unmap This Page */ - vmmUnmapPage((uInt32) newPageTable, 1); - /* Now We Are Done With The Page Directory So Lets Unmap That Too */ - vmmUnmapPage((uInt32) newPageDirectory, 1); - /* Return Physical Address Of Page Directory */ - return (newPageDirectoryAddress); -} - -/*** - END - ***/ - diff --git a/src/sys/vmm/getfreevirtualpage.c b/src/sys/vmm/getfreevirtualpage.c deleted file mode 100644 index f2dd047..0000000 --- a/src/sys/vmm/getfreevirtualpage.c +++ /dev/null @@ -1,293 +0,0 @@ -/***************************************************************************************** - Copyright (c) 2002-2004 The UbixOS Project - All rights reserved. - - Redistribution and use in source and binary forms, with or without modification, are - permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, this list of - conditions, the following disclaimer and the list of authors. Redistributions in binary - form must reproduce the above copyright notice, this list of conditions, the following - disclaimer and the list of authors in the documentation and/or other materials provided - with the distribution. Neither the name of the UbixOS Project nor the names of its - contributors may be used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - $Id$ - -*****************************************************************************************/ - -#include -#include -#include -#include -#include - -static spinLock_t fvpSpinLock = SPIN_LOCK_INITIALIZER; - -/************************************************************************ - -Function: void *vmmGetFreeVirtualPage(pidType pid,int count); -Description: Returns A Free Page Mapped To The VM Space -Notes: - -08/11/02 - This Will Return Next Avilable Free Page Of Tasks VM Space - -************************************************************************/ -void *vmmGetFreeVirtualPage(pidType pid, int count,int type) { - int x = 0, y = 0, c = 0; - uInt32 *pageTableSrc = 0x0; - uInt32 *pageDir = 0x0; - uInt32 start_page = 0x0; - - - spinLock(&fvpSpinLock); - - pageDir = (uInt32 *) parentPageDirAddr; - - /* Lets Search For A Free Page */ - if (_current->oInfo.vmStart <= 0x100000) - kpanic("Invalid vmStart\n"); - - - if (type == VM_THRD) { - start_page = (u_int32_t)(_current->td.vm_daddr + ctob(_current->td.vm_dsize)); - #ifdef DEBUG - kprintf(".%i.",count); - #endif - //count--; - } - else if (type == VM_TASK) { - //kprintf("vmStart"); - start_page = _current->oInfo.vmStart; - } - else - K_PANIC("Invalid Type"); - - //for (x = ((_current->td.vm_daddr + _current->td.vm_dsize) / (1024 * 4096)); x < 1024; x++) { - for (x = (start_page / (1024 * 4096)); x < 1024; x++) { - /* Set Page Table Address */ - if ((pageDir[x] & PAGE_PRESENT) != PAGE_PRESENT) { - /* If Page Table Is Non Existant Then Set It Up */ - pageDir[x] = (uInt32) vmmFindFreePage(_current->id) | PAGE_DEFAULT; - /* Also Add It To Virtual Space So We Can Make Changes Later */ - pageTableSrc = (uInt32 *) (tablesBaseAddress + (4096 * 767)); - pageTableSrc[x] = pageDir[x]; - y = 1; - /* Reload Page Directory */ - asm( - "movl %cr3,%eax\n" - "movl %eax,%cr3\n" - ); - } - pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); - if (y != 0x0) { - for (y = 0x0;ytd.vm_dsize += btoc(0x1000); - /* HACK MEMORY LEAK */ - //pageTableSrc[y] = 0x0; - } - if ((uInt32) pageTableSrc[y] == (uInt32) 0x0) { - if (count > 0x1) { - for (c = 0; c < count; c++) { - if (y + c < 1024) { - if ((pageTableSrc[y + c] & PAGE_COW) == PAGE_COW) { - #ifdef DEBUG - kprintf("PAGE-COW-2"); - #endif - //_current->td.vm_dsize += btoc(0x1000); - /* HACK MEMORY LEAK */ - //pageTableSrc[y + c] = 0x0; - } - - if ((uInt32) pageTableSrc[y + c] != (uInt32) 0x0) { - c = -1; - break; - } - } - } - if (c != -1) { - for (c = 0; c < count; c++) { - if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + ((y + c) * 4096)),PAGE_DEFAULT)) == 0x0) - kpanic("vmmRemapPage: getFreeVirtualPage-1: [0x%X]\n",((x * (1024 * 4096)) + ((y + c) * 4096))); - vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + ((y + c) * 4096))); - } - if (type == VM_THRD) - _current->td.vm_dsize += btoc(count * 0x1000); - spinUnlock(&fvpSpinLock); - return ((void *)((x * (1024 * 4096)) + (y * 4096))); - } - } else { - /* Map A Physical Page To The Virtual Page */ - - /* - * remapPage((uInt32)vmmFindFreePage(pid),((x*(1024*4096))+(y*4096)) - * ,pid); - */ - if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + (y * 4096)),PAGE_DEFAULT)) == 0x0) - kpanic("vmmRemapPage: getFreeVirtualPage-2\n"); - - /* Clear This Page So No Garbage Is There */ - vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + (y * 4096))); - - /* Return The Address Of The Newly Allocate Page */ - if (type == VM_THRD) { - _current->td.vm_dsize += btoc(count * 0x1000); - #ifdef DEBUG - kprintf("vm_dsize: [0x%X]][0x%X]\n",ctob(_current->td.vm_dsize),_current->td.vm_dsize); - #endif - } - //kprintf("(0x%X:0x%X)",_current->td.vm_dsize,vmm_getPhysicalAddr(((x * (1024 * 4096)) + (y * 4096)))); -// kprintf("(0x%X:0x%X)",_current->td.vm_dsize + _current->td.vm_daddr,((x * (1024 * 4096)) + (y * 4096))); - spinUnlock(&fvpSpinLock); - return ((void *)((x * (1024 * 4096)) + (y * 4096))); - } - } - } - } - /* If No Free Page Was Found Return NULL */ - spinUnlock(&fvpSpinLock); - return (0x0); -} - -void *vmmGetFreeVirtualPage_new(pidType pid, int count,int type,u_int32_t start_addr) { - int x = 0, y = 0, c = 0; - uInt32 *pageTableSrc = 0x0; - uInt32 *pageDir = 0x0; - uInt32 start_page = 0x0; - - - spinLock(&fvpSpinLock); - - pageDir = (uInt32 *) parentPageDirAddr; - - /* Lets Search For A Free Page */ - if (_current->oInfo.vmStart <= 0x100000) - kpanic("Invalid vmStart\n"); - - if (type == VM_THRD) { - start_page = (u_int32_t)(_current->td.vm_daddr + ctob(_current->td.vm_dsize)); - } - else if (type == VM_TASK) { - //kprintf("vmStart"); - start_page = _current->oInfo.vmStart; - } - else - K_PANIC("Invalid Type"); - -start_page = start_addr; - - //for (x = ((_current->td.vm_daddr + _current->td.vm_dsize) / (1024 * 4096)); x < 1024; x++) { - for (x = (start_page / (1024 * 4096)); x < 1024; x++) { - /* Set Page Table Address */ - if ((pageDir[x] & PAGE_PRESENT) != PAGE_PRESENT) { - /* If Page Table Is Non Existant Then Set It Up */ - pageDir[x] = (uInt32) vmmFindFreePage(_current->id) | PAGE_DEFAULT; - /* Also Add It To Virtual Space So We Can Make Changes Later */ - pageTableSrc = (uInt32 *) (tablesBaseAddress + (4096 * 767)); - pageTableSrc[x] = pageDir[x]; - y = 1; - /* Reload Page Directory */ - asm( - "movl %cr3,%eax\n" - "movl %eax,%cr3\n" - ); - } - pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); - if (y != 0x0) { - for (y = 0x0;ytd.vm_dsize += btoc(0x1000); - /* HACK MEMORY LEAK */ - //pageTableSrc[y] = 0x0; - } - if ((uInt32) pageTableSrc[y] == (uInt32) 0x0) { - if (count > 0x1) { - for (c = 0; c < count; c++) { - if (y + c < 1024) { - if ((pageTableSrc[y + c] & PAGE_COW) == PAGE_COW) { - kprintf("PAGE-COW"); - //_current->td.vm_dsize += btoc(0x1000); - /* HACK MEMORY LEAK */ - //pageTableSrc[y + c] = 0x0; - } - - if ((uInt32) pageTableSrc[y + c] != (uInt32) 0x0) { - c = -1; - break; - } - } - } - if (c != -1) { - for (c = 0; c < count; c++) { - if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + ((y + c) * 4096)),PAGE_DEFAULT)) == 0x0) - kpanic("vmmRemapPage: getFreeVirtualPage-1: [0x%X]\n",((x * (1024 * 4096)) + ((y + c) * 4096))); - vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + ((y + c) * 4096))); - } - if (type == VM_THRD) - _current->td.vm_dsize += btoc(count * 0x1000); - spinUnlock(&fvpSpinLock); - return ((void *)((x * (1024 * 4096)) + (y * 4096))); - } - } else { - /* Map A Physical Page To The Virtual Page */ - - /* - * remapPage((uInt32)vmmFindFreePage(pid),((x*(1024*4096))+(y*4096)) - * ,pid); - */ - if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + (y * 4096)),PAGE_DEFAULT)) == 0x0) - kpanic("vmmRemapPage: getFreeVirtualPage-2\n"); - - /* Clear This Page So No Garbage Is There */ - vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + (y * 4096))); - - /* Return The Address Of The Newly Allocate Page */ - if (type == VM_THRD) { - _current->td.vm_dsize += btoc(count * 0x1000); - #ifdef DEBUG - kprintf("vm_dsize: [0x%X]][0x%X]\n",ctob(_current->td.vm_dsize),_current->td.vm_dsize); - #endif - } - //kprintf("(0x%X:0x%X)",_current->td.vm_dsize,vmm_getPhysicalAddr(((x * (1024 * 4096)) + (y * 4096)))); -// kprintf("(0x%X:0x%X)",_current->td.vm_dsize + _current->td.vm_daddr,((x * (1024 * 4096)) + (y * 4096))); - spinUnlock(&fvpSpinLock); - return ((void *)((x * (1024 * 4096)) + (y * 4096))); - } - } - } - } - /* If No Free Page Was Found Return NULL */ - spinUnlock(&fvpSpinLock); - return (0x0); -} - -/*** - END - ***/ - diff --git a/src/sys/vmm/paging.c b/src/sys/vmm/paging.c index 4968c3d..de288e6 100644 --- a/src/sys/vmm/paging.c +++ b/src/sys/vmm/paging.c @@ -40,7 +40,6 @@ uInt32 *kernelPageDirectory = 0x0; - static spinLock_t fkpSpinLock = SPIN_LOCK_INITIALIZER; static spinLock_t rmpSpinLock = SPIN_LOCK_INITIALIZER; @@ -67,20 +66,21 @@ K_PANIC("Error: vmmFindFreePage Failed"); return (0x1); } /* end if */ - + /* Clear The Memory To Ensure There Is No Garbage */ for (i = 0; i < pageEntries; i++) { (uInt32) kernelPageDirectory[i] = (uInt32) 0x0; - } /* end for */ - + } /* end for */ + /* Allocate a page for the first 4MB of memory */ if ((pageTable = (uInt32 *) vmmFindFreePage(sysID)) == 0x0) K_PANIC("Error: vmmFindFreePage Failed"); - kernelPageDirectory[0] = (uInt32) ((uInt32) (pageTable) | KERNEL_PAGE_DEFAULT); - + + kernelPageDirectory[0] = (uInt32) ((uInt32) (pageTable) | KERNEL_PAGE_DEFAULT); + /* Make Sure The Page Table Is Clean */ memset(pageTable,0x0,0x1000); - + /* * Map the first 1MB of Memory to the kernel MM space because our kernel starts * at 0x30000 @@ -97,26 +97,27 @@ for (i = 768; i < pageEntries; i++) { if ((pageTable = (uInt32 *) vmmFindFreePage(sysID)) == 0x0) K_PANIC("Error: vmmFindFreePage Failed"); - + /* Make Sure The Page Table Is Clean */ memset(pageTable,0x0,0x1000); /* Map In The Page Directory */ kernelPageDirectory[i] = (uInt32) ((uInt32) (pageTable) | KERNEL_PAGE_DEFAULT); } /* end for */ - + /* Set Up Memory To Be All The Allocated Page Directories */ if ((pageTable = (uInt32 *) vmmFindFreePage(sysID)) == 0x0) K_PANIC("Error: vmmFindFreePage Failed"); - + /* Clean Page Table */ memset(pageTable,0x0,0x1000); - + kernelPageDirectory[767] = ((uInt32) pageTable | KERNEL_PAGE_DEFAULT); + for (i = 0; i < pageEntries; i++) { pageTable[i] = kernelPageDirectory[i]; } /* end for */ - + /* Also Set Up Page Directory To Be The The First Page In 0xE0400000 */ pageTable = (uInt32 *) (kernelPageDirectory[0] & 0xFFFFF000); pageTable[256] = (uInt32) ((uInt32) (kernelPageDirectory) | KERNEL_PAGE_DEFAULT); @@ -136,7 +137,8 @@ for (i = 0x101000; i <= (0x101000 + (numPages * sizeof(mMap))); i += 0x1000) { if ((vmm_remapPage(i, (vmmMemoryMapAddr + (i - 0x101000)),KERNEL_PAGE_DEFAULT)) == 0x0) K_PANIC("vmmRemapPage failed\n"); - } + } /* end for */ + /* Set New Address For Memory Map Since Its Relocation */ vmmMemoryMap = (mMap *) vmmMemoryMapAddr; @@ -145,31 +147,32 @@ /* Return so we know everything went well */ return (0x0); - } /* END */ + } /* END func */ /***************************************************************************************** Function: int vmmRemapPage(Physical Source,Virtual Destination) - + Description: This Function Will Remap A Physical Page Into Virtual Space - + Notes: 07/29/02 - Rewrote This To Work With Our New Paging System 07/30/02 - Changed Address Of Page Tables And Page Directory 07/28/04 - If perms == 0x0 set to PAGE_DEFAULT *****************************************************************************************/ -int vmm_remapPage(uInt32 source,uInt32 dest,uInt16 perms) -{ +int vmm_remapPage(uInt32 source,uInt32 dest,uInt16 perms) { uInt16 destPageDirectoryIndex = 0x0, destPageTableIndex = 0x0; uInt32 *pageDir = 0x0, *pageTable = 0x0; short i = 0x0; if (source == 0x0) K_PANIC("source == 0x0"); + if (dest == 0x0) K_PANIC("dest == 0x0"); spinLock(&rmpSpinLock); + if (perms == 0x0) perms = KERNEL_PAGE_DEFAULT; @@ -177,22 +180,25 @@ * Set Pointer pageDirectory To Point To The Virtual Mapping Of The Page * Directory */ + pageDir = (uInt32 *) parentPageDirAddr; + /* Check To See If Page Table Exists */ if (dest == 0x0) return(0x0); - + /* Get Index Into The Page Directory */ destPageDirectoryIndex = (dest / 0x400000); - + if ((pageDir[destPageDirectoryIndex] & PAGE_PRESENT) != PAGE_PRESENT) { /* If Page Table Is Non Existant Then Set It Up */ /* UBU Why does the page table need to be user writable? */ pageDir[destPageDirectoryIndex] = (uInt32) vmmFindFreePage(_current->id) | PAGE_DEFAULT; - + /* Also Add It To Virtual Space So We Can Make Changes Later */ pageTable = (uInt32 *) (tablesBaseAddress + 0x2FF000); pageTable[destPageDirectoryIndex] = pageDir[destPageDirectoryIndex]; + /* Reload Page Directory */ asm volatile( "push %eax \n" @@ -200,10 +206,14 @@ "mov %eax,%cr3 \n" "pop %eax \n" ); + pageTable = (uInt32 *) (tablesBaseAddress + (0x1000 * destPageDirectoryIndex)); + for (i = 0x0;i < pageEntries;i++) pageTable[i] = 0x0; - } + + } + /* Set Address To Page Table */ pageTable = (uInt32 *) (tablesBaseAddress + (0x1000 * destPageDirectoryIndex)); @@ -222,11 +232,14 @@ source = 0x0; goto rmDone; } + /* Clear The Page First For Security Reasons */ freePage(((uInt32) pageTable[destPageTableIndex] & 0xFFFFF000)); - } + } + /* Set The Source Address In The Destination */ pageTable[destPageTableIndex] = (uInt32) (source | perms); + /* Reload The Page Table; */ asm volatile( "push %eax \n" @@ -236,10 +249,11 @@ ); rmDone: + /* Return */ spinUnlock(&rmpSpinLock); return (source); -} + } /* end func */ /************************************************************************ @@ -250,21 +264,23 @@ 07/30/02 - This Returns A Free Page In The Top 1GB For The Kernel ************************************************************************/ -void * -vmmGetFreeKernelPage(pidType pid, uInt16 count) -{ +void *vmmGetFreeKernelPage(pidType pid, uInt16 count) { int x = 0, y = 0, c = 0; uInt32 *pageTableSrc = 0x0; spinLock(&fkpSpinLock); + /* Lets Search For A Free Page */ for (x = 768; x < 1024; x++) { + /* Set Page Table Address */ pageTableSrc = (uInt32 *) (tablesBaseAddress + (4096 * x)); + for (y = 0; y < 1024; y++) { + /* Loop Through The Page Table Find An UnAllocated Page */ if ((uInt32) pageTableSrc[y] == (uInt32) 0x0) { - if (count > 1) { + if (count > 1) { for (c = 0; c < count; c++) { if (y + c < 1024) { if ((uInt32) pageTableSrc[y + c] != (uInt32) 0x0) { @@ -273,33 +289,36 @@ } } } - if (c != -1) { - for (c = 0; c < count; c++) { - if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + ((y + c) * 4096)),KERNEL_PAGE_DEFAULT)) == 0x0) - K_PANIC("vmmRemapPage failed: gfkp-1\n"); - vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + ((y + c) * 4096))); - } - spinUnlock(&fkpSpinLock); - return ((void *)((x * (1024 * 4096)) + (y * 4096))); - } - } else { - /* Map A Physical Page To The Virtual Page */ + if (c != -1) { + for (c = 0; c < count; c++) { + if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + ((y + c) * 4096)),KERNEL_PAGE_DEFAULT)) == 0x0) + K_PANIC("vmmRemapPage failed: gfkp-1\n"); + vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + ((y + c) * 4096))); + } - if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + (y * 4096)),KERNEL_PAGE_DEFAULT)) == 0x0) - K_PANIC("vmmRemapPage failed: gfkp-2\n"); - /* Clear This Page So No Garbage Is There */ - vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + (y * 4096))); - /* Return The Address Of The Newly Allocate Page */ - spinUnlock(&fkpSpinLock); - return ((void *)((x * (1024 * 4096)) + (y * 4096))); - } + spinUnlock(&fkpSpinLock); + return ((void *)((x * (1024 * 4096)) + (y * 4096))); + } + } + else { + /* Map A Physical Page To The Virtual Page */ + if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + (y * 4096)),KERNEL_PAGE_DEFAULT)) == 0x0) + K_PANIC("vmmRemapPage failed: gfkp-2\n"); + + /* Clear This Page So No Garbage Is There */ + vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + (y * 4096))); + /* Return The Address Of The Newly Allocate Page */ + spinUnlock(&fkpSpinLock); + return ((void *)((x * (1024 * 4096)) + (y * 4096))); + } + } } } - } + /* If No Free Page Was Found Return NULL */ spinUnlock(&fkpSpinLock); return (0x0); -} + } /* end func */ /************************************************************************ @@ -550,45 +569,6 @@ return(0x0); } -int vmm_cleanVirtualSpace(u_int32_t addr) { - int x = 0x0; - int y = 0x0; - u_int32_t *pageTableSrc = 0x0; - u_int32_t *pageDir = 0x0; - - pageDir = (uInt32 *) parentPageDirAddr; - - #ifdef DEBUG - kprintf("CVS: [0x%X]\n",addr); - #endif - - for (x = (addr / (1024 * 4096)); x < 770; x++) { - if ((pageDir[x] & PAGE_PRESENT) == PAGE_PRESENT) { - pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); - for (y = 0;y < 1024;y++) { - if (pageTableSrc[y] != 0x0) { - if ((pageTableSrc[y] & PAGE_COW) == PAGE_COW) { - //kprintf("COWi*"); - pageTableSrc[y] = 0x0; - } - else if ((pageTableSrc[y] & PAGE_STACK) == PAGE_STACK) { - //pageTableSrc[y] = 0x0; - //kprintf("STACK: (%i:%i)",x,y); - } - else { - //kprintf("+"); - } - } - } - } - } - asm( - "movl %cr3,%eax\n" - "movl %eax,%cr3\n" - ); - return(0x0); - } - /*** END ***/ diff --git a/src/sys/vmm/vmm_virtual.c b/src/sys/vmm/vmm_virtual.c new file mode 100644 index 0000000..1f0ff22 --- /dev/null +++ b/src/sys/vmm/vmm_virtual.c @@ -0,0 +1,609 @@ +/***************************************************************************************** + Copyright (c) 2002-2004,2005,2006,2007 The UbixOS Project + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are + permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this list of + conditions, the following disclaimer and the list of authors. Redistributions in binary + form must reproduce the above copyright notice, this list of conditions, the following + disclaimer and the list of authors in the documentation and/or other materials provided + with the distribution. Neither the name of the UbixOS Project nor the names of its + contributors may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + $Id$ + +*****************************************************************************************/ + +#include +#include +#include +#include +#include +#include + +int vmm_cleanVirtualSpace(u_int32_t addr) { + int x = 0x0; + int y = 0x0; + u_int32_t *pageTableSrc = 0x0; + u_int32_t *pageDir = 0x0; + + pageDir = (uInt32 *) parentPageDirAddr; + + #ifdef VMMDEBUG + kprintf("CVS: [0x%X]\n",addr); + #endif + + /* Loop through the users virtual space flushing out COW pages */ + /* BUG memory leak this does not update COW counter on master page */ + for (x = (addr / (1024 * 4096)); x < 770; x++) { + if ((pageDir[x] & PAGE_PRESENT) == PAGE_PRESENT) { + pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); + for (y = 0;y < 1024;y++) { + if (pageTableSrc[y] != 0x0) { + if ((pageTableSrc[y] & PAGE_COW) == PAGE_COW) { + //kprintf("COWi*"); + pageTableSrc[y] = 0x0; + } + else if ((pageTableSrc[y] & PAGE_STACK) == PAGE_STACK) { + //pageTableSrc[y] = 0x0; + //kprintf("STACK: (%i:%i)",x,y); + } + else { + //kprintf("+"); + } + } + } + } + } + + /* we must now reload the page directory */ + asm( + "movl %cr3,%eax\n" + "movl %eax,%cr3\n" + ); + + return(0x0); + } /* end func */ + +/************************************************************************ + +Function: void *vmmGetFreeVirtualPage(pidType pid,int count); +Description: Returns A Free Page Mapped To The VM Space +Notes: + +08/11/02 - This Will Return Next Avilable Free Page Of Tasks VM Space + +************************************************************************/ +static spinLock_t fvpSpinLock = SPIN_LOCK_INITIALIZER; + +void *vmmGetFreeVirtualPage(pidType pid, int count,int type) { + int x = 0, y = 0, c = 0; + uInt32 *pageTableSrc = 0x0; + uInt32 *pageDir = 0x0; + uInt32 start_page = 0x0; + + + spinLock(&fvpSpinLock); + + pageDir = (uInt32 *)PARENT_PAGEDIR_ADDR; + + /* Lets Search For A Free Page */ + if (_current->oInfo.vmStart <= 0x100000) + K_PANIC("Invalid vmStart\n"); + + + /* Set starting page based on page allocation type */ + if (type == VM_THRD) { + start_page = (u_int32_t)(_current->td.vm_daddr + ctob(_current->td.vm_dsize)); + #ifdef DEBUG + kprintf(".%i.",count); + #endif + //count--; + } + else if (type == VM_TASK) { + //kprintf("vmStart"); + start_page = _current->oInfo.vmStart; + } + else + K_PANIC("Invalid Type"); + + for (x = (start_page / (1024 * 4096)); x < 1024; x++) { + + /* Set Page Table Address */ + if ((pageDir[x] & PAGE_PRESENT) != PAGE_PRESENT) { + + /* If Page Table Is Non Existant Then Set It Up */ + pageDir[x] = (uInt32) vmmFindFreePage(_current->id) | PAGE_DEFAULT; + + /* Also Add It To Virtual Space So We Can Make Changes Later */ + pageTableSrc = (uInt32 *) (tablesBaseAddress + (4096 * 767)); + pageTableSrc[x] = pageDir[x]; + y = 1; + + /* Reload Page Directory */ + asm( + "movl %cr3,%eax\n" + "movl %eax,%cr3\n" + ); + } + + pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); + + if (y != 0x0) { + for (y = 0x0;ytd.vm_dsize += btoc(0x1000); + /* BUG MEMORY LEAK */ + //pageTableSrc[y] = 0x0; + } + + if ((uInt32) pageTableSrc[y] == (uInt32) 0x0) { + + if (count > 0x1) { + + for (c = 0; c < count; c++) { + + if (y + c < 1024) { + + if ((pageTableSrc[y + c] & PAGE_COW) == PAGE_COW) { + #ifdef VMMDEBUG + kprintf("PAGE-COW-2"); + #endif + //_current->td.vm_dsize += btoc(0x1000); + /* BUG MEMORY LEAK */ + //pageTableSrc[y + c] = 0x0; + } + if ((uInt32) pageTableSrc[y + c] != (uInt32) 0x0) { + c = -1; + break; + } + } + } + if (c != -1) { + for (c = 0; c < count; c++) { + if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + ((y + c) * 4096)),PAGE_DEFAULT)) == 0x0) + kpanic("vmmRemapPage: getFreeVirtualPage-1: [0x%X]\n",((x * (1024 * 4096)) + ((y + c) * 4096))); + vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + ((y + c) * 4096))); + } + if (type == VM_THRD) + _current->td.vm_dsize += btoc(count * 0x1000); + spinUnlock(&fvpSpinLock); + return ((void *)((x * (1024 * 4096)) + (y * 4096))); + } + } + else { + /* Map A Physical Page To The Virtual Page */ + + /* + * remapPage((uInt32)vmmFindFreePage(pid),((x*(1024*4096))+(y*4096)) + * ,pid); + */ + if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + (y * 4096)),PAGE_DEFAULT)) == 0x0) + kpanic("vmmRemapPage: getFreeVirtualPage-2\n"); + + /* Clear This Page So No Garbage Is There */ + vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + (y * 4096))); + + /* Return The Address Of The Newly Allocate Page */ + if (type == VM_THRD) { + _current->td.vm_dsize += btoc(count * 0x1000); + #ifdef VMMDEBUG + kprintf("vm_dsize: [0x%X]][0x%X]\n",ctob(_current->td.vm_dsize),_current->td.vm_dsize); + #endif + } + //kprintf("(0x%X:0x%X)",_current->td.vm_dsize,vmm_getPhysicalAddr(((x * (1024 * 4096)) + (y * 4096)))); +// kprintf("(0x%X:0x%X)",_current->td.vm_dsize + _current->td.vm_daddr,((x * (1024 * 4096)) + (y * 4096))); + spinUnlock(&fvpSpinLock); + return ((void *)((x * (1024 * 4096)) + (y * 4096))); + } + } + } + } + + /* If No Free Page Was Found Return NULL */ + spinUnlock(&fvpSpinLock); + return (0x0); + } /* end func */ + +void *vmmGetFreeVirtualPage_new(pidType pid, int count,int type,u_int32_t start_addr) { + int x = 0, y = 0, c = 0; + uInt32 *pageTableSrc = 0x0; + uInt32 *pageDir = 0x0; + uInt32 start_page = 0x0; + + + spinLock(&fvpSpinLock); + + pageDir = (uInt32 *) parentPageDirAddr; + + /* Lets Search For A Free Page */ + if (_current->oInfo.vmStart <= 0x100000) + kpanic("Invalid vmStart\n"); + + if (type == VM_THRD) { + start_page = (u_int32_t)(_current->td.vm_daddr + ctob(_current->td.vm_dsize)); + } + else if (type == VM_TASK) { + //kprintf("vmStart"); + start_page = _current->oInfo.vmStart; + } + else + K_PANIC("Invalid Type"); + +start_page = start_addr; + + //for (x = ((_current->td.vm_daddr + _current->td.vm_dsize) / (1024 * 4096)); x < 1024; x++) { + for (x = (start_page / (1024 * 4096)); x < 1024; x++) { + /* Set Page Table Address */ + if ((pageDir[x] & PAGE_PRESENT) != PAGE_PRESENT) { + /* If Page Table Is Non Existant Then Set It Up */ + pageDir[x] = (uInt32) vmmFindFreePage(_current->id) | PAGE_DEFAULT; + /* Also Add It To Virtual Space So We Can Make Changes Later */ + pageTableSrc = (uInt32 *) (tablesBaseAddress + (4096 * 767)); + pageTableSrc[x] = pageDir[x]; + y = 1; + /* Reload Page Directory */ + asm( + "movl %cr3,%eax\n" + "movl %eax,%cr3\n" + ); + } + pageTableSrc = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); + if (y != 0x0) { + for (y = 0x0;ytd.vm_dsize += btoc(0x1000); + /* HACK MEMORY LEAK */ + //pageTableSrc[y] = 0x0; + } + if ((uInt32) pageTableSrc[y] == (uInt32) 0x0) { + if (count > 0x1) { + for (c = 0; c < count; c++) { + if (y + c < 1024) { + if ((pageTableSrc[y + c] & PAGE_COW) == PAGE_COW) { + kprintf("PAGE-COW"); + //_current->td.vm_dsize += btoc(0x1000); + /* HACK MEMORY LEAK */ + //pageTableSrc[y + c] = 0x0; + } + + if ((uInt32) pageTableSrc[y + c] != (uInt32) 0x0) { + c = -1; + break; + } + } + } + if (c != -1) { + for (c = 0; c < count; c++) { + if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + ((y + c) * 4096)),PAGE_DEFAULT)) == 0x0) + kpanic("vmmRemapPage: getFreeVirtualPage-1: [0x%X]\n",((x * (1024 * 4096)) + ((y + c) * 4096))); + vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + ((y + c) * 4096))); + } + if (type == VM_THRD) + _current->td.vm_dsize += btoc(count * 0x1000); + spinUnlock(&fvpSpinLock); + return ((void *)((x * (1024 * 4096)) + (y * 4096))); + } + } else { + /* Map A Physical Page To The Virtual Page */ + + /* + * remapPage((uInt32)vmmFindFreePage(pid),((x*(1024*4096))+(y*4096)) + * ,pid); + */ + if ((vmm_remapPage((uInt32) vmmFindFreePage(pid), ((x * (1024 * 4096)) + (y * 4096)),PAGE_DEFAULT)) == 0x0) + kpanic("vmmRemapPage: getFreeVirtualPage-2\n"); + + /* Clear This Page So No Garbage Is There */ + vmmClearVirtualPage((uInt32) ((x * (1024 * 4096)) + (y * 4096))); + + /* Return The Address Of The Newly Allocate Page */ + if (type == VM_THRD) { + _current->td.vm_dsize += btoc(count * 0x1000); + #ifdef DEBUG + kprintf("vm_dsize: [0x%X]][0x%X]\n",ctob(_current->td.vm_dsize),_current->td.vm_dsize); + #endif + } + //kprintf("(0x%X:0x%X)",_current->td.vm_dsize,vmm_getPhysicalAddr(((x * (1024 * 4096)) + (y * 4096)))); +// kprintf("(0x%X:0x%X)",_current->td.vm_dsize + _current->td.vm_daddr,((x * (1024 * 4096)) + (y * 4096))); + spinUnlock(&fvpSpinLock); + return ((void *)((x * (1024 * 4096)) + (y * 4096))); + } + } + } + } + /* If No Free Page Was Found Return NULL */ + spinUnlock(&fvpSpinLock); + return (0x0); +} + +/************************************************************************ + +Function: void *vmmCopyVirtualSpace(pidType pid); + +Description: Creates A Copy Of A Virtual Space And Set All NON Kernel + Space To COW For A Fork This Will Also Alter The Parents + VM Space To Make That COW As Well + +Notes: + +08/02/02 - Added Passing Of pidType pid So We Can Better Keep Track Of + Which Task Has Which Physical Pages + +************************************************************************/ +static spinLock_t cvsSpinLock = SPIN_LOCK_INITIALIZER; + +void *vmmCopyVirtualSpace(pidType pid) { + void *newPageDirectoryAddress = 0x0; + uInt32 *parentPageDirectory = 0x0, *newPageDirectory = 0x0; + uInt32 *parentPageTable = 0x0, *newPageTable = 0x0; + uInt32 *parentStackPage = 0x0, *newStackPage = 0x0; + uInt16 x = 0, i = 0, s = 0; + + spinLock(&cvsSpinLock); + + /* Set Address Of Parent Page Directory */ + parentPageDirectory = (uInt32 *) parentPageDirAddr; + /* Allocate A New Page For The New Page Directory */ + if ((newPageDirectory = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) + kpanic("Error: newPageDirectory == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); + + /* Set newPageDirectoryAddress To The Newly Created Page Directories Page */ + newPageDirectoryAddress = (void *)vmm_getPhysicalAddr((uInt32) newPageDirectory); + + /* First Set Up A Flushed Page Directory */ + memset(newPageDirectory,0x0,0x1000); + + /* Map The Top 1GB Region Of The VM Space */ + for (x = 768; x < pageEntries; x++) { + newPageDirectory[x] = parentPageDirectory[x]; + } + + /* + * Now For The Fun Stuff For Page Tables 1-766 We Must Map These And Set + * The Permissions On Every Mapped Pages To COW This Will Conserve Memory + * Because The Two VM Spaces Will Be Sharing Some Pages + */ + for (x = 0x1; x <= 766; x++) { + /* If Page Table Exists Map It */ + if (parentPageDirectory[x] != 0) { + /* Set Parent To Propper Page Table */ + parentPageTable = (uInt32 *) (tablesBaseAddress + (0x1000 * x)); + /* Allocate A New Page Table */ + if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) + kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); + + /* Set Parent And New Pages To COW */ + for (i = 0; i < pageEntries; i++) { + + /* If Page Is Mapped */ + if ((parentPageTable[i] & 0xFFFFF000) != 0x0) { + /* Check To See If Its A Stack Page */ + if (((uInt32) parentPageTable[i] & PAGE_STACK) == PAGE_STACK) { + /* Alloc A New Page For This Stack Page */ + if ((newStackPage = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) + kpanic("Error: newStackPage == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); + + /* Set Pointer To Parents Stack Page */ + parentStackPage = (uInt32 *) (((1024 * 4096) * x) + (4096 * i)); + + /* Copy The Tack Byte For Byte (I Should Find A Faster Way) */ + for (s = 0x0; s < pageEntries; s++) { + newStackPage[s] = parentStackPage[s]; + } + /* Insert New Stack Into Page Table */ + newPageTable[i] = (vmm_getPhysicalAddr((uInt32) newStackPage) | PAGE_DEFAULT | PAGE_STACK); + /* Unmap From Kernel Space */ + vmmUnmapPage((uInt32) newStackPage, 1); + } + else { + /* Set Page To COW In Parent And Child Space */ + newPageTable[i] = (((uInt32) parentPageTable[i] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW)); + /* Increment The COW Counter For This Page */ + if (((uInt32) parentPageTable[i] & PAGE_COW) == PAGE_COW) { + adjustCowCounter(((uInt32) parentPageTable[i] & 0xFFFFF000), 1); + } + else { + adjustCowCounter(((uInt32) parentPageTable[i] & 0xFFFFF000), 2); + parentPageTable[i] = newPageTable[i]; + } + } + } + else { + newPageTable[i] = (uInt32) 0x0; + } + } + + /* Put New Page Table Into New Page Directory */ + newPageDirectory[x] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT); + /* Unmap Page From Kernel Space But Keep It Marked As Not Avail */ + vmmUnmapPage((uInt32) newPageTable, 1); + } else { + newPageDirectory[x] = (uInt32) 0x0; + } + } + /* + * Allocate A New Page For The The First Page Table Where We Will Map The + * Lower Region + */ + if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) + kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); + + /* Flush The Page From Garbage In Memory */ + memset(newPageTable,0x0,0x1000); + + /* Map This Into The Page Directory */ + newPageDirectory[0] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT); + /* Set Address Of Parents Page Table */ + parentPageTable = (uInt32 *) tablesBaseAddress; + /* Map The First 1MB Worth Of Pages */ + for (x = 0; x < (pageEntries / 4); x++) { + newPageTable[x] = parentPageTable[x]; + } + /* Map The Next 3MB Worth Of Pages But Make Them COW */ + for (x = (pageEntries / 4) + 1; x < pageEntries; x++) { + /* If Page Is Avaiable Map It */ + if ((parentPageTable[x] & 0xFFFFF000) != 0x0) { + /* Set Pages To COW */ + newPageTable[x] = (((uInt32) parentPageTable[x] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW)); + /* Increment The COW Counter For This Page */ + if (((uInt32) parentPageTable[x] & PAGE_COW) == PAGE_COW) { + adjustCowCounter(((uInt32) parentPageTable[x] & 0xFFFFF000), 1); + } else { + adjustCowCounter(((uInt32) parentPageTable[x] & 0xFFFFF000), 2); + parentPageTable[x] = newPageTable[x]; + } + } else { + newPageTable[x] = (uInt32) 0x0; + } + } + /* Set Virtual Mapping For Page Directory */ + newPageTable[256] = (vmm_getPhysicalAddr((uInt32) newPageDirectory) | PAGE_DEFAULT); + + /* + * Now The Fun Stuff Build The Initial Virtual Page Space So We Don't Have + * To Worry About Mapping Them In Later How Ever I'm Concerned This May + * Become A Security Issue + */ + /* First Lets Unmap The Previously Allocated Page Table */ + vmmUnmapPage((uInt32) newPageTable, 1); + /* Allocate A New Page Table */ + if ((newPageTable = (uInt32 *) vmmGetFreeKernelPage(pid,1)) == 0x0) + kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n",__FILE__,__LINE__); + /* First Set Our Page Directory To Contain This */ + newPageDirectory[767] = vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT; + /* Now Lets Build The Page Table */ + for (x = 0; x < pageEntries; x++) { + newPageTable[x] = newPageDirectory[x]; + } + /* Now We Are Done So Lets Unmap This Page */ + vmmUnmapPage((uInt32) newPageTable, 1); + /* Now We Are Done With The Page Directory So Lets Unmap That Too */ + vmmUnmapPage((uInt32) newPageDirectory, 1); + + spinUnlock(&cvsSpinLock); + + /* Return Physical Address Of Page Directory */ + return (newPageDirectoryAddress); + } /* end func */ + +/************************************************************************ + +Function: void *vmmCreateVirtualSpace(pid_t); +Description: Creates A Virtual Space For A New Task +Notes: + +07/30/02 - This Is Going To Create A New VM Space However Its Going To + Share The Same Top 1GB Space With The Kernels VM And Lower + 1MB Of VM Space With The Kernel + +07/30/02 - Note This Is Going To Get The Top 1Gig And Lower 1MB Region + From The Currently Loaded Page Directory This Is Safe Because + All VM Spaces Will Share These Regions + +07/30/02 - Note I Realized A Mistake The First Page Table Will Need To Be + A Copy But The Page Tables For The Top 1GB Will Not Reason For + This Is That We Just Share The First 1MB In The First Page Table + So We Will Just Share Physical Pages. + +08/02/02 - Added Passing Of pid_t pid For Better Tracking Of Who Has Which + Set Of Pages + +************************************************************************/ +void * +vmmCreateVirtualSpace(pid_t pid) +{ + void *newPageDirectoryAddress = 0x0; + uInt32 *parentPageDirectory = 0x0, *newPageDirectory = 0x0; + uInt32 *parentPageTable = 0x0, *newPageTable = 0x0; + int x = 0; + + /* Set Address Of Parent Page Directory */ + parentPageDirectory = (uInt32 *) parentPageDirAddr; + /* Allocate A New Page For The New Page Directory */ + newPageDirectory = (uInt32 *) vmmGetFreePage(pid); + /* Set newPageDirectoryAddress To The Newly Created Page Directories Page */ + newPageDirectoryAddress = (void *)vmm_getPhysicalAddr((uInt32) newPageDirectory); + /* First Set Up A Flushed Page Directory */ + for (x = 0; x < pageEntries; x++) { + (uInt32) newPageDirectory[x] = (uInt32) 0x0; + } + /* Map The Top 1GB Region Of The VM Space */ + for (x = 768; x < pageEntries; x++) { + newPageDirectory[x] = parentPageDirectory[x]; + } + /* + * Allocate A New Page For The The First Page Table Where We Will Map The + * Lower Region + */ + newPageTable = (uInt32 *) vmmGetFreePage(pid); + /* Flush The Page From Garbage In Memory */ + for (x = 0; x < pageEntries; x++) { + (uInt32) newPageTable[x] = (uInt32) 0x0; + } + /* Map This Into The Page Directory */ + newPageDirectory[0] = (vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT); + /* Set Address Of Parents Page Table */ + parentPageTable = (uInt32 *) tablesBaseAddress; + /* Map The First 1MB Worth Of Pages */ + for (x = 0; x < (pageEntries / 4); x++) { + newPageTable[x] = parentPageTable[x]; + } + /* Set Virtual Mapping For Page Directory */ + newPageTable[256] = (vmm_getPhysicalAddr((uInt32) newPageDirectory) | PAGE_DEFAULT); + + /* + * Now The Fun Stuff Build The Initial Virtual Page Space So We Don't Have + * To Worry About Mapping Them In Later How Ever I'm Concerned This May + * Become A Security Issue + */ + /* First Lets Unmap The Previously Allocated Page Table */ + vmmUnmapPage((uInt32) newPageTable, 1); + /* Allocate A New Page Table */ + newPageTable = (uInt32 *) vmmGetFreePage(pid); + /* First Set Our Page Directory To Contain This */ + newPageDirectory[767] = vmm_getPhysicalAddr((uInt32) newPageTable) | PAGE_DEFAULT; + /* Now Lets Build The Page Table */ + for (x = 0; x < pageEntries; x++) { + newPageTable[x] = newPageDirectory[x]; + } + /* Now We Are Done So Lets Unmap This Page */ + vmmUnmapPage((uInt32) newPageTable, 1); + /* Now We Are Done With The Page Directory So Lets Unmap That Too */ + vmmUnmapPage((uInt32) newPageDirectory, 1); + /* Return Physical Address Of Page Directory */ + return (newPageDirectoryAddress); + } /* end func */ + +/* + END + */ diff --git a/ubixos.kdevelop.filelist b/ubixos.kdevelop.filelist index 9acda16..2bbd436 100644 --- a/ubixos.kdevelop.filelist +++ b/ubixos.kdevelop.filelist @@ -7,3 +7,6 @@ src/sys/kernel/tty.c src/sys/vmm/getfreevirtualpage.c src/sys/kernel/exec.c +src/sys/vmm/vmm_virtual.c +src/sys/include/vmm/vmm.h +src/sys/include/vmm/paging.h