From e5933446df66bf57a61a0f741a2533961c20ba01 Mon Sep 17 00:00:00 2001 From: Trevor Thompson Date: Thu, 23 Jul 2020 22:21:54 -0400 Subject: [PATCH 1/2] Add kmalloc and kfree to allocate and free memory when running in kernel mode. Kernel memory is tracked in it's own memory usage structures. This is important because kernel code can run in any context, but memory allocated in one context shouldn't be freed in another, but can be referenced in any context. --- MyOS_1/Build_Number.h | 2 +- MyOS_1/Drivers/Virtio_Net.c | 13 +++ MyOS_1/Interrupts/Interrupts.c | 2 + MyOS_1/MyOS_1.vcxproj | 2 + MyOS_1/MyOS_1.vcxproj.filters | 6 ++ MyOS_1/Networking/TFTP.c | 3 + MyOS_1/kmisc.c | 190 +++++++++++++++++++++++++++++++++ MyOS_1/kmisc.h | 14 +++ MyOS_1/main.c | 2 +- MyOS_1/misc.c | 22 +++- MyOS_1/misc.h | 26 +++-- MyOS_1/paging.c | 47 ++++++-- MyOS_1/paging.h | 6 ++ Release/MyOS_1.dll | Bin 2453504 -> 2527232 bytes 14 files changed, 313 insertions(+), 22 deletions(-) create mode 100644 MyOS_1/kmisc.c create mode 100644 MyOS_1/kmisc.h diff --git a/MyOS_1/Build_Number.h b/MyOS_1/Build_Number.h index ce02951..87e9354 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 6563 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..7e385b1 --- /dev/null +++ b/MyOS_1/kmisc.c @@ -0,0 +1,190 @@ +#include "paging.h" +#include "printf.h" +#include "kmisc.h" +#include "misc.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 *dbgMemFilename = noFileName; +int dbgMemLineNumber = 0; +char *dbgFreeFilename = noFileName; +int dbgFreeLineNumber = 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; +} + +// 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] = dbgMemLineNumber; + strncpy(kallocationArray.filename[knextAllocationSlot], dbgMemFilename, MAX_DEBUG_FILENAME_LENGTH); + dbgMemFilename = noFileName; + dbgMemLineNumber = 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; +} + +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", dbgFreeFilename, dbgFreeLineNumber); + dbgFreeFilename = noFileName; + dbgFreeLineNumber = 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..27d1845 100644 --- a/MyOS_1/misc.c +++ b/MyOS_1/misc.c @@ -5,6 +5,7 @@ #include "printf.h" #include "Interrupts\System_Calls.h" #include "Interrupts/Interrupts.h" +#include "Console_Serial.h" #include uint32_t pagedMemoryAvailable = 0; @@ -70,6 +71,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 +115,8 @@ void free(void *ptr) #else printf("\n"); #endif + +#endif // MYOS_KERNEL } char intToChar(int i) @@ -121,6 +128,7 @@ char intToChar(int i) } // TODO: Test +// TODO: Handle kernel-mode void* realloc(void* ptr, size_t size) { if (!ptr) @@ -382,6 +390,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 +408,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 +476,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 +515,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..9ca79b8 100644 --- a/MyOS_1/misc.h +++ b/MyOS_1/misc.h @@ -7,6 +7,10 @@ extern "C" { #include #include +#ifdef MYOS_KERNEL +#include "kmisc.h" +#endif + //#define DEBUG_MEM #ifdef DEBUG_MEM @@ -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..3235073 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,9 @@ 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 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 +51,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 +80,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 +127,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..800fe84 100644 --- a/MyOS_1/paging.h +++ b/MyOS_1/paging.h @@ -21,10 +21,13 @@ 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 paging4MPagesAvailable; extern uint32_t nextPageDirectory; // TEMPTEMP @@ -83,6 +86,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; diff --git a/Release/MyOS_1.dll b/Release/MyOS_1.dll index aca4a473c8616262c242704acec45fd52f452023..4200c93e29e9e4f2481d89b95269c6036caa5c83 100644 GIT binary patch delta 26647 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 z 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 delta 26450 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 WH2I0-Rmru<4auKx%y_2H!T$%i0lj1Z From db0e8706620c45c06ab95d428838713fe074f1ac Mon Sep 17 00:00:00 2001 From: Trevor Thompson Date: Tue, 4 Aug 2020 04:29:24 -0400 Subject: [PATCH 2/2] Add some reserved space in memory for a nonpaged pool. Fix DEBUG_MEM #define for kmalloc/kfree. Send memory debugging output to COM1 (for the simple debugger). Note: This experimental branch is still broken for now. --- MyOS_1/Build_Number.h | 2 +- MyOS_1/kmisc.c | 45 +++++++++++++++++++++++++++++++----------- MyOS_1/misc.c | 7 +++++++ MyOS_1/misc.h | 2 +- MyOS_1/paging.c | 1 + MyOS_1/paging.h | 25 ++++++++++++++--------- Release/MyOS_1.dll | Bin 2527232 -> 2987008 bytes 7 files changed, 60 insertions(+), 22 deletions(-) diff --git a/MyOS_1/Build_Number.h b/MyOS_1/Build_Number.h index 87e9354..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 6563 +BUILD_NUMBER 6605 \ No newline at end of file diff --git a/MyOS_1/kmisc.c b/MyOS_1/kmisc.c index 7e385b1..390a173 100644 --- a/MyOS_1/kmisc.c +++ b/MyOS_1/kmisc.c @@ -1,7 +1,10 @@ #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 @@ -20,10 +23,10 @@ unsigned int knextFreeMemorySlot = 0; #ifdef DEBUG_MEM #define noFileName "FILENAME NOT SET"; -char *dbgMemFilename = noFileName; -int dbgMemLineNumber = 0; -char *dbgFreeFilename = noFileName; -int dbgFreeLineNumber = 0; +char *dbgkMemFilename = noFileName; +int dbgkMemLineNumber = 0; +char *dbgkFreeFilename = noFileName; +int dbgkFreeLineNumber = 0; #endif inline void addAllocationToKFreeMemoryArray(int allocationIndex) @@ -40,6 +43,16 @@ inline void addAllocationToKFreeMemoryArray(int 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 @@ -54,10 +67,10 @@ void* kmalloc(size_t size) } #ifdef DEBUG_MEM - kallocationArray.lineNumber[knextAllocationSlot] = dbgMemLineNumber; - strncpy(kallocationArray.filename[knextAllocationSlot], dbgMemFilename, MAX_DEBUG_FILENAME_LENGTH); - dbgMemFilename = noFileName; - dbgMemLineNumber = 0; + 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) @@ -145,6 +158,16 @@ void* kmalloc(size_t size) 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 @@ -179,9 +202,9 @@ void kfree(void *ptr) kprintf("free() called with invalid pointer: 0x%lX", ptr); #ifdef DEBUG_MEM - printf(" from %s, line %d\n", dbgFreeFilename, dbgFreeLineNumber); - dbgFreeFilename = noFileName; - dbgFreeLineNumber = 0; + printf(" from %s, line %d\n", dbgkFreeFilename, dbgkFreeLineNumber); + dbgkFreeFilename = noFileName; + dbgkFreeLineNumber = 0; //for (;;) // __halt(); #else diff --git a/MyOS_1/misc.c b/MyOS_1/misc.c index 27d1845..b33f4b3 100644 --- a/MyOS_1/misc.c +++ b/MyOS_1/misc.c @@ -7,6 +7,7 @@ #include "Interrupts/Interrupts.h" #include "Console_Serial.h" #include +#include "Tasks/Context.h" uint32_t pagedMemoryAvailable = 0; uint32_t memoryNextAvailableAddress = 0; @@ -64,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 @@ -136,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) @@ -383,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 diff --git a/MyOS_1/misc.h b/MyOS_1/misc.h index 9ca79b8..43fb739 100644 --- a/MyOS_1/misc.h +++ b/MyOS_1/misc.h @@ -11,7 +11,7 @@ extern "C" { #include "kmisc.h" #endif -//#define DEBUG_MEM +#define DEBUG_MEM #ifdef DEBUG_MEM #define MAX_DEBUG_FILENAME_LENGTH 24 diff --git a/MyOS_1/paging.c b/MyOS_1/paging.c index 3235073..07b1532 100644 --- a/MyOS_1/paging.c +++ b/MyOS_1/paging.c @@ -17,6 +17,7 @@ uint32_t *pageDir; 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 diff --git a/MyOS_1/paging.h b/MyOS_1/paging.h index 800fe84..36d392e 100644 --- a/MyOS_1/paging.h +++ b/MyOS_1/paging.h @@ -28,6 +28,7 @@ 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 @@ -74,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) { @@ -125,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) { @@ -150,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 4200c93e29e9e4f2481d89b95269c6036caa5c83..2a485abe7cb4422c7c3f8b255e507a6bd3ed99fc 100644 GIT binary patch delta 38028 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 Us#RSaOCab#3!6IUq3VzRAG%SAWdHyG delta 37298 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