From: Amelia Coutard Date: Fri, 6 May 2022 22:57:12 +0000 (+0200) Subject: Changed the physical page allocator completely, to make the code simpler X-Git-Url: https://git.ameliathe1st.gay/?a=commitdiff_plain;h=6a6989d4c3cd42c60348b2ff7000da31198c91b0;p=voyage-au-centre-des-fichiers.git Changed the physical page allocator completely, to make the code simpler --- diff --git a/src/boot.S b/src/boot.S index 5c331ef..6cd3e60 100644 --- a/src/boot.S +++ b/src/boot.S @@ -85,11 +85,6 @@ TSS: TSS_END: .set TSS_SIZE, TSS_END - TSS .align 0x1000 -#TODO replace with actual RAM detection -.globl test_ram -test_ram: .quad 256 - .quad 0 - .skip 0x1000 * 256 - 16 # 1MiB RAM PDPT_low: .quad 0x83 .quad 0x83 + 1024 * 1024 * 1024 .skip 0x1000 - 16 @@ -99,6 +94,11 @@ PDPT_high: .skip 0x1000 - 16 .section .bss .align 0x1000 +.globl page_list_one_past_end +page_list_one_past_end: .skip 0x1000 +#TODO replace with actual RAM detection +.globl test_ram +test_ram: .skip 0x1000 * 256 # 1MiB RAM PML4T: .skip 0x1000 phys_mem_map: .skip 0x1000 * 128 - 8 .align 16 diff --git a/src/kernel.cpp b/src/kernel.cpp index 784859f..4b810d9 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -11,9 +11,33 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr ram_ptr = nullptr; + asm("mov $page_list_one_past_end - 0xFFFFFFFF80000000,%0" : "=ri"(ram_ptr)); + return ram_ptr; + })()}; + { + os::phys_ptr ram_ptr = nullptr; + asm("mov $test_ram - 0xFFFFFFFF80000000,%0" : "=ri"(ram_ptr)); + page_allocator.deallocate({.ptr = ram_ptr, .size = 256}); + } + + page_allocator.print_all(); + { + os::println("Alloc #1."); + auto mem1 = page_allocator.allocate(0x10); + page_allocator.print_all(); + os::println("Alloc #2."); + auto mem2 = page_allocator.allocate(0x20); + page_allocator.print_all(); + os::println("Dealloc #1."); + page_allocator.deallocate(mem1); + page_allocator.print_all(); + os::println("Dealloc #2."); + page_allocator.deallocate(mem2); + page_allocator.print_all(); + } os::framebuffer framebuffer; @@ -30,16 +54,19 @@ extern "C" void kmain(unsigned long magic, os::phys_ptr head): head(head.get_phys_addr()) { - phys_ptr prev{nullptr}; - for (auto it = this->head; it != nullptr; prev = it, it = it->next_streak) { - if (prev >= it) { - os::println("Error: unordered memory given to the page allocator."); - break; - } - while (it.get_phys_addr() + it->streak_size * 0x1000 == it->next_streak.get_phys_addr()) { - it->streak_size += it->next_streak->streak_size; - it->next_streak = it->next_streak->next_streak; - } - } +os::paging::page_allocator::page_allocator(phys_ptr one_past_end): begin_(one_past_end.get_phys_addr()), end_(begin_) { + end_->prev = nullptr; + end_->next = nullptr; + end_->size = 1; } void os::paging::page_allocator::print_all() const { - if (head == nullptr) { + if (is_empty()) { os::println("No RAM left."); - } else for (auto it = head; it != nullptr; it = it->next_streak) { + } else for (auto it = begin(); it != end(); it = it->next) { os::print("addr:size = 0x"); os::print(it.get_phys_addr()); os::print(":0x"); - os::print(it->streak_size); + os::print(it->size); os::printc('\n'); } } -os::paging::page_allocator::block os::paging::page_allocator::allocate(uint64_t count) { - phys_ptr prev{nullptr}; - for (auto it = head; it != nullptr; prev = it, it = it->next_streak) { - if (it->streak_size == count) { - if (prev == nullptr) { - head = it->next_streak; - } else { - prev->next_streak = it->next_streak; - } +// void os::paging::page_allocator::mark_as_used(block b); +os::paging::page_allocator::block os::paging::page_allocator::allocate(std::uint64_t count) { + for (auto it = begin(); it != end(); it = it->next) { + if (count == it->size) { + erase(it); return { - .ptr = it.get_phys_addr(), + .ptr = phys_ptr(it.get_phys_addr()), .size = count, }; - } - if (it->streak_size > count) { - if (prev == nullptr) { - head = it.get_phys_addr() + count * 0x1000; - head->streak_size = it->streak_size - count; - head->next_streak = it->next_streak; - } else { - prev->next_streak = it.get_phys_addr() + count * 0x1000; - prev->next_streak->streak_size = it->streak_size - count; - head->next_streak->next_streak = it->next_streak; - } + } else if (count < it->size) { + erase(split_at_offset(it, count)); return { - .ptr = it.get_phys_addr(), + .ptr = phys_ptr(it.get_phys_addr()), .size = count, }; } } - return {.ptr = nullptr, .size = 0}; + return { .ptr = nullptr, .size = 0 }; } - void os::paging::page_allocator::deallocate(block b) { - const phys_ptr ptr = b.ptr.get_phys_addr(); - const uint64_t size = b.size; - + const phys_ptr b_it{b.ptr.get_phys_addr()}; + auto it = begin(); + while (it != end() && it < b_it) { it = it->next; } + try_merge_next(try_merge_prev(insert(it, b))); +} + +bool os::paging::page_allocator::is_empty() const { return begin() == end(); } +os::phys_ptr os::paging::page_allocator::begin() { return begin_; } +os::phys_ptr os::paging::page_allocator::end() { return end_; } +os::phys_ptr os::paging::page_allocator::begin() const { return begin_; } +os::phys_ptr os::paging::page_allocator::end() const { return end_; } - phys_ptr before{nullptr}; - phys_ptr after = head; - while (after != nullptr && after < ptr) { - before = after; - after = after->next_streak; +os::phys_ptr os::paging::page_allocator::insert(phys_ptr it, block b) { + const phys_ptr b_it{b.ptr.get_phys_addr()}; + if (it->prev == nullptr) { + begin_ = b_it; + } else { + it->prev->next = b_it; } - if (before != nullptr && before.get_phys_addr() + 0x1000 * before->streak_size == ptr) { - // Should merge with previous. - if (after != nullptr && ptr.get_phys_addr() + 0x1000 * size == after) { - // Should merge with next. - before->streak_size += size + after->streak_size; - before->next_streak = after->next_streak; - } else { - // Shouldn't merge with next. - before->streak_size += size; - } + b_it->prev = it->prev; + b_it->next = it; + it->prev = b_it; + b_it->size = b.size; + return b_it; +} +os::phys_ptr os::paging::page_allocator::try_merge_prev(phys_ptr it) { + os::assert(it != end(), "end() passed to page_allocator::try_merge_prev(phys_ptr)."); + if (it->prev == nullptr) { return it; } + if (it->prev + it->prev->size != it) { return it; } + it->prev->size += it->size; + return erase(it)->prev; +} +os::phys_ptr os::paging::page_allocator::try_merge_next(phys_ptr it) { + os::assert(it != end(), "end() passed to page_allocator::try_merge_next(phys_ptr)."); + if (it->next == end()) return it; + try_merge_prev(it->next); + return it; +} +os::phys_ptr os::paging::page_allocator::erase(phys_ptr it) { + os::assert(it != end(), "end() passed to page_allocator::remove(phys_ptr)."); + if (it->prev == nullptr) { + begin_ = it->next; } else { - // Shouldn't merge with previous. - if (after != nullptr && ptr.get_phys_addr() + 0x1000 * size == after) { - // Should merge with next. - if (before != nullptr) { - before->next_streak = before->next_streak.get_phys_addr() - 0x1000 * size; - before->next_streak->next_streak = after->next_streak; - before->next_streak->streak_size = after->streak_size + size; - } else { - head = head.get_phys_addr() - 0x1000 * size; - head->next_streak = after->next_streak; - head->streak_size = after->streak_size + size; - } - } else { - // Shouldn't merge with next. - if (before != nullptr) { - before->next_streak = ptr; - ptr->next_streak = after; - ptr->streak_size = size; - } else { - head = ptr; - ptr->next_streak = after; - ptr->streak_size = size; - } - } + it->prev->next = it->next; } + it->next->prev = it->prev; + return it->next; +} +os::phys_ptr os::paging::page_allocator::split_at_offset(phys_ptr it, std::size_t offset) { + os::assert(it != end(), "end() passed to page_allocator::split_at_offset(phys_ptr, std::size_t)."); + os::assert(offset < it->size, "offset passed to page_allocator::split_at_offset(phys_ptr, std::size_t) was too big."); + os::assert(offset != 0, "offset 0 passed to page_allocator::split_at_offset(phys_ptr, std::size_t)."); + phys_ptr after_split = it + offset; + insert(it->next, block{ .ptr = phys_ptr{after_split.get_phys_addr()}, .size = it->size - offset }); + it->size = offset; + return it; } diff --git a/src/paging.hpp b/src/paging.hpp index c2d0fa7..bcdb12d 100644 --- a/src/paging.hpp +++ b/src/paging.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include "serial.hpp" #include "utils.hpp" @@ -36,20 +36,20 @@ public: inline void PK(unsigned v) { os::assert(is_page(), "Error: write to protection key of non-page."); os::assert((v & 0xF) == v, "Error: incorrect protection key."); - data = (data & ~(0xFul << 59)) | (uint64_t(v) << 59); + data = (data & ~(0xFul << 59)) | (std::uint64_t(v) << 59); } inline unsigned AVL_high() { return (data >> 52) & (is_page() ? 0x7F : 0x7FF); } inline void AVL_high(unsigned v) { os::assert((v & (is_page() ? 0x7F : 0x7FF)) == v, "Error: incorrect AVL high bits."); - data = (data & ~((is_page() ? 0x7Ful : 0x7FFul) << 52)) | (uint64_t(v) << 52); + data = (data & ~((is_page() ? 0x7Ful : 0x7FFul) << 52)) | (std::uint64_t(v) << 52); } inline phys_ptr> base_address() { return {data & 0x000FFFFFFFFFF000 & ~(order != 0 && is_page() ? 1ul << 12 : 0ul)}; } inline void base_address(phys_ptr> v) { - const uint64_t v_int = v.get_phys_addr(); + const std::uint64_t v_int = v.get_phys_addr(); os::assert((v_int & 0x000FFFFFFFFFF000 & (0xFFFFFFFFFFFFF000 << (is_page() ? 9 * order : 0))) == v_int, "Error: incorrect base address."); data = (data & ~0x000FFFFFFFFFF000ul & ~(order != 0 && is_page() ? 1ul << 12 : 0ul)) | v_int; } @@ -122,7 +122,7 @@ public: } private: - uint64_t data; + std::uint64_t data; }; template @@ -133,7 +133,7 @@ struct __attribute__((aligned(0x1000))) paging_table { template<> struct paging_table<-1> { - uint8_t contents[0x1000]; + std::uint8_t contents[0x1000]; }; using PML4T = paging_table<3>; @@ -150,24 +150,38 @@ class page_allocator { public: struct block { phys_ptr ptr = nullptr; - uint64_t size; + std::uint64_t size; }; - page_allocator(phys_ptr head); + page_allocator(phys_ptr one_past_end_page); void print_all() const; - block allocate(uint64_t page_count); + void mark_as_used(block b); + block allocate(std::uint64_t page_count); void deallocate(block b); private: struct __attribute__((aligned(0x1000))) page { - uint64_t streak_size; - phys_ptr next_streak; - char padding[0x1000 - 8 - 8]; + phys_ptr prev; + phys_ptr next; + std::uint64_t size; + char padding[0x1000 - 8 * 3]; }; static_assert(sizeof(page) == 0x1000); static_assert(alignof(page) == 0x1000); - phys_ptr head; + phys_ptr begin_; + phys_ptr end_; + + phys_ptr begin(); + phys_ptr end(); + phys_ptr begin() const; + phys_ptr end() const; + bool is_empty() const; + phys_ptr insert(phys_ptr it, block b); + phys_ptr try_merge_prev(phys_ptr it); + phys_ptr try_merge_next(phys_ptr it); + phys_ptr erase(phys_ptr it); + phys_ptr split_at_offset(phys_ptr it, std::size_t offset); }; }} // os::paging