aboutsummaryrefslogtreecommitdiffstats
path: root/memory.cpp
blob: 59e2bbeb9a20a3c4918b879e8a25403952d13c54 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#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);
}

void operator delete(void *ptr)
{

}

void operator delete[](void *ptr)
{

}