Compare commits

..

No commits in common. "12ca4e4e8947af8e70616dcb21753582f8217bea" and "126482f3e84d575cab9570375e8f6e08b83237e8" have entirely different histories.

4 changed files with 79 additions and 106 deletions

View File

@ -74,12 +74,10 @@ uint64_t LoadElfProgram(Process& dest_proc, uint64_t base, uint64_t offset) {
program.type, program.flags, program.offset, program.vaddr, program.type, program.flags, program.offset, program.vaddr,
program.paddr, program.filesz, program.memsz, program.align); program.paddr, program.filesz, program.memsz, program.align);
#endif #endif
auto mem_obj = glcr::MakeRefCounted<VariableMemoryObject>(program.memsz); auto mem_obj = glcr::MakeRefCounted<MemoryObject>(program.memsz);
mem_obj->CopyBytesToObject(base + program.offset, program.filesz); mem_obj->CopyBytesToObject(base + program.offset, program.filesz);
PANIC_ON_ERR( PANIC_ON_ERR(dest_proc.vmas()->MapInMemoryObject(program.vaddr, mem_obj),
dest_proc.vmas()->MapInMemoryObject( "Couldn't map in init program.");
program.vaddr, glcr::StaticCastRefPtr<MemoryObject>(mem_obj)),
"Couldn't map in init program.");
} }
return header->entry; return header->entry;
} }
@ -123,8 +121,8 @@ const limine_file& GetInitProgram(const glcr::String& path) {
void WriteInitProgram(glcr::RefPtr<Port> port, glcr::String name, uint64_t id) { void WriteInitProgram(glcr::RefPtr<Port> port, glcr::String name, uint64_t id) {
const limine_file& prog = GetInitProgram(name); const limine_file& prog = GetInitProgram(name);
glcr::RefPtr<VariableMemoryObject> prog_vmmo = glcr::RefPtr<MemoryObject> prog_vmmo =
glcr::MakeRefCounted<VariableMemoryObject>(prog.size); glcr::MakeRefCounted<MemoryObject>(prog.size);
prog_vmmo->CopyBytesToObject(reinterpret_cast<uint64_t>(prog.address), prog_vmmo->CopyBytesToObject(reinterpret_cast<uint64_t>(prog.address),
prog.size); prog.size);
port->WriteKernel(id, MakeRefCounted<Capability>(prog_vmmo)); port->WriteKernel(id, MakeRefCounted<Capability>(prog_vmmo));
@ -132,8 +130,8 @@ void WriteInitProgram(glcr::RefPtr<Port> port, glcr::String name, uint64_t id) {
glcr::ErrorCode WritePciVmmo(glcr::RefPtr<Port> port, uint64_t id) { glcr::ErrorCode WritePciVmmo(glcr::RefPtr<Port> port, uint64_t id) {
ASSIGN_OR_RETURN(PcieConfiguration config, GetPciExtendedConfiguration()); ASSIGN_OR_RETURN(PcieConfiguration config, GetPciExtendedConfiguration());
auto vmmo = auto vmmo = glcr::MakeRefCounted<FixedMemoryObject>(config.base,
glcr::MakeRefCounted<ViewMemoryObject>(config.base, config.offset); config.offset, false);
port->WriteKernel(id, MakeRefCounted<Capability>(vmmo)); port->WriteKernel(id, MakeRefCounted<Capability>(vmmo));
@ -157,8 +155,8 @@ void WriteFramebufferVmmo(glcr::RefPtr<Port> port) {
.blue_mask_size = buf.blue_mask_size, .blue_mask_size = buf.blue_mask_size,
.blue_mask_shift = buf.blue_mask_shift, .blue_mask_shift = buf.blue_mask_shift,
}; };
glcr::RefPtr<VariableMemoryObject> ubuf_vmmo = glcr::RefPtr<MemoryObject> ubuf_vmmo =
glcr::MakeRefCounted<VariableMemoryObject>(sizeof(ubuf)); glcr::MakeRefCounted<MemoryObject>(sizeof(ubuf));
ubuf_vmmo->CopyBytesToObject(reinterpret_cast<uint64_t>(&ubuf), sizeof(ubuf)); ubuf_vmmo->CopyBytesToObject(reinterpret_cast<uint64_t>(&ubuf), sizeof(ubuf));
port->WriteKernel(Z_BOOT_FRAMEBUFFER_INFO_VMMO, port->WriteKernel(Z_BOOT_FRAMEBUFFER_INFO_VMMO,
MakeRefCounted<Capability>(ubuf_vmmo)); MakeRefCounted<Capability>(ubuf_vmmo));

View File

@ -6,8 +6,30 @@
#define K_MEM_DEBUG 0 #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) { uint64_t MemoryObject::PhysicalPageAtOffset(uint64_t offset) {
if (offset > size()) { if (offset > size_) {
panic("Invalid offset"); panic("Invalid offset");
} }
uint64_t page_num = offset / 0x1000; uint64_t page_num = offset / 0x1000;
@ -15,8 +37,8 @@ uint64_t MemoryObject::PhysicalPageAtOffset(uint64_t offset) {
} }
void MemoryObject::CopyBytesToObject(uint64_t source, uint64_t length) { void MemoryObject::CopyBytesToObject(uint64_t source, uint64_t length) {
if (length > size()) { if (length > size_) {
panic("Copy overruns memory object: {x} too large for {x}", length, size()); panic("Copy overruns memory object: {x} too large for {x}", length, size_);
} }
uint64_t hhdm = boot::GetHigherHalfDirectMap(); uint64_t hhdm = boot::GetHigherHalfDirectMap();
uint64_t page_number = 0; uint64_t page_number = 0;
@ -37,50 +59,36 @@ void MemoryObject::CopyBytesToObject(uint64_t source, uint64_t length) {
} }
} }
VariableMemoryObject::VariableMemoryObject(uint64_t size) : size_(size) { uint64_t MemoryObject::PageNumberToPhysAddr(uint64_t page_num) {
if ((size & 0xFFF) != 0) { auto iter = phys_page_list_.begin();
size_ = (size & ~0xFFF) + 0x1000; uint64_t index = 0;
#if K_MEM_DEBUG while (index < page_num) {
dbgln("MemoryObject: aligned {x} to {x}", size, size_); ++iter;
#endif index++;
} }
// FIXME: Do this lazily.
uint64_t num_pages = size_ / 0x1000;
phys_page_list_ = glcr::Array<uint64_t>(num_pages);
for (uint64_t i = 0; i < phys_page_list_.size(); i++) {
phys_page_list_[i] = 0;
}
}
VariableMemoryObject::~VariableMemoryObject() { if (*iter == 0) {
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 #if K_MEM_DEBUG
dbgln("Allocating page num {} for mem object", page_num); dbgln("Allocating page num {} for mem object", page_num);
#endif #endif
phys_page_list_[page_num] = phys_mem::AllocatePage(); *iter = phys_mem::AllocatePage();
} }
return phys_page_list_[page_num]; return *iter;
} }
FixedMemoryObject::~FixedMemoryObject() { FixedMemoryObject::~FixedMemoryObject() {
phys_mem::FreePages(physical_addr_, num_pages()); if (should_free_) {
phys_mem::FreePages(physical_addr_, num_pages());
}
} }
glcr::ErrorOr<glcr::RefPtr<MemoryObject>> ViewMemoryObject::Duplicate( glcr::ErrorOr<glcr::RefPtr<MemoryObject>> FixedMemoryObject::Duplicate(
uint64_t offset, uint64_t length) { uint64_t offset, uint64_t length) {
if (offset + length > size()) { if (offset + length > size()) {
return glcr::INVALID_ARGUMENT; return glcr::INVALID_ARGUMENT;
} }
return glcr::StaticCastRefPtr<MemoryObject>( return glcr::StaticCastRefPtr<MemoryObject>(
glcr::MakeRefCounted<ViewMemoryObject>(physical_addr_ + offset, length)); glcr::MakeRefCounted<FixedMemoryObject>(physical_addr_ + offset, length,
false));
} }

View File

@ -1,11 +1,10 @@
#pragma once #pragma once
#include <glacier/container/array.h> #include <glacier/container/linked_list.h>
#include <glacier/memory/ref_ptr.h> #include <glacier/memory/ref_ptr.h>
#include <glacier/status/error_or.h> #include <glacier/status/error_or.h>
#include "include/ztypes.h" #include "include/ztypes.h"
#include "memory/constants.h"
#include "object/kernel_object.h" #include "object/kernel_object.h"
class MemoryObject; class MemoryObject;
@ -28,87 +27,53 @@ class MemoryObject : public KernelObject {
kZionPerm_Transmit; kZionPerm_Transmit;
} }
MemoryObject() = default; explicit MemoryObject(uint64_t size);
virtual ~MemoryObject() = default; ~MemoryObject();
virtual uint64_t size() = 0; uint64_t size() { return size_; }
uint64_t num_pages() { return ((size() - 1) / kPageSize) + 1; } uint64_t num_pages() { return ((size_ - 1) / 0x1000) + 1; }
virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate(
uint64_t offset, uint64_t length) = 0;
uint64_t PhysicalPageAtOffset(uint64_t offset); uint64_t PhysicalPageAtOffset(uint64_t offset);
void CopyBytesToObject(uint64_t source, uint64_t length); void CopyBytesToObject(uint64_t source, uint64_t length);
protected: virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate(uint64_t offset,
virtual uint64_t PageNumberToPhysAddr(uint64_t page_num) = 0; uint64_t length) {
};
class VariableMemoryObject : public MemoryObject {
public:
explicit VariableMemoryObject(uint64_t size);
~VariableMemoryObject() override;
uint64_t size() override { return size_; }
virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate(
uint64_t offset, uint64_t length) override {
return glcr::UNIMPLEMENTED; return glcr::UNIMPLEMENTED;
} }
protected: protected:
virtual uint64_t PageNumberToPhysAddr(uint64_t page_num) override; // Hacky to avoid linked_list creation.
MemoryObject(uint64_t size, bool) : size_(size) {}
private: private:
// Always stores the full page-aligned size. // Always stores the full page-aligned size.
uint64_t size_; uint64_t size_;
glcr::Array<uint64_t> phys_page_list_; virtual uint64_t PageNumberToPhysAddr(uint64_t page_num);
glcr::LinkedList<uint64_t> phys_page_list_;
}; };
class FixedMemoryObject : public MemoryObject { class FixedMemoryObject : public MemoryObject {
public: public:
// FIXME: Validate that this is 4k aligned. // FIXME: Validate that this is 4k aligned.
FixedMemoryObject(uint64_t physical_addr, uint64_t size) // Create a new class object for should free.
: size_(size), physical_addr_(physical_addr) {} FixedMemoryObject(uint64_t physical_addr, uint64_t size, bool should_free)
: MemoryObject(size, true),
physical_addr_(physical_addr),
should_free_(should_free) {}
~FixedMemoryObject() override; ~FixedMemoryObject();
virtual uint64_t size() override { return size_; }
virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate(
uint64_t offset, uint64_t length) override {
return glcr::UNIMPLEMENTED;
}
protected:
uint64_t PageNumberToPhysAddr(uint64_t page_num) override {
return physical_addr_ + (kPageSize * page_num);
}
private:
uint64_t size_;
uint64_t physical_addr_;
};
// Like a FixedMemoryObject except it doesn't release
// it's pages when it is done. Should be used for things
// like HBAs and the PCI config space.
class ViewMemoryObject : public MemoryObject {
public:
ViewMemoryObject(uint64_t physical_addr, uint64_t size)
: size_(size), physical_addr_(physical_addr) {}
~ViewMemoryObject(){};
virtual uint64_t size() override { return size_; }
virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate( virtual glcr::ErrorOr<glcr::RefPtr<MemoryObject>> Duplicate(
uint64_t offset, uint64_t length) override; uint64_t offset, uint64_t length) override;
protected:
uint64_t PageNumberToPhysAddr(uint64_t page_num) override {
return physical_addr_ + (kPageSize * page_num);
}
private: private:
uint64_t size_;
uint64_t physical_addr_; uint64_t physical_addr_;
bool should_free_;
uint64_t PageNumberToPhysAddr(uint64_t page_num) override {
return physical_addr_ + (0x1000 * page_num);
}
}; };

