feat: start adding physical memory allocator
This commit is contained in:
parent
8dc53f662e
commit
e2ea22ad53
15 changed files with 440 additions and 38 deletions
10
kernel/src/init/cxxabi.cpp
Normal file
10
kernel/src/init/cxxabi.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
extern "C" {
|
||||
|
||||
void __cxa_pure_virtual() {
|
||||
for (;;) {
|
||||
__asm__ volatile("cli; hlt");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,9 +3,10 @@
|
|||
#include "init/init.h"
|
||||
#include "init/multiboot2.h"
|
||||
#include "init/print.h"
|
||||
#include "memory/allocator.h"
|
||||
|
||||
[[maybe_unused]] [[noreturn]] __attribute__((used)) static void halt() {
|
||||
while (true) __asm__ volatile ("");
|
||||
while (true) __asm__ volatile ("hlt");
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[noreturn]] __attribute__((used)) static void panic(const char* msg) {
|
||||
|
|
@ -13,40 +14,116 @@
|
|||
halt();
|
||||
}
|
||||
|
||||
static int step_depth = 0;
|
||||
template<typename T>
|
||||
static void step(const char* name, T&& fn) {
|
||||
print("Starting ", {});
|
||||
print(name, {});
|
||||
print("\n", {});
|
||||
for(int i = 0; i < step_depth; ++i) {
|
||||
print(" ");
|
||||
}
|
||||
print("Starting ");
|
||||
print(name);
|
||||
print("\n");
|
||||
++step_depth;
|
||||
fn();
|
||||
print("Finished ", {});
|
||||
print(name, {});
|
||||
print("\n", {});
|
||||
--step_depth;
|
||||
for(int i = 0; i < step_depth; ++i) {
|
||||
print(" ");
|
||||
}
|
||||
print("Finished ");
|
||||
print(name);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
optional<paddr_t> findInitialMemoryPage(const multiboot::tag_mmap* multiboot_info) {
|
||||
const auto* base = reinterpret_cast<const uint8_t*>(multiboot_info->entries);
|
||||
const auto* end = reinterpret_cast<const uint8_t*>(multiboot_info) + multiboot_info->size;
|
||||
for (const auto* ptr = base; ptr < end; ptr += multiboot_info->entry_size) {
|
||||
const auto* entry = reinterpret_cast<const multiboot::mem_entry*>(ptr);
|
||||
if(entry->type != multiboot::mem_type::available) {
|
||||
continue;
|
||||
}
|
||||
auto start_ptr = (entry->addr + page_size - 1) & (~page_size);
|
||||
auto end_ptr = (entry->addr + entry->len) & (~page_size);
|
||||
auto size = end_ptr - start_ptr;
|
||||
if(size < page_size) {
|
||||
continue;
|
||||
}
|
||||
for(auto ptr = start_ptr; ptr < end_ptr; ptr += page_size) {
|
||||
if(!is_in_reserved_section(paddr_t{ptr}, page_size)) {
|
||||
return paddr_t{ptr};
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void PhysicalAllocator::init(const multiboot::tag_mmap* multiboot_info) {
|
||||
PhysicalAllocator alloc;
|
||||
auto page_opt = findInitialMemoryPage(multiboot_info);
|
||||
if(!page_opt.has_value()) {
|
||||
panic("System could not find enough valid ram!");
|
||||
}
|
||||
auto page = page_opt.value();
|
||||
memset(page.access<uint8_t*>(), 0, page_size);
|
||||
alloc.storage = page.access<PhysicalAllocator::Page>();
|
||||
|
||||
alloc.storage->entries[0].page_count=68719476736;
|
||||
alloc.storage->entries[0].owner=pid_reserved;
|
||||
|
||||
step("multiboot", [&]() {
|
||||
const auto* base = reinterpret_cast<const uint8_t*>(multiboot_info->entries);
|
||||
const auto* end = reinterpret_cast<const uint8_t*>(multiboot_info) + multiboot_info->size;
|
||||
for (const auto* ptr = base; ptr < end; ptr += multiboot_info->entry_size) {
|
||||
const auto* entry = reinterpret_cast<const multiboot::mem_entry*>(ptr);
|
||||
if(entry->type!=multiboot::mem_type::available) {
|
||||
continue;
|
||||
}
|
||||
auto start_ptr = (entry->addr + page_size - 1) & (~page_size);
|
||||
auto end_ptr = (entry->addr + entry->len) & (~page_size);
|
||||
auto size = end_ptr - start_ptr;
|
||||
alloc.storage->forceEntry({size/page_size, pid_free});
|
||||
}
|
||||
});
|
||||
step("reserved_sections", [&]() {
|
||||
for_each_reserved_section([&](const KernelSection& section){
|
||||
if(section.vma_start == section.vma_end) {
|
||||
return;
|
||||
}
|
||||
auto start_ptr = (section.phys_start().address) & (~page_size);
|
||||
auto end_ptr = (section.phys_end().address + page_size - 1) & (~page_size);
|
||||
auto size = end_ptr - start_ptr;
|
||||
alloc.storage->forceEntry({size/page_size, pid_kernel});
|
||||
});
|
||||
});
|
||||
alloc.storage->cleanup();
|
||||
alloc.storage->compact();
|
||||
PhysicalAllocator::getInstance() = alloc;
|
||||
}
|
||||
|
||||
static void loadMultiboot() {
|
||||
multiboot::visit_all(overloaded{
|
||||
[](const multiboot::tag_mmap* mem) {
|
||||
print("Tag Memory\n", {});
|
||||
print("Tag Memory Map\n");
|
||||
step("memory setup", [mem](){PhysicalAllocator::init(mem);});
|
||||
},
|
||||
[](const multiboot::tag_string* str) {
|
||||
print("Tag String (0x", {});
|
||||
print_hex(static_cast<uint64_t>(str->type), {});
|
||||
print("): ", {});
|
||||
print(str->string, {});
|
||||
print("\n", {});
|
||||
print("Tag String (");
|
||||
print(multiboot::get_tag_name(str->type));
|
||||
print("): ");
|
||||
print(str->string);
|
||||
print("\n");
|
||||
},
|
||||
[](const auto* tag) {
|
||||
print("Tag (0x", {});
|
||||
print_hex(static_cast<uint64_t>(tag->type), {});
|
||||
print(")\n", {});
|
||||
print("Tag ");
|
||||
print(multiboot::get_tag_name(tag->type));
|
||||
print("\n");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[noreturn]] __attribute__((used)) void init() {
|
||||
initFromLow();
|
||||
print("Reached init\n", {});
|
||||
print("Reached init\n");
|
||||
step("multiboot", loadMultiboot);
|
||||
halt();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ static constexpr int VGA_COLS = 80;
|
|||
static constexpr int VGA_ROWS = 25;
|
||||
static constexpr int BYTES_PER_CELL = 2;
|
||||
static constexpr int BYTES_PER_ROW = VGA_COLS * BYTES_PER_CELL;
|
||||
static constexpr int SCREEN_BYTES = BYTES_PER_ROW * VGA_ROWS;
|
||||
static constexpr int HEX_BITS = 4;
|
||||
static constexpr int HEX_TOP_SHIFT = (sizeof(uint64_t) * 8) - HEX_BITS;
|
||||
|
||||
|
|
@ -17,8 +18,23 @@ static volatile uint16_t* vga_cell(uint32_t offset) {
|
|||
return paddr_t{VGA_PHYS_BASE + offset}.access<volatile uint16_t>();
|
||||
}
|
||||
|
||||
static void scroll() {
|
||||
// Shift every row up by one.
|
||||
for (int i = 0; i < (VGA_ROWS - 1) * VGA_COLS; i++) {
|
||||
*vga_cell(i * BYTES_PER_CELL) = *vga_cell((i + VGA_COLS) * BYTES_PER_CELL);
|
||||
}
|
||||
// Clear the last row.
|
||||
for (int i = (VGA_ROWS - 1) * VGA_COLS; i < VGA_ROWS * VGA_COLS; i++) {
|
||||
*vga_cell(i * BYTES_PER_CELL) = 0;
|
||||
}
|
||||
cursor -= BYTES_PER_ROW;
|
||||
}
|
||||
|
||||
static void next_line() {
|
||||
cursor = ((cursor + BYTES_PER_ROW - 1) / BYTES_PER_ROW) * BYTES_PER_ROW;
|
||||
while (cursor >= SCREEN_BYTES) {
|
||||
scroll();
|
||||
}
|
||||
}
|
||||
|
||||
static void put_char(char ch, uint16_t attr_word) {
|
||||
|
|
@ -26,6 +42,9 @@ static void put_char(char ch, uint16_t attr_word) {
|
|||
next_line();
|
||||
return;
|
||||
}
|
||||
while (cursor >= SCREEN_BYTES) {
|
||||
scroll();
|
||||
}
|
||||
*vga_cell(cursor) = attr_word | (uint16_t)ch;
|
||||
cursor += BYTES_PER_CELL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,9 @@ RESERVE_SECTION(boot);
|
|||
RESERVE_SECTION(startup_text);
|
||||
RESERVE_SECTION(startup_data);
|
||||
RESERVE_SECTION(text);
|
||||
RESERVE_SECTION(rodata);
|
||||
RESERVE_SECTION(rodata); // covers the nested .reserved_ranges array
|
||||
RESERVE_SECTION(data);
|
||||
RESERVE_SECTION(bss);
|
||||
[[maybe_unused]] static const KernelSection _rsv_reserved_ranges
|
||||
__attribute__((section(".reserved_ranges"), used)) = {
|
||||
(uint64_t)__reserved_ranges_start__,
|
||||
(uint64_t)__reserved_ranges_end__,
|
||||
"reserved_ranges"
|
||||
};
|
||||
RESERVE_SECTION(trampoline_text);
|
||||
RESERVE_SECTION(trampoline_data);
|
||||
RESERVE_SECTION(trampoline_bss);
|
||||
|
|
|
|||
16
kernel/src/memory/allocator.cpp
Normal file
16
kernel/src/memory/allocator.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include "memory/allocator.h"
|
||||
#include "util/optional.h"
|
||||
|
||||
static PhysicalAllocator allocator{};
|
||||
|
||||
PhysicalAllocator& PhysicalAllocator::getInstance() {
|
||||
return allocator;
|
||||
}
|
||||
|
||||
PhysicalAllocator::allocation_t PhysicalAllocator::allocPages(size_t count, pid_t owner) {
|
||||
|
||||
}
|
||||
|
||||
void PhysicalAllocator::free(allocation_t ptr) {
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +1,24 @@
|
|||
#include "init/init.h"
|
||||
#include "memory/pointer.h"
|
||||
|
||||
extern "C" {
|
||||
// Linker-defined bounds of the (NOLOAD) .bss section and the .init_array of
|
||||
// global constructors. See linker.ld.
|
||||
extern char __bss_start__[];
|
||||
extern char __bss_end__[];
|
||||
|
||||
using constructor_t = void (*)();
|
||||
extern constructor_t __init_array_start__[];
|
||||
extern constructor_t __init_array_end__[];
|
||||
}
|
||||
|
||||
extern "C" [[maybe_unused]] [[noreturn]] __attribute__((used)) void __entry64() {
|
||||
memset(__bss_start__, 0, static_cast<size_t>(__bss_end__ - __bss_start__));
|
||||
for (constructor_t* ctor = __init_array_start__; ctor != __init_array_end__; ++ctor) {
|
||||
(*ctor)();
|
||||
}
|
||||
init();
|
||||
while (true) __asm__ volatile ("");
|
||||
while (true) __asm__ volatile ("hlt");
|
||||
}
|
||||
|
||||
asm(R"(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue