diff --git a/MyOS_1/Build_Number.h b/MyOS_1/Build_Number.h index ce02951..a32aa93 100644 --- a/MyOS_1/Build_Number.h +++ b/MyOS_1/Build_Number.h @@ -3,4 +3,4 @@ // Define a build number. This number will be incremented by a simple console program called by a post-build event // It's put here in its own file to keep the other program from messing up the source #define \ -BUILD_NUMBER 6507 +BUILD_NUMBER 6605 \ No newline at end of file diff --git a/MyOS_1/Drivers/Virtio_Net.c b/MyOS_1/Drivers/Virtio_Net.c index 9231c25..64e818b 100644 --- a/MyOS_1/Drivers/Virtio_Net.c +++ b/MyOS_1/Drivers/Virtio_Net.c @@ -12,6 +12,9 @@ #include "../Networking/IPv4.h" #include "Virtio.h" #include "../Timers/System_Clock.h" +#include "../Console_Serial.h" +#include "../paging.h" +#include "../Tasks/Context.h" // TODO: Support multiple NIC's @@ -301,6 +304,8 @@ void _declspec(naked) VirtIO_Net_InterruptHandler() bool VirtIO_Net_SharedInterruptHandler(void) { + _disable(); + if (debugLevel) terminal_writestring(" --------- virtio-net interrupt fired! -------\n"); @@ -470,6 +475,14 @@ void VirtIO_Net_SendPacket(Ethernet_Header *packet, uint16_t dataSize) return; } + + if (/*(uint32_t)(&transmitQueue.descriptors[descIndex2]) == 0x2800000 || (uint32_t)(&transmitQueue.descriptors[descIndex2].address) == 0x2800000 + ||*/ (uint32_t)packetBuffer == 0x2800000) + { + //serial_printf("Got em - %s\n", tasks[currentTask].imageName); + //Paging_Print_Page_Table(tasks[currentTask].cr3); + } + memcpy(packetBuffer, packet, dataSize); // (TODO: malloc returns identity-mapped addresses for now but later we'll need a function to convert virtual to physical) diff --git a/MyOS_1/Interrupts/Interrupts.c b/MyOS_1/Interrupts/Interrupts.c index 2a49973..36161c9 100644 --- a/MyOS_1/Interrupts/Interrupts.c +++ b/MyOS_1/Interrupts/Interrupts.c @@ -47,6 +47,7 @@ void _declspec(naked) default_interrupt_handler(void) void _declspec(naked) irq11_shared_interrupt_handler(void) { + _disable(); _asm pushad; ++interrupts_fired; @@ -73,6 +74,7 @@ void _declspec(naked) irq11_shared_interrupt_handler(void) void _declspec(naked) irq9_shared_interrupt_handler(void) { + _disable(); _asm pushad; ++interrupts_fired; diff --git a/MyOS_1/MyOS_1.vcxproj b/MyOS_1/MyOS_1.vcxproj index 1de4db8..28dc691 100644 --- a/MyOS_1/MyOS_1.vcxproj +++ b/MyOS_1/MyOS_1.vcxproj @@ -307,6 +307,7 @@ + UninitializedLocalUsageCheck UninitializedLocalUsageCheck @@ -362,6 +363,7 @@ + diff --git a/MyOS_1/MyOS_1.vcxproj.filters b/MyOS_1/MyOS_1.vcxproj.filters index d3813f3..d0dbde9 100644 --- a/MyOS_1/MyOS_1.vcxproj.filters +++ b/MyOS_1/MyOS_1.vcxproj.filters @@ -222,6 +222,9 @@ Source Files\Debugging + + Source Files + @@ -374,6 +377,9 @@ Header Files\Debugging + + Header Files + diff --git a/MyOS_1/Networking/TFTP.c b/MyOS_1/Networking/TFTP.c index d0b9d4d..144f7e4 100644 --- a/MyOS_1/Networking/TFTP.c +++ b/MyOS_1/Networking/TFTP.c @@ -4,6 +4,7 @@ #include "Ethernet.h" #include "../Drivers/Virtio_Net.h" #include "../Tasks/Context.h" +#include "../Console_Serial.h" // TODO: Support multiple transactions uint16_t transactionID; @@ -166,6 +167,7 @@ uint16_t TFTP_RequestFile(uint32_t serverIP, const char *filename, const char *t // TODO: Seems like Qemu and VirtualBox don't support writing files via TFTP so I can't finish this :( uint16_t TFTP_WriteFile(uint32_t serverIP, const char *filename, const char *transferMode, uint8_t *sourceMAC) { + return 1235; // Don't even bother TFTP_RequestHeader *tftpData; size_t filenameLength = strlen(filename) + 1; // length of filename plus null terminator size_t transferModeLength = strlen(transferMode) + 1; @@ -285,6 +287,7 @@ void TFTP_ProcessDataPacket(TFTP_DataHeader *dataPacket, uint16_t sourcePort, ui } else { + //serial_printf("tftpTaskIndex: %d, currentTask: %d\n", tftpTaskIndex, currentTask); // We need to swap out the page directory with the one for the task that requested the file __writecr3(tasks[tftpTaskIndex].cr3); diff --git a/MyOS_1/kmisc.c b/MyOS_1/kmisc.c new file mode 100644 index 0000000..390a173 --- /dev/null +++ b/MyOS_1/kmisc.c @@ -0,0 +1,213 @@ +#include "paging.h" +#include "printf.h" +#include "Interrupts\System_Calls.h" +#include "kmisc.h" +#include "misc.h" +#include "Console_Serial.h" +#include "Tasks/Context.h" + +// Functions used by the kernel & drivers + +// TODO: This might all go out the window in favor of conditionally-compiling misc.c functions; I haven't decided yet. + +extern uint32_t memoryNextAvailableAddress; +extern uint32_t pagedMemoryAvailable; + +// TODO: Change this to a more robust scheme (?) +ALLOCATION_ARRAY kallocationArray = { 0 }; +unsigned int knextAllocationSlot = 0; + +// Very, very basic support for freeing memory: +ALLOCATION_ARRAY kfreeMemoryArray = { 0 }; +unsigned int knextFreeMemorySlot = 0; + +#ifdef DEBUG_MEM +#define noFileName "FILENAME NOT SET"; +char *dbgkMemFilename = noFileName; +int dbgkMemLineNumber = 0; +char *dbgkFreeFilename = noFileName; +int dbgkFreeLineNumber = 0; +#endif + +inline void addAllocationToKFreeMemoryArray(int allocationIndex) +{ + // Try to add this memory to the free memory array + if (knextFreeMemorySlot == MAX_ALLOCATIONS) + { + kprintf("NSLFM"); + return; + } + + kfreeMemoryArray.address[knextFreeMemorySlot] = kallocationArray.address[allocationIndex]; + kfreeMemoryArray.size[knextFreeMemorySlot] = kallocationArray.size[allocationIndex]; + kfreeMemoryArray.inUse[knextFreeMemorySlot++] = true; +} + +#ifdef DEBUG_MEM +void *dbg_kmalloc(size_t size, char *filename, int lineNumber) +{ + dbgkMemFilename = filename; + dbgkMemLineNumber = lineNumber; + serial_printf("Allocating %d bytes from %s, line %d for %s\n", size, filename, lineNumber, tasks[currentTask].imageName); + return kmalloc(size); +} +#endif + +// Allocate some kernel memory. Mostly this is meant to be used by drivers. +// This will be mapped into every tasks page space and will be allocated contiguously +// TODO: Is it better to have this crazy scheme with the two functions, or just modify malloc to make sure +// it never reuses user-space memory when called from the kernel? + +void* kmalloc(size_t size) +{ + if (knextAllocationSlot >= MAX_ALLOCATIONS) + { + kprintf("Maximum memory allocations exceeded!\n"); + return NULL; + } + +#ifdef DEBUG_MEM + kallocationArray.lineNumber[knextAllocationSlot] = dbgkMemLineNumber; + strncpy(kallocationArray.filename[knextAllocationSlot], dbgkMemFilename, MAX_DEBUG_FILENAME_LENGTH); + dbgkMemFilename = noFileName; + dbgkMemLineNumber = 0; +#endif + + // See if there's freed memory available to reallocate (first fit algorithm; memory will end up wasted) + for (size_t i = 0; i < knextFreeMemorySlot; ++i) + { + if (kfreeMemoryArray.size[i] >= size) + { + // We found a piece of free memory we can reuse + + // Keep track of the memory in our allocations array + kallocationArray.address[knextAllocationSlot] = kfreeMemoryArray.address[i]; + kallocationArray.size[knextAllocationSlot] = kfreeMemoryArray.size[i]; + kallocationArray.inUse[knextAllocationSlot] = true; + + // We want to keep kfreeMemoryArray from fragmenting, so we'll copy + // last used free memory entry of the array to the i position and decrease + // the used portion of the array by one + --knextFreeMemorySlot; + if (knextFreeMemorySlot) + { + kfreeMemoryArray.address[i] = kfreeMemoryArray.address[knextFreeMemorySlot]; + kfreeMemoryArray.size[i] = kfreeMemoryArray.size[knextFreeMemorySlot]; + } + // The last entry is no longer in use + kfreeMemoryArray.inUse[knextFreeMemorySlot] = false; + +#ifdef DEBUG_MEM + //printf("Reusing freed memory from slot %d, (reuse #%d)\n", i, ++reuses); +#endif + return (void *)kallocationArray.address[knextAllocationSlot++]; + } + } + + uint32_t availableAddress = memoryNextAvailableAddress; + +#ifdef DEBUG_MEM + printf("Allocating new %d bytes\n", size); +#endif + + //if(debugLevel) + //printf("size: %d\nadrress: %d\n", size, memoryNextAvailableAddress); + + /*terminal_writestring("Paged memory available: "); + terminal_print_int(pagedMemoryAvailable); + terminal_newline();*/ + + // see if we need to allocate a page + if (size > pagedMemoryAvailable) + { + // TODO: Support dynamic page granularity, not just large pages + unsigned int pagesToAllocate = size / FOUR_MEGABYTES; + + // check for remainder from division + if (pagesToAllocate * FOUR_MEGABYTES < size) + ++pagesToAllocate; + + // Allocate the pages + unsigned int pagesAllocated; + KPageAllocator(pagesToAllocate, &pagesAllocated, &availableAddress); + + // We need to ensure the pages are in order + if (!availableAddress || (pagesAllocated < pagesToAllocate)) + { + kprintf("Returning NULL, %d pages allocated out of %d\n", pagesAllocated, pagesToAllocate); + // TODO: Free allocated pages + return NULL; + } + + // TODO: see if the page we allocated follows the previous page + // for now, we'll just ignore the old allocated memory + pagedMemoryAvailable = pagesAllocated * FOUR_MEGABYTES; + + memoryNextAvailableAddress = availableAddress; + } + + pagedMemoryAvailable -= size; + availableAddress = memoryNextAvailableAddress; + memoryNextAvailableAddress += size; + + // Keep track of the memory in our allocations array + kallocationArray.address[knextAllocationSlot] = availableAddress; + kallocationArray.size[knextAllocationSlot] = size; + kallocationArray.inUse[knextAllocationSlot++] = true; + + return (void *)availableAddress; +} + +#ifdef DEBUG_MEM +void dbg_kfree(void *ptr, char *filename, int lineNumber) +{ + dbgkFreeFilename = filename; + dbgkFreeLineNumber = lineNumber; + serial_printf("Freeing mem from %s, line %d for %s\n", filename, lineNumber, tasks[currentTask].imageName); + kfree(ptr); +} +#endif + +void kfree(void *ptr) +{ + // Find this pointer in the allocation array + for (size_t i = 0; i < knextAllocationSlot; ++i) + { + if (kallocationArray.address[i] == (uint32_t)ptr) + { + if (kallocationArray.inUse[i]) + { + addAllocationToKFreeMemoryArray(i); + + // We want to keep the allocation array from being fragmented, so we + // copy the final entry in allocation array to the i position and + // decrease the size of the allocation array + --knextAllocationSlot; + if (knextAllocationSlot) + { + kallocationArray.address[i] = kallocationArray.address[knextAllocationSlot]; + kallocationArray.size[i] = kallocationArray.size[knextAllocationSlot]; + } + + kallocationArray.inUse[knextAllocationSlot] = false; + } + else + { + kprintf("free() called to free already-freed pointer, 0x%lX\n", ptr); + } + + return; + } + } + + kprintf("free() called with invalid pointer: 0x%lX", ptr); +#ifdef DEBUG_MEM + printf(" from %s, line %d\n", dbgkFreeFilename, dbgkFreeLineNumber); + dbgkFreeFilename = noFileName; + dbgkFreeLineNumber = 0; + //for (;;) + // __halt(); +#else + kprintf("\n"); +#endif +} \ No newline at end of file diff --git a/MyOS_1/kmisc.h b/MyOS_1/kmisc.h new file mode 100644 index 0000000..517124d --- /dev/null +++ b/MyOS_1/kmisc.h @@ -0,0 +1,14 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +void* kmalloc(size_t size); +void kfree(void *ptr); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ diff --git a/MyOS_1/main.c b/MyOS_1/main.c index 4c08f19..8b71859 100644 --- a/MyOS_1/main.c +++ b/MyOS_1/main.c @@ -133,7 +133,7 @@ void KeStartupPhase2(multiboot_info *multibootInfo) //Mouse_Init(); // Execute autoexec.bat (if it exists) - //Autoexec(); + Autoexec(); // Say Hello terminal_writestring("Hello world!\n"); diff --git a/MyOS_1/misc.c b/MyOS_1/misc.c index 1a26097..b33f4b3 100644 --- a/MyOS_1/misc.c +++ b/MyOS_1/misc.c @@ -5,7 +5,9 @@ #include "printf.h" #include "Interrupts\System_Calls.h" #include "Interrupts/Interrupts.h" +#include "Console_Serial.h" #include +#include "Tasks/Context.h" uint32_t pagedMemoryAvailable = 0; uint32_t memoryNextAvailableAddress = 0; @@ -63,6 +65,7 @@ void dbg_free(void *ptr, char *filename, int lineNumber) { dbgFreeFilename = filename; dbgFreeLineNumber = lineNumber; + serial_printf("Freeing mem from %s, line %d for %s\n", filename, lineNumber, tasks[currentTask].imageName); free(ptr); } #endif @@ -70,6 +73,10 @@ void dbg_free(void *ptr, char *filename, int lineNumber) // TODO: Make thread-safe void free(void *ptr) { +#ifdef MYOS_KERNEL + kfree(ptr); + return; +#else // Find this pointer in the allocation array for (size_t i = 0; i < nextAllocationSlot; ++i) { @@ -110,6 +117,8 @@ void free(void *ptr) #else printf("\n"); #endif + +#endif // MYOS_KERNEL } char intToChar(int i) @@ -121,6 +130,7 @@ char intToChar(int i) } // TODO: Test +// TODO: Handle kernel-mode void* realloc(void* ptr, size_t size) { if (!ptr) @@ -128,6 +138,10 @@ void* realloc(void* ptr, size_t size) void *ptrNew = malloc(size); +#ifdef MYOS_KERNEL + serial_printf("realloc called\n"); +#endif + // Find ptr in allocation array int index; for (index = 0; index < MAX_ALLOCATIONS; ++index) @@ -375,6 +389,7 @@ void *dbg_malloc(size_t size, char *filename, int lineNumber) { dbgMemFilename = filename; dbgMemLineNumber = lineNumber; + serial_printf("Allocating %d bytes from %s, line %d for %s\n", size, filename, lineNumber, tasks[currentTask].imageName); return malloc(size); } #endif @@ -382,6 +397,9 @@ void *dbg_malloc(size_t size, char *filename, int lineNumber) unsigned int reuses = 0; void* malloc(size_t size) { +#ifdef MYOS_KERNEL + return kmalloc(size); +#else if (nextAllocationSlot >= MAX_ALLOCATIONS) { printf("Maximum memory allocations exceeded!\n"); @@ -397,7 +415,8 @@ void* malloc(size_t size) // See if there's freed memory available to reallocate (first fit algorithm; memory will end up wasted) - for(size_t i = 0; i < nextFreeMemorySlot; ++i) + // TODO: We have to guarantee that if we're calling this from the kernel, we don't try to reuse memory mapped to user space + for (size_t i = 0; i < nextFreeMemorySlot; ++i) { if (freeMemoryArray.size[i] >= size) { @@ -464,9 +483,9 @@ void* malloc(size_t size) // So we can guarantee the pages will be allocated in order. (TODO: Now that I think of it, this logic should maybe be in PageAllocator?) /*while (pagesToAllocate) { - unsigned int pagesAllocated; - PageAllocator(pagesToAllocate, &pagesAllocated); - pagesToAllocate -= pagesAllocated; + unsigned int pagesAllocated; + PageAllocator(pagesToAllocate, &pagesAllocated); + pagesToAllocate -= pagesAllocated; }*/ unsigned int pagesAllocated; @@ -503,6 +522,8 @@ void* malloc(size_t size) allocationArray.inUse[nextAllocationSlot++] = true; return (void *)availableAddress; + +#endif // MYOS_KERNEL } #pragma function(memcmp) diff --git a/MyOS_1/misc.h b/MyOS_1/misc.h index 4ab9a94..43fb739 100644 --- a/MyOS_1/misc.h +++ b/MyOS_1/misc.h @@ -7,7 +7,11 @@ extern "C" { #include #include -//#define DEBUG_MEM +#ifdef MYOS_KERNEL +#include "kmisc.h" +#endif + +#define DEBUG_MEM #ifdef DEBUG_MEM #define MAX_DEBUG_FILENAME_LENGTH 24 @@ -82,13 +86,23 @@ int strcasecmp(const char *s1, const char *s2); int __cdecl strcmp(const char *str1, const char *str2); #pragma intrinsic(strcmp) -#ifdef DEBUG_MEM -// TODO: Not thread safe, but it probably doesn't matter -#define dbg_alloc(sz) dbg_malloc(sz, __FILE__, __LINE__) -#define dbg_release(ptr) dbg_free(ptr, __FILE__, __LINE__) +#ifdef MYOS_KERNEL + #ifdef DEBUG_MEM + // TODO: Not thread safe, but it probably doesn't matter + #define dbg_alloc(sz) dbg_kmalloc(sz, __FILE__, __LINE__) + #define dbg_release(ptr) dbg_kfree(ptr, __FILE__, __LINE__) + #else + #define dbg_alloc(sz) kmalloc(sz) + #define dbg_release(ptr) kfree(ptr) + #endif #else -#define dbg_alloc(sz) malloc(sz) -#define dbg_release(ptr) free(ptr) + #ifdef DEBUG_MEM + #define dbg_alloc(sz) dbg_malloc(sz, __FILE__, __LINE__) + #define dbg_release(ptr) dbg_free(ptr, __FILE__, __LINE__) + #else + #define dbg_alloc(sz) malloc(sz) + #define dbg_release(ptr) free(ptr) + #endif #endif void *malloc(size_t size); diff --git a/MyOS_1/paging.c b/MyOS_1/paging.c index ec37dc1..07b1532 100644 --- a/MyOS_1/paging.c +++ b/MyOS_1/paging.c @@ -4,6 +4,7 @@ #include #include "Interrupts/System_Calls.h" #include "Tasks/Context.h" +#include "Console_Serial.h" // Allocate space for paging structures. We need enough space for three arrays with 0x1000 32-bit entries each. // Each array must be aligned on a 0x1000-byte boundary. @@ -14,8 +15,10 @@ uint32_t paging_space[0x3FFF]; uint32_t *pageDir; -uint32_t pagingNextAvailableMemory; // physical address of the next available page -uint32_t paging4MPagesAvailable; // number of 4M physical memory pages available to be mapped +uint32_t pagingNextAvailableMemory; // physical address of the next available page +uint32_t pagingNextAvailableKernelPage; // The index into the page directory where the next kernel page can go +uint32_t pagingKernelNonPagedArea; // A page (4MiB) of non-paged, identity-mapped memory drivers can use (non-paged pool) +uint32_t paging4MPagesAvailable; // number of 4M physical memory pages available to be mapped uint32_t nextPageDirectory; // TEMPTEMP where the next created page directory will be stored @@ -49,13 +52,27 @@ void KPageAllocator(unsigned int pages, unsigned int *pPagesAllocated, uint32_t // limit the number of pages to allocate to the number available. if (pages > paging4MPagesAvailable) - pages = paging4MPagesAvailable; + { + // pages = paging4MPagesAvailable; + // NOPE: kmalloc expects all pages to be allocated + kprintf("Too few pages available to satisfy request\n"); + return; + } /*terminal_writestring("Need to allocate "); terminal_print_int(pages); terminal_writestring(" pages.\n");*/ - uint32_t nextPage = pagingNextAvailableMemory / FOUR_MEGABYTES; + uint32_t nextPage = /*pagingNextAvailableKernelPage;// */pagingNextAvailableMemory / FOUR_MEGABYTES; + uint32_t physicalAddress = pagingNextAvailableMemory; + + // sanity check + if ((physicalAddress & PAGING_ADDRESS_BITS) != physicalAddress) + { + kprintf("Physical address does not lie on a 4M boundary!\nSystem halted.\n"); + for (;;) + __halt(); + } // Get the page directory we'll be using PAGE_DIRECTORY_ENTRY *pageDirectory = (PAGE_DIRECTORY_ENTRY *)tasks[currentTask].cr3; @@ -64,26 +81,36 @@ void KPageAllocator(unsigned int pages, unsigned int *pPagesAllocated, uint32_t for (size_t allocated = 0; allocated < pages; ++allocated) { // Add the current page to the page directory - pageDirectory[nextPage] = ((nextPage * FOUR_MEGABYTES) + pageDirectory[nextPage] = ((physicalAddress) | DIRECTORY_ENTRY_PRESENT | DIRECTORY_ENTRY_USER_ACCESSIBLE | DIRECTORY_ENTRY_WRITABLE | DIRECTORY_ENTRY_4MB); - // If we're mapping this into the kernel space, we need to copy that mapping into every running task - if (pageDirectory == pageDir) + // Since we're mapping this into the kernel space, we need to copy that mapping into every running task + //if (pageDirectory == pageDir) { for (int i = 0; i < MAX_TASKS; ++i) { - if (!tasks[i].inUse || tasks[i].cr3 == (uint32_t)pageDir) + if (!tasks[i].inUse || tasks[i].cr3 == (uint32_t)pageDirectory) continue; PAGE_DIRECTORY_ENTRY *otherPageDir = (PAGE_DIRECTORY_ENTRY *)tasks[i].cr3; - otherPageDir[nextPage] = ((nextPage * FOUR_MEGABYTES) + // make sure we aren't overwriting the app's mapping (TODO: not sure how we are guaranteeing that we won't) + if ((otherPageDir[nextPage] & DIRECTORY_ENTRY_PRESENT) == DIRECTORY_ENTRY_PRESENT) + { + kprintf("Tried to overwrite page mapping of %s at 0x%X\nSystem halted.\n", tasks[i].imageName, nextPage * FOUR_MEGABYTES); + for (;;) + __halt(); + // TODO: How should this be handled? + } + + otherPageDir[nextPage] = ((physicalAddress) | DIRECTORY_ENTRY_PRESENT | DIRECTORY_ENTRY_USER_ACCESSIBLE | DIRECTORY_ENTRY_WRITABLE | DIRECTORY_ENTRY_4MB); } } // update pointers and stuff ++nextPage; + ++pagingNextAvailableKernelPage; --paging4MPagesAvailable; pagingNextAvailableMemory += FOUR_MEGABYTES; ++(*pPagesAllocated); @@ -101,13 +128,14 @@ bool Paging_Print_Page_Table(PAGE_DIRECTORY_ENTRY *thePageDir) done = true; kprintf("Page table entries:\nLogical -> Physical -- flags\n"); - kprintf("continuing\n"); + //serial_printf("Page table entries:\nLogical -> Physical -- flags\n"); for (int i = 0; i < 1024; ++i) { if (!(thePageDir[i] & PAGE_ENTRY_PRESENT)) continue; done = false; kprintf("0x%X -> 0x%X - 0x%X\n", i * FOUR_MEGABYTES, thePageDir[i] & 0xFFFFF000, thePageDir[i] & 0xFFF); + //serial_printf("0x%X -> 0x%X - 0x%X\n", i * FOUR_MEGABYTES, thePageDir[i] & 0xFFFFF000, thePageDir[i] & 0xFFF); } return done; } diff --git a/MyOS_1/paging.h b/MyOS_1/paging.h index ccc09b2..36d392e 100644 --- a/MyOS_1/paging.h +++ b/MyOS_1/paging.h @@ -21,10 +21,14 @@ typedef /*__declspec(align(4096))*/ uint32_t PAGE_TABLE_ENTRY; #define FOUR_MEGABYTES 0x400000 #define PAGING_ADDRESS_BITS 0xFFFFF000 +#define PAGING_ADDRESS_BITS 0xFFFFF000 + extern uint32_t paging_space[0x3FFF]; extern uint32_t *pageDir; extern uint32_t pagingNextAvailableMemory; +extern uint32_t pagingNextAvailableKernelPage; +extern uint32_t pagingKernelNonPagedArea; extern uint32_t paging4MPagesAvailable; extern uint32_t nextPageDirectory; // TEMPTEMP @@ -71,9 +75,12 @@ inline void Paging_Enable(multiboot_info *multibootInfo) // Identity map the next four megs (this is used by the GUI shell) pageDirectory[3] = (PAGE_DIRECTORY_ENTRY)((uint32_t)0xC00000 | DIRECTORY_ENTRY_PRESENT | DIRECTORY_ENTRY_WRITABLE | DIRECTORY_ENTRY_4MB | DIRECTORY_ENTRY_USER_ACCESSIBLE); - // Identity map the next four megs + // Identity map the next four megs (this is used for applications' page tables) pageDirectory[4] = (PAGE_DIRECTORY_ENTRY)((uint32_t)0x1000000 | DIRECTORY_ENTRY_PRESENT | DIRECTORY_ENTRY_WRITABLE | DIRECTORY_ENTRY_4MB | DIRECTORY_ENTRY_USER_ACCESSIBLE); + // Another 4 megs - this one is used by the non-paged pool (for drivers) + pageDirectory[5] = (PAGE_DIRECTORY_ENTRY)((uint32_t)0x1400000 | DIRECTORY_ENTRY_PRESENT | DIRECTORY_ENTRY_WRITABLE | DIRECTORY_ENTRY_4MB | DIRECTORY_ENTRY_USER_ACCESSIBLE); + // Map the kernel (4 megs starting at 0x10 0000) to 0xC000 0000 for (i = 0; i < 1024; ++i) { @@ -83,6 +90,9 @@ inline void Paging_Enable(multiboot_info *multibootInfo) // put the kernel page table in the page directory into entry 768, which will map it to 0xC000 0000 pageDirectory[768] = (PAGE_DIRECTORY_ENTRY)((uint32_t)initialKernelTable | DIRECTORY_ENTRY_PRESENT | DIRECTORY_ENTRY_WRITABLE); + // The next kernel page we allocate can go to this index in the page directory + pagingNextAvailableKernelPage = 769; + // TEMPTEMP HACKHACK! - identity map the linear frame buffer, which on my Qemu starts at 0xFD00 0000 uint32_t lfbAddress = 0xFD000000; @@ -119,20 +129,23 @@ inline void Paging_Enable(multiboot_info *multibootInfo) // save a pointer to pageDirectory pageDir = pageDirectory; - // determine available pages - pagingNextAvailableMemory = FOUR_MEGABYTES * 5; // TEMP: Next available page will (likely) start at 20 Megs - // We'll assume we have 64 megs available - paging4MPagesAvailable = 16; // TODO: Calculate based on the memory map Grub gave us - // TEMPTEMP: put page directories between 16 - 20 megs nextPageDirectory = FOUR_MEGABYTES * 4; + // TEMPTEMP: put a non-paged pool of memory between 20 - 24 megs + pagingKernelNonPagedArea = FOUR_MEGABYTES * 5; + // Walk through the mem map grub gave us // TODO: Assert that grub gave us a memory map // TODO: Don't assume we have memory at the beginning of RAM // TODO: Use all the entries we get from GRUB multiboot_mmap_entry *entry = (multiboot_mmap_entry *)multibootInfo->mmap_addr; - + + // determine available pages + pagingNextAvailableMemory = FOUR_MEGABYTES * 6; // TEMP: Next available page will (likely) start at 24 Megs + // We'll assume we have 64 megs available + //paging4MPagesAvailable = 16; // TODO: Calculate based on the memory map Grub gave us + // examine each mmap entry for (uint32_t offset = 0; offset <= multibootInfo->mmap_length && entry->size; offset += entry->size + 4) { @@ -144,10 +157,10 @@ inline void Paging_Enable(multiboot_info *multibootInfo) // determine how many pages we really have available uint64_t addrEnd = entry->addr + entry->len; uint64_t bytesAvailable = addrEnd - pagingNextAvailableMemory; - paging4MPagesAvailable = bytesAvailable / FOUR_MEGABYTES; + paging4MPagesAvailable = (uint32_t)(bytesAvailable / (uint64_t)FOUR_MEGABYTES); return; } - } + } // advance pointer to next entry entry = (multiboot_mmap_entry*)((uint32_t)entry + entry->size + 4); diff --git a/Release/MyOS_1.dll b/Release/MyOS_1.dll index aca4a47..2a485ab 100644 Binary files a/Release/MyOS_1.dll and b/Release/MyOS_1.dll differ