diff --git a/sys/vmm/copyvirtualspace.c b/sys/vmm/copyvirtualspace.c index dba354b..0df35bc 100644 --- a/sys/vmm/copyvirtualspace.c +++ b/sys/vmm/copyvirtualspace.c @@ -49,228 +49,290 @@ Which Task Has Which Physical Pages ************************************************************************/ -void *vmm_copyVirtualSpace(pidType pid) { - void *newPageDirectoryAddress = 0x0; +void *vmm_copyVirtualSpace( pidType pid ) { - uint32_t *parentPageDirectory = 0x0, *newPageDirectory = 0x0; - uint32_t *parentPageTable = 0x0, *newPageTable = 0x0; - uint32_t *parentStackPage = 0x0, *newStackPage = 0x0; - uint16_t x = 0, i = 0, s = 0; + void *newPageDirectoryAddress = 0x0; - spinLock(&cvsSpinLock); + uint32_t *parentPageDirectory = 0x0; + uint32_t *newPageDirectory = 0x0; + uint32_t *parentPageTable = 0x0; + uint32_t *newPageTable = 0x0; + uint32_t *parentStackPage = 0x0; + uint32_t *newStackPage = 0x0; - /* Set Address Of Parent Page Directory */ - parentPageDirectory = (uint32_t *) PD_BASE_ADDR; + uint16_t x = 0x0; + uint16_t i = 0x0; + uint16_t s = 0x0; - /* Allocate A New Page For The New Page Directory */ - if ((newPageDirectory = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) - kpanic("Error: newPageDirectory == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); + spinLock(&cvsSpinLock); - /* Set newPageDirectoryAddress To The Newly Created Page Directories Page */ - newPageDirectoryAddress = (void *) vmm_getPhysicalAddr((uint32_t) newPageDirectory); + /* Set Address Of Parent Page Directory */ + parentPageDirectory = (uint32_t *) PD_BASE_ADDR; - /* First Set Up A Flushed Page Directory */ - bzero(newPageDirectory, PAGE_SIZE); + /* Allocate A New Page For The New Page Directory */ + if( ( newPageDirectory = ( uint32_t * ) vmm_getFreeKernelPage( pid, 1 ) ) == 0x0 ) + kpanic( "Error: newPageDirectory == NULL, File: %s, Line: %i\n", __FILE__, __LINE__ ); - /* Map Kernel Code Region Entries 0 & 1 */ - newPageDirectory[0] = parentPageDirectory[0]; - //XXX: We Dont Need This - newPageDirectory[1] = parentPageDirectory[1]; + /* Set newPageDirectoryAddress To The Newly Created Page Directories Page */ + newPageDirectoryAddress = ( void * ) vmm_getPhysicalAddr( ( uint32_t ) newPageDirectory ); - if ((newPageTable = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) - kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); + /* First Set Up A Flushed Page Directory */ + bzero( newPageDirectory, PAGE_SIZE ); - parentPageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * 1)); + /* Map Kernel Code Region Entries 0 & 1 */ + newPageDirectory[0] = parentPageDirectory[0]; + // XXX: We Dont Need This - newPageDirectory[1] = parentPageDirectory[1]; - for (x = 0; x < PT_ENTRIES; x++) { - if (((parentPageTable[x]) & PAGE_PRESENT) == PAGE_PRESENT) { + if( ( newPageTable = ( uint32_t * ) vmm_getFreeKernelPage( pid, 1 ) ) == 0x0 ) + kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); - /* Set Page To COW In Parent And Child Space */ - newPageTable[x] = (((uint32_t) parentPageTable[x] & 0xFFFFF000) | (KERNEL_PAGE_DEFAULT | PAGE_COW)); + // Zero the newPageTable to ensure no garbage + bzero( newPageTable, PAGE_SIZE ); - /* 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]; - } + parentPageTable = ( uint32_t * ) ( PT_BASE_ADDR + ( PAGE_SIZE * 1 ) ); + + 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]; + + } } - else - newPageTable[x] = parentPageTable[x]; - } - newPageDirectory[1] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | KERNEL_PAGE_DEFAULT); + newPageDirectory[1] = ( vmm_getPhysicalAddr( ( uint32_t ) newPageTable ) | KERNEL_PAGE_DEFAULT ); - vmm_unmapPage((uint32_t) newPageTable, 1); + vmm_unmapPage( ( uint32_t ) newPageTable, 1 ); - newPageTable = 0x0; + 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]; + /* Map The Kernel Memory Region Entry 770 Address 0xC0800000 */ + for( x = PD_INDEX( VMM_KERN_START ); x <= PD_INDEX( VMM_KERN_END ); x++ ) { - /* Map The Kernel Stack Region */ - for (x = PD_INDEX(VMM_KERN_STACK_START); x <= PD_INDEX(VMM_KERN_STACK_END); x++) { - if ((parentPageDirectory[x] & PAGE_PRESENT) == PAGE_PRESENT) { - /* Set Parent To Propper Page Table */ - parentPageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * x)); + newPageDirectory[x] = parentPageDirectory[x]; - /* Allocate A New Page Table */ - if ((newPageTable = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) - kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); - - bzero(newPageTable, PAGE_SIZE); - - 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__); - - /* 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); - - /* 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); - } - } - /* Put New Page Table Into New Page Directory */ - newPageDirectory[x] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | PAGE_DEFAULT); - /* Unmap Page From Kernel Space But Keep It Marked As Not Avail */ - vmm_unmapPage((uint32_t) newPageTable, 1); } - } - /* - * Now For The Fun Stuff For Page Tables 2-767 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 Pages Unless an EXECVE Happens - * - * We start at the 4MB boundary as the first 4MB is special - */ + /* Map The Kernel Stack Region */ + for( x = PD_INDEX( VMM_KERN_STACK_START ); x <= PD_INDEX( VMM_KERN_STACK_END ); x++ ) { - for (x = PD_INDEX(VMM_USER_START); x <= PD_INDEX(VMM_USER_END); x++) { + if( ( parentPageDirectory[x] & PAGE_PRESENT ) == PAGE_PRESENT ) { - /* If Page Table Exists Map It */ - if ((parentPageDirectory[x] & PAGE_PRESENT) == PAGE_PRESENT) { + /* Set Parent To Propper Page Table */ + parentPageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * x)); - /* Set Parent To Propper Page Table */ - parentPageTable = (uint32_t *) (PT_BASE_ADDR + (PAGE_SIZE * x)); + /* Allocate A New Page Table */ + if( ( newPageTable = ( uint32_t * ) vmm_getFreeKernelPage( pid, 1 ) ) == 0x0 ) { - /* Allocate A New Page Table */ - if ((newPageTable = (uint32_t *) vmm_getFreeKernelPage(pid, 1)) == 0x0) - kpanic("Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__); + kpanic( "Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__ ); - bzero(newPageTable, PAGE_SIZE); + } - /* Set Parent And New Pages To COW */ - for (i = 0; i < PD_ENTRIES; i++) { + bzero( newPageTable, PAGE_SIZE ); - /* If Page Is Mapped */ - if ((parentPageTable[i] & PAGE_PRESENT) == PAGE_PRESENT) { + for( i = 0; i < PT_ENTRIES; i++ ) { - /* Check To See If Its A Stack Page */ - if (((uint32_t) parentPageTable[i] & PAGE_STACK) == PAGE_STACK) { + 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 ) { - /* Set Pointer To Parents Stack Page */ - parentStackPage = (uint32_t *) (((PAGE_SIZE * PD_ENTRIES) * x) + (PAGE_SIZE * i)); + kpanic( "Error: newStackPage == NULL, File: %s, Line: %i\n", __FILE__, __LINE__ ); - /* 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); + /* Set Pointer To Parents Stack Page */ + parentStackPage = ( uint32_t * ) ( ( ( PAGE_SIZE * PD_ENTRIES ) * x ) + ( PAGE_SIZE * i ) ); - /* Unmap From Kernel Space */ - vmm_unmapPage((uint32_t) newStackPage, 1); + /* Copy The Stack Byte For Byte (I Should Find A Faster Way) */ + memcpy( newStackPage, parentStackPage, PAGE_SIZE ); - } - else { + /* Insert New Stack Into Page Table */ + newPageTable[i] = ( vmm_getPhysicalAddr( ( uint32_t ) newStackPage ) | PAGE_DEFAULT | PAGE_STACK ); - /* Set Page To COW In Parent And Child Space */ - newPageTable[i] = (((uint32_t) parentPageTable[i] & 0xFFFFF000) | (PAGE_DEFAULT | PAGE_COW)); + /* Unmap From Kernel Space */ + vmm_unmapPage( ( uint32_t ) newStackPage, 1 ); - /* Increment The COW Counter For This Page */ - if (((uint32_t) parentPageTable[i] & PAGE_COW) == PAGE_COW) { - adjustCowCounter(((uint32_t) parentPageTable[i] & 0xFFFFF000), 1); - } - else { - /* Add Two If This Is The First Time Setting To COW */ - adjustCowCounter(((uint32_t) parentPageTable[i] & 0xFFFFF000), 2); - parentPageTable[i] |= PAGE_COW; // newPageTable[i]; - } - } - } - else { - newPageTable[i] = (uint32_t) 0x0; - } - } + } - /* Put New Page Table Into New Page Directory */ - newPageDirectory[x] = (vmm_getPhysicalAddr((uint32_t) newPageTable) | PAGE_DEFAULT); - /* Unmap Page From Kernel Space But Keep It Marked As Not Avail */ - vmm_unmapPage((uint32_t) newPageTable, 1); + } + + /* Put New Page Table Into New Page Directory */ + newPageDirectory[x] = ( vmm_getPhysicalAddr( ( uint32_t ) newPageTable) | PAGE_DEFAULT ); + + /* Unmap Page From Kernel Space But Keep It Marked As Not Avail */ + vmm_unmapPage( ( uint32_t ) newPageTable, 1 ); + + } + } - } - /* - * Allocate A New Page For The The First Page Table Where We Will Map The - * Lower Region First 4MB - */ + /* + * Now For The Fun Stuff For Page Tables 2-767 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 Pages Unless an EXECVE Happens + * + * We start at the 4MB boundary as the first 4MB is special + */ - /* - * - * Map Page Directory Into VM Space - * First Page After Page Tables - * This must be mapped into the page directory before we map all 1024 page directories into the memory space - */ - newPageTable = (uint32_t *) vmm_getFreePage(pid); + for( x = PD_INDEX( VMM_USER_START ); x <= PD_INDEX( VMM_USER_END ); x++ ) { - newPageDirectory[PD_INDEX(PD_BASE_ADDR)] = (uint32_t) (vmm_getPhysicalAddr((uint32_t) newPageTable) | PAGE_DEFAULT); + /* If Page Table Exists Map It */ + if( ( parentPageDirectory[x] & PAGE_PRESENT ) == PAGE_PRESENT ) { - newPageTable[0] = (uint32_t) ((uint32_t) (newPageDirectoryAddress) | PAGE_DEFAULT); + /* Set Parent To Propper Page Table */ + parentPageTable = ( uint32_t * ) ( PT_BASE_ADDR + ( PAGE_SIZE * x ) ); - vmm_unmapPage((uint32_t) newPageTable, 1); + /* Allocate A New Page Table */ + if( ( newPageTable = ( uint32_t * ) vmm_getFreeKernelPage( pid, 1 ) ) == 0x0 ) { - /* - * - * Map Page Tables Into VM Space - * The First Page Table (4MB) Maps To All Page Directories - * - */ + kpanic( "Error: newPageTable == NULL, File: %s, Line: %i\n", __FILE__, __LINE__ ); - newPageTable = (uint32_t *) vmm_getFreePage(pid); + } - newPageDirectory[PD_INDEX(PT_BASE_ADDR)] = (uint32_t) (vmm_getPhysicalAddr((uint32_t) newPageTable) | PAGE_DEFAULT); + bzero( newPageTable, PAGE_SIZE ); - /* Flush The Page From Garbage In Memory */ - bzero(newPageTable, PAGE_SIZE); + /* Set Parent And New Pages To COW */ + for( i = 0; i < PD_ENTRIES; i++ ) { - for (x = 0; x < PD_ENTRIES; x++) - newPageTable[x] = newPageDirectory[x]; - /* Unmap Page From Virtual Space */ - vmm_unmapPage((uint32_t) newPageTable, 1); + /* If Page Is Mapped */ + if( ( parentPageTable[i] & PAGE_PRESENT ) == PAGE_PRESENT ) { - /* Now We Are Done With The Page Directory So Lets Unmap That Too */ - vmm_unmapPage((uint32_t) newPageDirectory, 1); + /* Check To See If Its A Stack Page */ + if( ( ( uint32_t ) parentPageTable[i] & PAGE_STACK ) == PAGE_STACK ) { - spinUnlock(&cvsSpinLock); + /* Alloc A New Page For This Stack Page */ + if( ( newStackPage = (uint32_t *) vmm_getFreeKernelPage( pid, 1 ) ) == 0x0 ) { - /* Return Physical Address Of Page Directory */ - return (newPageDirectoryAddress); + kpanic( "Error: newStackPage == NULL, File: %s, Line: %i\n", __FILE__, __LINE__ ); + + } + + bzero( newStackPage, PAGE_SIZE ); + + /* 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 ); + + /* 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 ); + + } else { + + /* Set Page To COW In Parent And Child Space */ + newPageTable[i] = ( ( ( uint32_t ) parentPageTable[i] & 0xFFFFF000 ) | (PAGE_DEFAULT | PAGE_COW ) ); + + /* Increment The COW Counter For This Page */ + if( ( ( uint32_t ) parentPageTable[i] & PAGE_COW ) == PAGE_COW ) { + + adjustCowCounter( ( ( uint32_t ) parentPageTable[i] & 0xFFFFF000 ), 1 ); + + } else { + + /* Add Two If This Is The First Time Setting To COW */ + adjustCowCounter( ( ( uint32_t ) parentPageTable[i] & 0xFFFFF000 ), 2 ); + + parentPageTable[i] |= PAGE_COW; // newPageTable[i]; + + } + + } + + } else { + + newPageTable[i] = ( uint32_t ) 0x0; + + } + + } + + /* Put New Page Table Into New Page Directory */ + newPageDirectory[x] = ( vmm_getPhysicalAddr( ( uint32_t ) newPageTable) | PAGE_DEFAULT ); + + /* Unmap Page From Kernel Space But Keep It Marked As Not Avail */ + vmm_unmapPage( ( uint32_t ) newPageTable, 1 ); + + } + + } + + /* + * Allocate A New Page For The The First Page Table Where We Will Map The + * Lower Region First 4MB + */ + + /* + * + * Map Page Directory Into VM Space + * First Page After Page Tables + * This must be mapped into the page directory before we map all 1024 page directories into the memory space + */ + + newPageTable = ( uint32_t * ) vmm_getFreePage( pid ); + + bzero( newPageTable, PAGE_SIZE ); + + newPageDirectory[PD_INDEX(PD_BASE_ADDR)] = ( uint32_t ) ( vmm_getPhysicalAddr( ( uint32_t ) newPageTable ) | PAGE_DEFAULT ); + + newPageTable[0] = ( uint32_t ) ( ( uint32_t ) ( newPageDirectoryAddress ) | PAGE_DEFAULT ); + + vmm_unmapPage( ( uint32_t ) newPageTable, 1 ); + + /* + * + * Map Page Tables Into VM Space + * The First Page Table (4MB) Maps To All Page Directories + * + */ + + newPageTable = ( uint32_t * ) vmm_getFreePage( pid ); + + /* Flush The Page From Garbage In Memory */ + bzero( newPageTable, PAGE_SIZE ); + + newPageDirectory[PD_INDEX( PT_BASE_ADDR )] = ( uint32_t ) ( vmm_getPhysicalAddr( ( uint32_t ) newPageTable ) | PAGE_DEFAULT ); + + for( x = 0; x < PD_ENTRIES; x++ ) { + + newPageTable[x] = newPageDirectory[x]; + + } + + /* Unmap Page From Virtual Space */ + vmm_unmapPage( ( uint32_t ) newPageTable, 1 ); + + /* Now We Are Done With The Page Directory So Lets Unmap That Too */ + vmm_unmapPage( ( uint32_t ) newPageDirectory, 1 ); + + spinUnlock( &cvsSpinLock ); + + /* Return Physical Address Of Page Directory */ + return( newPageDirectoryAddress ); + }