diff --git a/sys/include/vmm/paging.h b/sys/include/vmm/paging.h index 6269e46..4cd0b78 100644 --- a/sys/include/vmm/paging.h +++ b/sys/include/vmm/paging.h @@ -76,8 +76,6 @@ int vmmClearVirtualPage(uint32_t pageAddr); -void vmm_unmapPage(uint32_t, int); -void vmm_unmapPages(void *, uint32_t); void *vmm_mapFromTask(pidType, void *, uint32_t); void *vmm_copyVirtualSpace(pidType); void *vmm_getFreePage(pidType); diff --git a/sys/include/vmm/vmm.h b/sys/include/vmm/vmm.h index 009c0a3..bb769b1 100644 --- a/sys/include/vmm/vmm.h +++ b/sys/include/vmm/vmm.h @@ -107,6 +107,10 @@ int cowCounter; } mMap; + typedef enum { + VMM_FREE = 0, VMM_KEEP = 1 + } unmapFlags_t; + extern int numPages; extern mMap *vmmMemoryMap; @@ -114,11 +118,13 @@ int vmm_memMapInit(); int countMemory(); uint32_t vmm_findFreePage(pidType pid); - int freePage(uInt32 pageAddr); - int adjustCowCounter(uInt32 baseAddr, int adjustment); + int freePage(uint32_t pageAddr); + int adjustCowCounter(uint32_t baseAddr, int adjustment); void vmm_freeProcessPages(pidType pid); int vmm_allocPageTable(uint32_t, pidType); + void vmm_unmapPage(uint32_t, unmapFlags_t); + void vmm_unmapPages(void *, uint32_t, unmapFlags_t); #ifdef __cplusplus } diff --git a/sys/vmm/copyvirtualspace.c b/sys/vmm/copyvirtualspace.c index 87f7716..88fd4e7 100644 --- a/sys/vmm/copyvirtualspace.c +++ b/sys/vmm/copyvirtualspace.c @@ -57,7 +57,6 @@ uint32_t *parentStackPage = 0x0, *newStackPage = 0x0; uint16_t x = 0, i = 0, s = 0; - spinLock(&cvsSpinLock); /* Set Address Of Parent Page Directory */ @@ -82,8 +81,26 @@ parentPageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * 1)); - for (x = 0;x < PT_ENTRIES;x++) - newPageTable[x] = parentPageTable[x]; + for (x = 0; x < PT_ENTRIES; x++) { + if (((parentPageTable[x]) & PAGE_PRESENT) == PAGE_PRESENT) { + + /* Set Page To COW In Parent And Child Space */ + newPageTable[x] = (((uint32_t) parentPageTable[x] & 0xFFFFF000) | (KERNEL_PAGE_DEFAULT | PAGE_COW)); + + /* Increment The COW Counter For This Page */ + if (((uint32_t) parentPageTable[x] & PAGE_COW) == PAGE_COW) { + adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 1); + } + else { + /* Add Two If This Is The First Time Setting To COW */ + adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 2); + parentPageTable[x] |= PAGE_COW; // newPageTable[i]; + } + + } + else + newPageTable[x] = parentPageTable[x]; + } newPageDirectory[1] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | KERNEL_PAGE_DEFAULT); @@ -91,8 +108,6 @@ newPageTable = 0x0; - - /* Map The Kernel Memory Region Entry 770 Address 0xC0800000 */ for (x = PD_INDEX(VMM_KERN_START); x <= PD_INDEX(VMM_KERN_END); x++) newPageDirectory[x] = parentPageDirectory[x]; @@ -112,21 +127,21 @@ for (i = 0; i < PT_ENTRIES; i++) { if ((parentPageTable[i] & PAGE_PRESENT) == PAGE_PRESENT) { - /* Alloc A New Page For This Stack Page */ - if ((newStackPage = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) - kpanic("Error: newStackPage == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); + /* Alloc A New Page For This Stack Page */ + if ((newStackPage = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) + kpanic("Error: newStackPage == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); - /* Set Pointer To Parents Stack Page */ - parentStackPage = (uint32_t *) (((PAGE_SIZE * PD_ENTRIES) * x) + (PAGE_SIZE * i)); + /* Set Pointer To Parents Stack Page */ + parentStackPage = (uint32_t *) (((PAGE_SIZE * PD_ENTRIES) * x) + (PAGE_SIZE * i)); - /* Copy The Stack Byte For Byte (I Should Find A Faster Way) */ - memcpy(newStackPage, parentStackPage, PAGE_SIZE); + /* Copy The Stack Byte For Byte (I Should Find A Faster Way) */ + memcpy(newStackPage, parentStackPage, PAGE_SIZE); - /* Insert New Stack Into Page Table */ - newPageTable[i] = (vmm_getPhysicalAddr((uint32_t) newStackPage) | PAGE_DEFAULT | PAGE_STACK); + /* Insert New Stack Into Page Table */ + newPageTable[i] = (vmm_getPhysicalAddr((uint32_t) newStackPage) | PAGE_DEFAULT | PAGE_STACK); - /* Unmap From Kernel Space */ - vmm_unmapPage((uint32_t) newStackPage, 1); + /* Unmap From Kernel Space */ + vmm_unmapPage((uint32_t) newStackPage, 1); } } /* Put New Page Table Into New Page Directory */ @@ -217,52 +232,52 @@ * Lower Region First 4MB */ /* - if ((newPageTable = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) - kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); + if ((newPageTable = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) + kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); */ /* Flush The Page From Garbage In Memory */ /* - bzero(newPageTable, PAGE_SIZE); + bzero(newPageTable, PAGE_SIZE); */ /* Map This Into The Page Directory */ /* - newPageDirectory[0] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | PAGE_DEFAULT); + newPageDirectory[0] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | PAGE_DEFAULT); */ /* Set Address Of Parents Page Table */ /* - parentPageTable = (uint32_t) PT_BASE_ADDR; + parentPageTable = (uint32_t) PT_BASE_ADDR; */ /* Map The First 1MB Worth Of Pages */ /* - for (x = 0; x < (PD_ENTRIES / 4); x++) { - newPageTable[x] = parentPageTable[x]; - } + for (x = 0; x < (PD_ENTRIES / 4); x++) { + newPageTable[x] = parentPageTable[x]; + } */ /* Map The Next 3MB Worth Of Pages But Make Them COW */ /* - for (x = (PD_ENTRIES / 4); x < PD_ENTRIES; x++) { + for (x = (PD_ENTRIES / 4); x < PD_ENTRIES; x++) { // If Page Is Avaiable Map It - if ((parentPageTable[x] & 0xFFFFF000) != 0x0) { + if ((parentPageTable[x] & 0xFFFFF000) != 0x0) { // Set Pages To COW - newPageTable[x] = (((uint32_t) parentPageTable[x] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW)); + newPageTable[x] = (((uint32_t) parentPageTable[x] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW)); // Increment The COW Counter For This Page - if (((uint32_t) parentPageTable[x] & PAGE_COW) == PAGE_COW) { - adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 1); - } - else { - adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 2); - parentPageTable[x] = newPageTable[x]; - } - } - } + if (((uint32_t) parentPageTable[x] & PAGE_COW) == PAGE_COW) { + adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 1); + } + else { + adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 2); + parentPageTable[x] = newPageTable[x]; + } + } + } */ /* diff --git a/sys/vmm/createvirtualspace.c b/sys/vmm/createvirtualspace.c index a7e64c7..8dad1d2 100644 --- a/sys/vmm/createvirtualspace.c +++ b/sys/vmm/createvirtualspace.c @@ -78,10 +78,28 @@ newPageTable = (uint32_t *) vmm_getFreePage(pid); bzero(newPageTable, PAGE_SIZE); - parentPageTable = (uint32_t *)(PT_BASE_ADDR + (PAGE_SIZE * 1)); + parentPageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * 1)); for (x = 0; x < PT_ENTRIES; x++) { - newPageTable[x] = parentPageTable[x]; + if (((parentPageTable[x]) & PAGE_PRESENT) == PAGE_PRESENT) { + + /* Set Page To COW In Parent And Child Space */ + newPageTable[x] = (((uint32_t) parentPageTable[x] & 0xFFFFF000) | (KERNEL_PAGE_DEFAULT | PAGE_COW)); + + /* Increment The COW Counter For This Page */ + if (((uint32_t) parentPageTable[x] & PAGE_COW) == PAGE_COW) { + adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 1); + } + else { + /* Add Two If This Is The First Time Setting To COW */ + adjustCowCounter(((uint32_t) parentPageTable[x] & 0xFFFFF000), 2); + parentPageTable[x] |= PAGE_COW; // newPageTable[i]; + } + + } + else + newPageTable[x] = parentPageTable[x]; + } newPageDirectory[1] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | KERNEL_PAGE_DEFAULT); @@ -99,42 +117,35 @@ newPageDirectory[1023] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | KERNEL_PAGE_DEFAULT); - parentPageTable = (uint32_t *)(PT_BASE_ADDR + (PAGE_SIZE * 1023)); + parentPageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * 1023)); newPageTable[1023] = parentPageTable[1023] | PAGE_COW; adjustCowCounter(((uint32_t) parentPageTable[1023] & 0xFFFFF000), 2); newPageTable[1022] = parentPageTable[1022] | PAGE_COW; adjustCowCounter(((uint32_t) parentPageTable[1022] & 0xFFFFF000), 2); - vmm_unmapPage((uint32_t) newPageTable, 1); - /* * Allocate A New Page For The The First Page Table Where We Will Map The * Lower Region */ //newPageTable = (uint32_t *) vmm_getFreePage(pid); - /* Flush The Page From Garbage In Memory */ //bzero(newPageTable, PAGE_SIZE); - /* Map This Into The Page Directory */ //newPageDirectory[0] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | KERNEL_PAGE_DEFAULT); //MrOlsen 2018-01-14 PAGE_DEFAULT - /* Set Address Of Parents Page Table */ //parentPageTable = (uint32_t *) PT_BASE_ADDR; - /* Map The First 1MB Worth Of Pages */ /* - for (x = 0; x < (PD_ENTRIES / 4); x++) { - newPageTable[x] = parentPageTable[x]; - } + for (x = 0; x < (PD_ENTRIES / 4); x++) { + newPageTable[x] = parentPageTable[x]; + } */ /* Unmap Page From Virtual Space */ //vmm_unmapPage((uint32_t) newPageTable, 1); - /* * * Map Page Directory Into VM Space @@ -143,7 +154,7 @@ */ newPageTable = (uint32_t *) vmm_getFreePage(pid); - newPageDirectory[PD_INDEX(PD_BASE_ADDR)] = (uint32_t) (vmm_getPhysicalAddr((uint32_t) newPageTable) | KERNEL_PAGE_DEFAULT ); //MrOlsen 2018-01-14 PAGE_DEFAULT + newPageDirectory[PD_INDEX(PD_BASE_ADDR)] = (uint32_t) (vmm_getPhysicalAddr((uint32_t) newPageTable) | KERNEL_PAGE_DEFAULT); //MrOlsen 2018-01-14 PAGE_DEFAULT newPageTable[0] = (uint32_t) ((uint32_t) (newPageDirectoryAddress) | KERNEL_PAGE_DEFAULT); //MrOlsen 2018-01-14 PAGE_DEFAULT diff --git a/sys/vmm/unmappage.c b/sys/vmm/unmappage.c index 21fd215..dd77cb0 100644 --- a/sys/vmm/unmappage.c +++ b/sys/vmm/unmappage.c @@ -45,7 +45,7 @@ To Create A New Virtual Space So Now It Has A Flag ************************************************************************/ -void vmm_unmapPage(uint32_t pageAddr, int flags) { +void vmm_unmapPage(uint32_t pageAddr, unmapFlags_t flags) { int pageDirectoryIndex = 0, pageTableIndex = 0; uint32_t *pageTable = 0x0; uint32_t *pageDirectory = 0x0; @@ -65,12 +65,8 @@ pageTable = (uint32_t *) (PT_BASE_ADDR + (0x1000 * pageDirectoryIndex)); /* Free The Physical Page If Flags Is 0 */ - if (flags == 0) { - - // FIXME This is temp i think its still an issue clearVirtualPage(pageAddr); - //freePage((uInt32)(pageTable[pageTableIndex] & 0xFFFFF000)); - - } + if (flags == 0) + freePage((uint32_t) (pageTable[pageTableIndex] & 0xFFFFF000)); /* Unmap The Page */ pageTable[pageTableIndex] = 0x0; @@ -102,7 +98,7 @@ To Create A New Virtual Space So Now It Has A Flag ************************************************************************/ -void vmm_unmapPages(void *ptr, uint32_t size) { +void vmm_unmapPages(void *ptr, uint32_t size, unmapFlags_t flags) { uInt32 baseAddr = (uInt32) ptr & 0xFFFFF000; uInt32 dI = 0x0, tI = 0x0; uInt32 y = 0x0; diff --git a/sys/vmm/vmm_memory.c b/sys/vmm/vmm_memory.c index 4dc8f35..56e2ac8 100644 --- a/sys/vmm/vmm_memory.c +++ b/sys/vmm/vmm_memory.c @@ -43,6 +43,7 @@ static struct spinLock vmmCowSpinLock = SPIN_LOCK_INITIALIZER; int numPages = 0x0; + mMap *vmmMemoryMap = (mMap *) VMM_MMAP_ADDR_RMODE; /************************************************************************ @@ -266,7 +267,6 @@ int pageIndex = 0x0; assert((pageAddr & 0xFFF) == 0x0); - spinLock(&vmmSpinLock); /* Find The Page Index To The Memory Map */ pageIndex = (pageAddr / 4096); @@ -275,20 +275,19 @@ if (vmmMemoryMap[pageIndex].cowCounter == 0) { /* Set Page As Avail So It Can Be Used Again */ + spinLock(&vmmSpinLock); vmmMemoryMap[pageIndex].status = memAvail; vmmMemoryMap[pageIndex].cowCounter = 0x0; vmmMemoryMap[pageIndex].pid = -2; freePages++; systemVitals->freePages = freePages; + spinUnlock(&vmmSpinLock); } else { - /* Adjust The COW Counter */ adjustCowCounter(((uint32_t) vmmMemoryMap[pageIndex].pageAddr), -1); - } - spinUnlock(&vmmSpinLock); /* Return */ return (0); @@ -307,9 +306,12 @@ ************************************************************************/ int adjustCowCounter(uInt32 baseAddr, int adjustment) { - int vmmMemoryMapIndex = (baseAddr / 4096); + + int vmmMemoryMapIndex = (baseAddr / PAGE_SIZE); + assert((baseAddr & 0xFFF) == 0x0); - spinLock(&vmmCowSpinLock); + + spinLock(&vmmSpinLock); /* Adjust COW Counter */ vmmMemoryMap[vmmMemoryMapIndex].cowCounter += adjustment; @@ -325,7 +327,7 @@ systemVitals->freePages = freePages; } - spinUnlock(&vmmCowSpinLock); + spinUnlock(&vmmSpinLock); /* Return */ return (0); } @@ -383,8 +385,11 @@ freePages++; systemVitals->freePages = freePages; } - else - vmmMemoryMap[i].cowCounter--; + else { + spinUnlock(&vmmSpinLock); + adjustCowCounter((i * PAGE_SIZE), -1); + spinLock(&vmmSpinLock); + } } } @@ -392,87 +397,3 @@ spinUnlock(&vmmSpinLock); return; } - -/*** - $Log: vmm_memory.c,v $ - Revision 1.1 2006/12/01 18:46:19 reddawg - renaming files - - Revision 1.2 2006/12/01 05:12:35 reddawg - We're almost there... :) - - Revision 1.1.1.1 2006/06/01 12:46:13 reddawg - ubix2 - - Revision 1.5 2006/06/01 12:42:09 reddawg - Getting back to the basics - - Revision 1.4 2006/06/01 04:15:32 reddawg - Woot - - Revision 1.3 2006/06/01 03:58:33 reddawg - wondering about this stuff here - - Revision 1.2 2005/10/12 00:13:38 reddawg - Removed - - Revision 1.1.1.1 2005/09/26 17:24:51 reddawg - no message - - Revision 1.15 2004/09/11 23:39:31 reddawg - ok time for bed - - Revision 1.14 2004/09/11 16:39:19 apwillia - Fix order in adjustCowCounter to prevent potential race condition - - Revision 1.13 2004/08/14 11:23:03 reddawg - Changes - - Revision 1.12 2004/08/01 20:51:33 reddawg - adjustCowCounter: we no longer need to debug unhandled adjustments they are normal situations now - - Revision 1.11 2004/07/28 00:17:05 reddawg - Major: - Disconnected page 0x0 from the system... Unfortunately this broke many things - all of which have been fixed. This was good because nothing deferences NULL - any more. - - Things affected: - malloc,kmalloc,getfreepage,getfreevirtualpage,pagefault,fork,exec,ld,ld.so,exec,file - - Revision 1.10 2004/07/26 19:15:49 reddawg - test code, fixes and the like - - Revision 1.9 2004/07/24 23:04:44 reddawg - Changes... mark let me know if you fault at pid 185 when you type stress - - Revision 1.8 2004/07/24 17:47:28 reddawg - vmm_pageFault: deadlock resolved thanks to a propper solution suggested by geist - - Revision 1.7 2004/07/19 02:04:32 reddawg - memory.c: added spinlocks to vmm_findFreePage and vmmFreePage to prevent two tasks from possibly allocating the same page - - Revision 1.6 2004/06/14 12:20:54 reddawg - notes: many bugs repaired and ld works 100% now. - - Revision 1.5 2004/05/21 15:34:23 reddawg - Fixed a couple of typo - - Revision 1.4 2004/05/21 14:50:10 reddawg - Cleaned up - - Revision 1.3 2004/05/19 17:28:28 reddawg - Added the correct endTask Procedure - - Revision 1.2 2004/04/30 14:16:04 reddawg - Fixed all the datatypes to be consistant uInt8,uInt16,uInt32,Int8,Int16,Int32 - - Revision 1.1.1.1 2004/04/15 12:06:52 reddawg - UbixOS v1.0 - - Revision 1.27 2004/04/13 16:36:34 reddawg - Changed our copyright, it is all now under a BSD-Style license - - - END - ***/ diff --git a/sys/vmm/vmm_mmap.c b/sys/vmm/vmm_mmap.c index 0d1a1ff..28aa85b 100644 --- a/sys/vmm/vmm_mmap.c +++ b/sys/vmm/vmm_mmap.c @@ -169,7 +169,7 @@ if (uap->fd == -1) { if (uap->addr != 0x0) { for (x = 0x0; x < round_page(uap->len); x += 0x1000) { - vmm_unmapPage(((uint32_t)uap->addr & 0xFFFFF000) + x, 1); + vmm_unmapPage(((uint32_t) uap->addr & 0xFFFFF000) + x, VMM_FREE); /* Make readonly and read/write !!! */ if (vmm_remapPage(vmm_findFreePage(_current->id), (((uint32_t)uap->addr & 0xFFFFF000) + x), PAGE_DEFAULT, _current->id, 0) == 0x0) K_PANIC("Remap Page Failed");