aboutsummaryrefslogtreecommitdiffstats
path: root/memory.cpp
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2024-09-27 06:02:49 -0400
committerClyne Sullivan <clyne@bitgloo.com>2024-09-27 06:02:49 -0400
commitd43d7caf15a01dd9c2ef1d9e975df3ef7c4e9204 (patch)
treeaaf1f0f3a18b6f7b3fc25022e06941a9fb4fa612 /memory.cpp
wip: initial commit
Diffstat (limited to 'memory.cpp')
-rw-r--r--memory.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/memory.cpp b/memory.cpp
new file mode 100644
index 0000000..2cc15be
--- /dev/null
+++ b/memory.cpp
@@ -0,0 +1,87 @@
+#include "textoutput.hpp"
+
+#include <array>
+#include <cstdint>
+
+struct PageDirectory
+{
+ static constexpr std::uint32_t NotPresent = 0x2;
+
+ PageDirectory(): value(NotPresent) {}
+ PageDirectory(void *addr): value(reinterpret_cast<std::uint32_t>(addr) | 3) {}
+
+ std::uint32_t value;
+};
+static_assert(sizeof(PageDirectory) == sizeof(std::uint32_t));
+
+extern std::uint32_t lowerMem;
+extern std::uint32_t upperMem;
+extern TextOutput& term;
+
+static std::uintptr_t lowerFree = 0x400;
+static std::uintptr_t upperFree = 0x100000;
+
+alignas(4096)
+static std::array<PageDirectory, 1024> pageDirectory;
+
+alignas(4096)
+static std::array<std::uint32_t, 1024> pageTable;
+
+void memory_initialize()
+{
+ lowerMem -= 1024;
+
+ const auto totalKb = (lowerMem + upperMem) / 1024u;
+
+ term.write("Claiming ");
+ term.write(totalKb);
+ term.write(" kB for allocations...\n");
+
+ std::uint32_t addr = 0;
+ for (auto& p : pageTable) {
+ p = addr | 3; // supervisor, r/w, present
+ addr += 0x1000;
+ }
+
+ pageDirectory[0] = PageDirectory(pageTable.data());
+
+ asm volatile(R"(
+ mov %%eax, %%cr3
+ mov %%cr0, %%eax
+ or $0x80000000, %%eax
+ mov %%eax, %%cr0
+ )" :: "a"(pageDirectory.data()));
+
+ term.write("Paging enabled.\n");
+}
+
+static void *memory_alloc(std::size_t size)
+{
+ void *ret = nullptr;
+
+ if (lowerMem > size) {
+ ret = reinterpret_cast<void *>(lowerFree);
+ lowerFree += size;
+ lowerMem -= size;
+ } else if (upperMem > size) {
+ ret = reinterpret_cast<void *>(upperFree);
+ upperFree += size;
+ upperMem -= size;
+ } else {
+ // Uh oh!
+ term.write("!!! Kernel allocation failed !!!");
+ }
+
+ return ret;
+}
+
+void *operator new(std::size_t size)
+{
+ return memory_alloc(size);
+}
+
+void *operator new[](std::size_t size)
+{
+ return memory_alloc(size);
+}
+