View File

@ -6,15 +6,16 @@
z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req) { z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
*req->vmmo_cap = curr_proc.AddNewCapability( *req->vmmo_cap =
glcr::MakeRefCounted<VariableMemoryObject>(req->size)); curr_proc.AddNewCapability(glcr::MakeRefCounted<MemoryObject>(req->size));
return glcr::OK; return glcr::OK;
} }
z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req) { z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
uint64_t paddr = req->paddr; uint64_t paddr = req->paddr;
auto vmmo_ref = glcr::MakeRefCounted<ViewMemoryObject>(paddr, req->size); auto vmmo_ref =
glcr::MakeRefCounted<FixedMemoryObject>(paddr, req->size, false);
*req->vmmo_cap = *req->vmmo_cap =
curr_proc.AddNewCapability(StaticCastRefPtr<MemoryObject>(vmmo_ref)); curr_proc.AddNewCapability(StaticCastRefPtr<MemoryObject>(vmmo_ref));
return glcr::OK; return glcr::OK;
@ -24,7 +25,8 @@ z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
uint64_t num_pages = ((req->size - 1) / 0x1000) + 1; uint64_t num_pages = ((req->size - 1) / 0x1000) + 1;
uint64_t paddr = phys_mem::AllocateContinuous(num_pages); uint64_t paddr = phys_mem::AllocateContinuous(num_pages);
auto vmmo_ref = glcr::MakeRefCounted<FixedMemoryObject>(paddr, req->size); auto vmmo_ref =
glcr::MakeRefCounted<FixedMemoryObject>(paddr, req->size, true);
*req->vmmo_cap = *req->vmmo_cap =
curr_proc.AddNewCapability(StaticCastRefPtr<MemoryObject>(vmmo_ref)); curr_proc.AddNewCapability(StaticCastRefPtr<MemoryObject>(vmmo_ref));
*req->paddr = paddr; *req->paddr = paddr;