diff --git a/.vscode/settings.json b/.vscode/settings.json index 896c677..58e978a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -62,6 +62,13 @@ "streambuf": "cpp", "text_encoding": "cpp", "thread": "cpp", - "cinttypes": "cpp" + "cinttypes": "cpp", + "bitset": "cpp", + "ranges": "cpp", + "hash_map": "cpp", + "rope": "cpp", + "slist": "cpp", + "stacktrace": "cpp", + "regex": "cpp" } } \ No newline at end of file diff --git a/kernel/src/Common/Panic.cpp b/kernel/src/Common/Panic.cpp index 42d0f0d..ae2daac 100644 --- a/kernel/src/Common/Panic.cpp +++ b/kernel/src/Common/Panic.cpp @@ -3,7 +3,6 @@ void Panic(const char *meditationString, System::Registers registers) { kerr << "=========== Kernel panic ===========" << Kt::newline; kerr << meditationString << Kt::newline; - while (true) { #if defined (__x86_64__) diff --git a/kernel/src/Common/Panic.hpp b/kernel/src/Common/Panic.hpp index febae56..b342b4d 100644 --- a/kernel/src/Common/Panic.hpp +++ b/kernel/src/Common/Panic.hpp @@ -1,5 +1,5 @@ #pragma once #include -#include +#include void Panic(const char *meditationString, System::Registers registers); \ No newline at end of file diff --git a/kernel/src/Cpp/CppSupport.cpp b/kernel/src/Cpp/CppSupport.cpp new file mode 100644 index 0000000..2efa742 --- /dev/null +++ b/kernel/src/Cpp/CppSupport.cpp @@ -0,0 +1,17 @@ +/* + * C++ new/delete operator + * Copyright (c) 2025 Daniel Hammer +*/ + +#include +#include + +void* operator new(std::size_t size) +{ + return Memory::g_allocator->Request(size); +} + +void operator delete(void* block) +{ + Memory::g_allocator->Free(block); +} \ No newline at end of file diff --git a/kernel/src/CppLib/Stream.cpp b/kernel/src/CppLib/Stream.cpp new file mode 100644 index 0000000..50d16d7 --- /dev/null +++ b/kernel/src/CppLib/Stream.cpp @@ -0,0 +1,75 @@ +/* + * stream.cpp + * String stream/string writer + * Copyright (c) 2025 Daniel Hammer +*/ + +#include "Stream.hpp" +#include +#include +#include + +kcp::cstringstream::cstringstream() +{ + this->string = nullptr; + this->size = 0; +} + +kcp::cstringstream& kcp::cstringstream::operator<<(char c) { + this->string = (const char *)Memory::g_allocator->Realloc((void *)this->string, this->size + 1); + + if (!this->string) + { + return *this; + } + + char* ref = (char *)&string[size]; + *ref = c; + + ref++; + *ref = '\0'; + + this->size++; + + return *this; +} + +kcp::cstringstream& kcp::cstringstream::operator<<(char* str) { + while (*str != '\0') + { + *this << *str; + str++; + } + + return *this; +} + +kcp::cstringstream& kcp::cstringstream::operator<<(int num) { + char* out_str = Lib::int2basestr(num, current_base); + + *this << out_str; + return *this; +} + +kcp::cstringstream& kcp::cstringstream::operator<<(uint32_t val) { + char* out_str = Lib::uint2basestr(val, current_base); + + *this << out_str; + return *this; +} + +kcp::cstringstream& kcp::cstringstream::operator<<(uint64_t val) { + char* out_str = Lib::u64_2_basestr(val, current_base); + + *this << out_str; + return *this; +} + +kcp::cstringstream& kcp::cstringstream::operator<<(base nb) +{ + current_base = nb; +} + +const char* kcp::cstringstream::str() { + return this->string; +} \ No newline at end of file diff --git a/kernel/src/CppLib/Stream.hpp b/kernel/src/CppLib/Stream.hpp new file mode 100644 index 0000000..8f3367c --- /dev/null +++ b/kernel/src/CppLib/Stream.hpp @@ -0,0 +1,42 @@ +/* + * stream.hpp + * Streaming + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include +#include + +using namespace std; + +// Kernel C++ Platform +namespace kcp { + enum base + { + oct = 8, + dec = 10, + hex = 16 + }; + + class cstringstream { + const char* string; + std::size_t size; + + base current_base = base::dec; + + public: + cstringstream(); + + cstringstream& operator<<(char c); + cstringstream& operator<<(char* str); + + cstringstream& operator<<(int num); + cstringstream& operator<<(uint32_t val); + cstringstream& operator<<(uint64_t val); + + cstringstream& operator<<(base nb); + + const char* str(); + }; +}; \ No newline at end of file diff --git a/kernel/src/Hal/GDT.cpp b/kernel/src/Hal/GDT.cpp index 3ee2986..e4f28ec 100644 --- a/kernel/src/Hal/GDT.cpp +++ b/kernel/src/Hal/GDT.cpp @@ -3,7 +3,7 @@ */ #include "GDT.hpp" -#include "../KernelTerminal/terminal.hpp" +#include "../Terminal/terminal.hpp" // Limine loads a GDT of course, (CS = 0x28) but we will need to make a TSS someday... therefore we load our own now diff --git a/kernel/src/Libraries/Memory.hpp b/kernel/src/Libraries/Memory.hpp new file mode 100644 index 0000000..bc4c346 --- /dev/null +++ b/kernel/src/Libraries/Memory.hpp @@ -0,0 +1,17 @@ +/* + * memory.hpp + * Memory function signatures + * Copyright (c) 2025 Daniel Hammer +*/ + +#pragma once +#include + +// Signatures, defined in main.cpp, probably will move sometime soon +extern "C" +{ + void *memcpy(void *dest, const void *src, std::size_t n); + void *memset(void *s, int c, std::size_t n); + void *memmove(void *dest, const void *src, std::size_t n); + int memcmp(const void *s1, const void *s2, std::size_t n); +} \ No newline at end of file diff --git a/kernel/src/Libraries/string.cpp b/kernel/src/Libraries/string.cpp index bf973ed..630e16e 100644 --- a/kernel/src/Libraries/string.cpp +++ b/kernel/src/Libraries/string.cpp @@ -14,7 +14,7 @@ namespace Lib char * str = (char *)&output; if (!num) { - return "0"; + return (char *)"0"; } char base[] = "0123456789ABCDEFGH"; // IJKLMN .... @@ -48,7 +48,7 @@ namespace Lib char * str = (char *)&output; if (!num) { - return "0"; + return (char *)"0"; } char base[] = "0123456789ABCDEFGH"; // IJKLMN .... diff --git a/kernel/src/Memory/Memmap.cpp b/kernel/src/Memory/Memmap.cpp index 6ffdf89..3f7f13b 100644 --- a/kernel/src/Memory/Memmap.cpp +++ b/kernel/src/Memory/Memmap.cpp @@ -1,8 +1,8 @@ #include "Memmap.hpp" -#include +#include #include -#include "PageAllocator.hpp" +#include "MemoryAllocator.hpp" using namespace Kt; diff --git a/kernel/src/Memory/MemoryAllocator.cpp b/kernel/src/Memory/MemoryAllocator.cpp new file mode 100644 index 0000000..4e57484 --- /dev/null +++ b/kernel/src/Memory/MemoryAllocator.cpp @@ -0,0 +1,174 @@ +/* + * MemoryAllocator.cpp + * Heap memory allocator + * Copyright (c) 2025 Daniel Hammer +*/ + +#include "MemoryAllocator.hpp" +#include "Memmap.hpp" +#include "HHDM.hpp" + +#include +#include + +namespace Memory +{ +#if defined(__x86_64__) || defined(__aarch64__) +#define PAGE_SIZE 0x1000 +#else +#error Sorry, Unimplemented! +#endif + + Allocator::Allocator(LargestSection section) + { + g_section = section; + + Block *current_ref{&head}; + Block *start_block_ptr {(Block *)HHDM(section.address)}; + Block& start_block = *start_block_ptr; + + start_block = Block { + .size = section.size, + .next = nullptr + }; + + *start_block_ptr = start_block; + + current_ref->next = start_block_ptr; + + kout << "[Mem] Allocator created for memory section starting at 0x" << base::hex << section.address << Kt::newline; + } + + int i = 1; + void* Allocator::Request(size_t size, bool phys) { + Block* current_block_ptr{head.next}; + Block* current_prev_ptr{(Block *)&head}; + + while (true) { + if (current_block_ptr == nullptr) { + kerr << "An allocator was forced to return a Null pointer. (1)" << Kt::newline; + return nullptr; + } + + if (current_prev_ptr == nullptr) { + kerr << "An allocator was forced to return a Null pointer. (2)" << Kt::newline; + return nullptr; + } + + size_t descriptor_size = 8; + size_t total_size = size + descriptor_size; + + if (current_block_ptr->size >= total_size) { + Block block_copy = *current_block_ptr; + BlockDescriptor* descriptor {(BlockDescriptor *)current_block_ptr}; + descriptor->block_size = size; + + void* block_start = (void *)(uint64_t)current_block_ptr + descriptor_size; + + if (!block_copy.size) { + current_prev_ptr->next = block_copy.next; + } + else + { + block_copy.size -= total_size; + + current_prev_ptr->next = (Block *)(uint64_t)descriptor + total_size; + *current_prev_ptr->next = block_copy; + } + + if (phys) { + return (void *)SubHHDM(current_block_ptr); + } + + return (void *)block_start; + } else { + if (current_block_ptr->next != nullptr) { + current_prev_ptr = current_block_ptr; + current_block_ptr = current_block_ptr->next; + + continue; + } else { + kerr << "An allocator was forced to return a Null pointer. (3)" << Kt::newline; + return nullptr; + } + } + + if (current_block_ptr != nullptr) { + if (current_block_ptr->next == nullptr) { + kerr << "An allocator was forced to return a Null pointer. (4)" << Kt::newline; + return nullptr; + } + + current_block_ptr = current_block_ptr->next; + } else + { + kerr << "An allocator was forced to return a Null pointer. (5)" << Kt::newline; + return nullptr; + } + } + + return nullptr; + } + + void* Allocator::Realloc(void* ptr, size_t size) { + void *new_block = this->Request(size); + + if (ptr == nullptr) { + return new_block; + } + + if (new_block == nullptr) { + kerr << "Reallocation failed due to memory starvation" << Kt::newline; + return nullptr; + } + + BlockDescriptor* descriptor = (BlockDescriptor*)((uint64_t)ptr - 8); + + memcpy(new_block, ptr, descriptor->block_size); + + this->Free(ptr); + + return new_block; + } + + void Allocator::Free(void *pagePtr) { + if (!IsHDDMVirtAddr((uint64_t)pagePtr)) { + pagePtr = (void *)HHDM(pagePtr); + } + + BlockDescriptor* descriptor_ptr = (BlockDescriptor*)((uint64_t)pagePtr - 8); + BlockDescriptor descriptor = *descriptor_ptr; + + Block* fmrNext = head.next; + Block* blockPtr = (Block *)pagePtr; + + // Merge the descriptor with the block + Block* base = (Block *)((uint64_t)blockPtr - 8); + head.next = base; + + // Set the full size + base->size = descriptor.block_size + 8; + + // Attach the merged block to the structure + head.next->next = fmrNext; + } + + void Allocator::Stress() { + // ~410 MiB + for (size_t i = 0; i < 100000; i++) { + kout << "[Mem] Stress allocation " << base::dec << i << ": " << "0x" << base::hex << (uint64_t)this->Request(PAGE_SIZE, false) << Kt::newline; + } + } + + // Traverses the Allocator's linked list for debugging + void Allocator::Walk() { + Block* current = {head.next}; + size_t i{0}; + + while (current != nullptr) { + kout << "Block " << base::dec << i << " {" << current->size << " bytes & address 0x" << base::hex << (uint64_t)current << "}" << Kt::newline; + current = current->next; + i++; + } + } +}; \ No newline at end of file diff --git a/kernel/src/Memory/PageAllocator.hpp b/kernel/src/Memory/MemoryAllocator.hpp similarity index 51% rename from kernel/src/Memory/PageAllocator.hpp rename to kernel/src/Memory/MemoryAllocator.hpp index 3f5f8c6..641e7fe 100644 --- a/kernel/src/Memory/PageAllocator.hpp +++ b/kernel/src/Memory/MemoryAllocator.hpp @@ -2,7 +2,7 @@ #include "Memmap.hpp" namespace Memory { - class PageAllocator { + class Allocator { LargestSection g_section; struct Block { @@ -10,15 +10,20 @@ namespace Memory { Block* next; }; + struct BlockDescriptor { + size_t block_size; + }; + Block head; public: - PageAllocator(LargestSection section); - void* RequestPage(bool phys = false); + Allocator(LargestSection section); + void* Request(size_t size, bool phys = false); + void* Realloc(void* ptr, size_t size); void Free(void *pagePtr); void Stress(); void Walk(); }; - extern PageAllocator* KernelPFA; + extern Allocator* g_allocator; }; \ No newline at end of file diff --git a/kernel/src/Memory/PageAllocator.cpp b/kernel/src/Memory/PageAllocator.cpp deleted file mode 100644 index 2157a4f..0000000 --- a/kernel/src/Memory/PageAllocator.cpp +++ /dev/null @@ -1,131 +0,0 @@ -#include "PageAllocator.hpp" -#include "Memmap.hpp" -#include "HHDM.hpp" - -#include - -namespace Memory -{ -#if defined(__x86_64__) || defined(__aarch64__) -#define PAGE_SIZE 4096 -#else -#error Sorry, Unimplemented! -#endif - - PageAllocator::PageAllocator(LargestSection section) - { - g_section = section; - - size_t pages = g_section.size / PAGE_SIZE; - Block *current_ref{&head}; - Block *start_block_ptr {(Block *)HHDM(section.address)}; - Block& start_block = *start_block_ptr; - - start_block = Block { - .size = section.size, - .next = nullptr - }; - - *start_block_ptr = start_block; - - current_ref->next = start_block_ptr; - - kout << "[Mem] PageAllocator created for memory section starting at 0x" << Kt::base::hex << section.address << Kt::newline; - } - - void* PageAllocator::RequestPage(bool phys) { - bool found_block = false; - - Block* current_block_ptr{head.next}; - Block* current_prev_ptr{(Block *)&head}; - - while (!found_block) { - if (current_block_ptr == nullptr) { - kerr << "A PageAllocator was forced to return a Null pointer. (1)" << Kt::newline; - return nullptr; - } - - if (current_prev_ptr == nullptr) { - kerr << "A PageAllocator was forced to return a Null pointer. (2)" << Kt::newline; - return nullptr; - } - - if (current_block_ptr->size >= 0x1000) { // 0x1000 == 4096 - current_block_ptr->size -= 0x1000; - - if (!current_block_ptr->size) { - current_prev_ptr->next = current_block_ptr->next; - return (void *)current_block_ptr; - } - - Block block_copy = *current_block_ptr; - - current_prev_ptr->next = (Block *)(uint64_t)current_block_ptr + 0x1000; - *current_prev_ptr->next = block_copy; - - if (phys) { - return (void *)SubHHDM(current_block_ptr); - } - - return (void *)current_block_ptr; - } else { - if (current_block_ptr->next != nullptr) { - current_prev_ptr = current_block_ptr; - current_block_ptr = current_block_ptr->next; - } else { - kerr << "A PageAllocator was forced to return a Null pointer. (3)" << Kt::newline; - return nullptr; - } - } - - if (current_block_ptr != nullptr) { - if (current_block_ptr->next == nullptr) { - kerr << "A PageAllocator was forced to return a Null pointer. (4)" << Kt::newline; - return nullptr; - } - - current_block_ptr = current_block_ptr->next; - } else - { - kerr << "A PageAllocator was forced to return a Null pointer. (5)" << Kt::newline; - return nullptr; - } - } - - return nullptr; - } - - void PageAllocator::Free(void *pagePtr) { - if (!IsHDDMVirtAddr((uint64_t)pagePtr)) { - pagePtr = (void *)HHDM(pagePtr); - } - - Block* fmrNext = head.next; - - Block* blockPtr = (Block *)pagePtr; - - head.next = blockPtr; - head.next->size = 0x1000; - - head.next->next = fmrNext; - } - - void PageAllocator::Stress() { - // ~410 MiB - for (size_t i = 0; i < 100000; i++) { - kout << "[Mem] Stress allocation " << Kt::base::dec << i << ": " << "0x" << Kt::base::hex << (uint64_t)Memory::KernelPFA->RequestPage(false) << Kt::newline; - } - } - - // Traverses the PageAllocator's linked list for debugging - void PageAllocator::Walk() { - Block* current = {head.next}; - size_t i{0}; - - while (current != nullptr) { - kout << "Block " << Kt::base::dec << i << " {" << current->size << " bytes & address 0x" << Kt::base::hex << (uint64_t)current << "}" << Kt::newline; - current = current->next; - i++; - } - } -}; \ No newline at end of file diff --git a/kernel/src/KernelTerminal/terminal.cpp b/kernel/src/Terminal/terminal.cpp similarity index 100% rename from kernel/src/KernelTerminal/terminal.cpp rename to kernel/src/Terminal/terminal.cpp diff --git a/kernel/src/KernelTerminal/terminal.hpp b/kernel/src/Terminal/terminal.hpp similarity index 96% rename from kernel/src/KernelTerminal/terminal.hpp rename to kernel/src/Terminal/terminal.hpp index 9f79bf6..054ec72 100644 --- a/kernel/src/KernelTerminal/terminal.hpp +++ b/kernel/src/Terminal/terminal.hpp @@ -3,6 +3,9 @@ #include #include +#include + +using namespace kcp; namespace Kt { @@ -21,13 +24,6 @@ namespace Kt void Putchar(char c); void Print(const char *text); - enum base - { - oct = 8, - dec = 10, - hex = 16 - }; - inline base base_custom(int custom) { return (base)custom; diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 9bc9a1b..7817ad9 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -1,19 +1,27 @@ +/* + * main.cpp + * Kernel entry point + * Copyright (c) 2025 Daniel Hammer +*/ + #include #include #include #include -#include +#include #include #include #include #include -#include +#include + +#include using namespace Kt; namespace Memory { - PageAllocator* KernelPFA; + Allocator* g_allocator; uint64_t HHDMBase; }; @@ -212,14 +220,6 @@ extern "C" void kmain() { fb_ptr[i * (framebuffer->pitch / 4) + (i - 5*5)] = 0xFF0000; // Red fb_ptr[i * (framebuffer->pitch / 4) + (i - 10*5)] = 0x00FF00; // Green fb_ptr[i * (framebuffer->pitch / 4) + (i - 15*5)] = 0x0000FF; // Blue - - // fb_ptr[i * (framebuffer->pitch / 4) + (i - 20*5)] = 0xFF0000; // Red - // fb_ptr[i * (framebuffer->pitch / 4) + (i - 25*5)] = 0x00FF00; // Green - // fb_ptr[i * (framebuffer->pitch / 4) + (i - 30*5)] = 0x0000FF; // Blue - - // fb_ptr[i * (framebuffer->pitch / 4) + (i - 35*5)] = 0xFF0000; // Red - // fb_ptr[i * (framebuffer->pitch / 4) + (i - 40*5)] = 0x00FF00; // Green - // fb_ptr[i * (framebuffer->pitch / 4) + (i - 45*5)] = 0x0000FF; // Blue } uint64_t hhdm_offset = hhdm_request.response->offset; @@ -235,15 +235,15 @@ extern "C" void kmain() { } if (memmap_request.response != nullptr) { - auto result = Memory::Scan(memmap_request.response); - auto allocator = Memory::PageAllocator(result); + kout << "[Mem] Creating Allocator for system conventional memory" << newline; - kout << "[Mem] Creating PageAllocator for system conventional memory" << newline; - Memory::KernelPFA = &allocator; + auto result = Memory::Scan(memmap_request.response); + auto allocator = Memory::Allocator(result); + + Memory::g_allocator = &allocator; } else { Panic("Guru Meditation Error: System memory map missing!", System::Registers{}); } - hcf(); }