diff --git a/zion/loader/init_loader.cpp b/zion/loader/init_loader.cpp index c7157eb..b6962e4 100644 --- a/zion/loader/init_loader.cpp +++ b/zion/loader/init_loader.cpp @@ -74,10 +74,12 @@ uint64_t LoadElfProgram(Process& dest_proc, uint64_t base, uint64_t offset) { program.type, program.flags, program.offset, program.vaddr, program.paddr, program.filesz, program.memsz, program.align); #endif - auto mem_obj = glcr::MakeRefCounted(program.memsz); + auto mem_obj = glcr::MakeRefCounted(program.memsz); mem_obj->CopyBytesToObject(base + program.offset, program.filesz); - PANIC_ON_ERR(dest_proc.vmas()->MapInMemoryObject(program.vaddr, mem_obj), - "Couldn't map in init program."); + PANIC_ON_ERR( + dest_proc.vmas()->MapInMemoryObject( + program.vaddr, glcr::StaticCastRefPtr(mem_obj)), + "Couldn't map in init program."); } return header->entry; } @@ -121,8 +123,8 @@ const limine_file& GetInitProgram(const glcr::String& path) { void WriteInitProgram(glcr::RefPtr port, glcr::String name, uint64_t id) { const limine_file& prog = GetInitProgram(name); - glcr::RefPtr prog_vmmo = - glcr::MakeRefCounted(prog.size); + glcr::RefPtr prog_vmmo = + glcr::MakeRefCounted(prog.size); prog_vmmo->CopyBytesToObject(reinterpret_cast(prog.address), prog.size); port->WriteKernel(id, MakeRefCounted(prog_vmmo)); @@ -155,8 +157,8 @@ void WriteFramebufferVmmo(glcr::RefPtr port) { .blue_mask_size = buf.blue_mask_size, .blue_mask_shift = buf.blue_mask_shift, }; - glcr::RefPtr ubuf_vmmo = - glcr::MakeRefCounted(sizeof(ubuf)); + glcr::RefPtr ubuf_vmmo = + glcr::MakeRefCounted(sizeof(ubuf)); ubuf_vmmo->CopyBytesToObject(reinterpret_cast(&ubuf), sizeof(ubuf)); port->WriteKernel(Z_BOOT_FRAMEBUFFER_INFO_VMMO, MakeRefCounted(ubuf_vmmo)); diff --git a/zion/object/memory_object.cpp b/zion/object/memory_object.cpp index bfc775a..cefb371 100644 --- a/zion/object/memory_object.cpp +++ b/zion/object/memory_object.cpp @@ -6,30 +6,8 @@ #define K_MEM_DEBUG 0 -MemoryObject::MemoryObject(uint64_t size) : size_(size) { - if ((size & 0xFFF) != 0) { - size_ = (size & ~0xFFF) + 0x1000; -#if K_MEM_DEBUG - dbgln("MemoryObject: aligned {x} to {x}", size, size_); -#endif - } - // FIXME: Do this lazily. - uint64_t num_pages = size_ / 0x1000; - for (uint64_t i = 0; i < num_pages; i++) { - phys_page_list_.PushBack(0); - } -} - -MemoryObject::~MemoryObject() { - for (uint64_t page : phys_page_list_) { - if (page != 0) { - phys_mem::FreePage(page); - } - } -} - uint64_t MemoryObject::PhysicalPageAtOffset(uint64_t offset) { - if (offset > size_) { + if (offset > size()) { panic("Invalid offset"); } uint64_t page_num = offset / 0x1000; @@ -37,8 +15,8 @@ uint64_t MemoryObject::PhysicalPageAtOffset(uint64_t offset) { } void MemoryObject::CopyBytesToObject(uint64_t source, uint64_t length) { - if (length > size_) { - panic("Copy overruns memory object: {x} too large for {x}", length, size_); + if (length > size()) { + panic("Copy overruns memory object: {x} too large for {x}", length, size()); } uint64_t hhdm = boot::GetHigherHalfDirectMap(); uint64_t page_number = 0; @@ -59,21 +37,38 @@ void MemoryObject::CopyBytesToObject(uint64_t source, uint64_t length) { } } -uint64_t MemoryObject::PageNumberToPhysAddr(uint64_t page_num) { - auto iter = phys_page_list_.begin(); - uint64_t index = 0; - while (index < page_num) { - ++iter; - index++; +VariableMemoryObject::VariableMemoryObject(uint64_t size) : size_(size) { + if ((size & 0xFFF) != 0) { + size_ = (size & ~0xFFF) + 0x1000; +#if K_MEM_DEBUG + dbgln("MemoryObject: aligned {x} to {x}", size, size_); +#endif } + // FIXME: Do this lazily. + uint64_t num_pages = size_ / 0x1000; + phys_page_list_ = glcr::Array(num_pages); + for (uint64_t i = 0; i < phys_page_list_.size(); i++) { + phys_page_list_[i] = 0; + } +} - if (*iter == 0) { +VariableMemoryObject::~VariableMemoryObject() { + for (uint64_t p = 0; p < phys_page_list_.size(); p++) { + if (phys_page_list_[p] != 0) { + // TODO: We may be able to do some sort of coalescing here. + phys_mem::FreePage(phys_page_list_[p]); + } + } +} + +uint64_t VariableMemoryObject::PageNumberToPhysAddr(uint64_t page_num) { + if (phys_page_list_[page_num] == 0) { #if K_MEM_DEBUG dbgln("Allocating page num {} for mem object", page_num); #endif - *iter = phys_mem::AllocatePage(); + phys_page_list_[page_num] = phys_mem::AllocatePage(); } - return *iter; + return phys_page_list_[page_num]; } FixedMemoryObject::~FixedMemoryObject() { diff --git a/zion/object/memory_object.h b/zion/object/memory_object.h index fc4f653..3c39c4a 100644 --- a/zion/object/memory_object.h +++ b/zion/object/memory_object.h @@ -1,10 +1,11 @@ #pragma once -#include +#include #include #include #include "include/ztypes.h" +#include "memory/constants.h" #include "object/kernel_object.h" class MemoryObject; @@ -27,32 +28,41 @@ class MemoryObject : public KernelObject { kZionPerm_Transmit; } - explicit MemoryObject(uint64_t size); - ~MemoryObject(); + MemoryObject() = default; + virtual ~MemoryObject() = default; - uint64_t size() { return size_; } - uint64_t num_pages() { return ((size_ - 1) / 0x1000) + 1; } + virtual uint64_t size() = 0; + uint64_t num_pages() { return ((size() - 1) / kPageSize) + 1; } + virtual glcr::ErrorOr> Duplicate( + uint64_t offset, uint64_t length) = 0; uint64_t PhysicalPageAtOffset(uint64_t offset); - void CopyBytesToObject(uint64_t source, uint64_t length); - virtual glcr::ErrorOr> Duplicate(uint64_t offset, - uint64_t length) { + protected: + virtual uint64_t PageNumberToPhysAddr(uint64_t page_num) = 0; +}; + +class VariableMemoryObject : public MemoryObject { + public: + explicit VariableMemoryObject(uint64_t size); + ~VariableMemoryObject() override; + + uint64_t size() override { return size_; } + + virtual glcr::ErrorOr> Duplicate( + uint64_t offset, uint64_t length) override { return glcr::UNIMPLEMENTED; } protected: - // Hacky to avoid linked_list creation. - MemoryObject(uint64_t size, bool) : size_(size) {} + virtual uint64_t PageNumberToPhysAddr(uint64_t page_num) override; private: // Always stores the full page-aligned size. uint64_t size_; - virtual uint64_t PageNumberToPhysAddr(uint64_t page_num); - - glcr::LinkedList phys_page_list_; + glcr::Array phys_page_list_; }; class FixedMemoryObject : public MemoryObject { @@ -60,20 +70,21 @@ class FixedMemoryObject : public MemoryObject { // FIXME: Validate that this is 4k aligned. // Create a new class object for should free. FixedMemoryObject(uint64_t physical_addr, uint64_t size, bool should_free) - : MemoryObject(size, true), - physical_addr_(physical_addr), - should_free_(should_free) {} + : size_(size), physical_addr_(physical_addr), should_free_(should_free) {} - ~FixedMemoryObject(); + ~FixedMemoryObject() override; + virtual uint64_t size() override { return size_; } virtual glcr::ErrorOr> Duplicate( uint64_t offset, uint64_t length) override; + protected: + uint64_t PageNumberToPhysAddr(uint64_t page_num) override { + return physical_addr_ + (kPageSize * page_num); + } + private: + uint64_t size_; uint64_t physical_addr_; bool should_free_; - - uint64_t PageNumberToPhysAddr(uint64_t page_num) override { - return physical_addr_ + (0x1000 * page_num); - } }; diff --git a/zion/syscall/memory_object.cpp b/zion/syscall/memory_object.cpp index b358ee8..eebd12f 100644 --- a/zion/syscall/memory_object.cpp +++ b/zion/syscall/memory_object.cpp @@ -6,8 +6,8 @@ z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req) { auto& curr_proc = gScheduler->CurrentProcess(); - *req->vmmo_cap = - curr_proc.AddNewCapability(glcr::MakeRefCounted(req->size)); + *req->vmmo_cap = curr_proc.AddNewCapability( + glcr::MakeRefCounted(req->size)); return glcr::OK; }