Compare commits

..

No commits in common. "662afad426bc2c96caefedb0c1455f3cd9c0661c" and "559d074ce4cb30f9fc79cecfe31254c17c10727d" have entirely different histories.

10 changed files with 26 additions and 177 deletions

View File

@ -1,10 +1,9 @@
#pragma once #pragma once
#include "memory/Paging.h" #include "memory/Paging.h"
#include "utils/Result.h"
struct AddressSpace struct AddressSpace
{ {
static Result<AddressSpace> create(); static AddressSpace create();
void destroy(); void destroy();

View File

@ -1,13 +1,15 @@
#pragma once #pragma once
#include "utils/Result.h"
#include <stdint.h> #include <stdint.h>
#define PMM_FAILED (void*)-1
#define PMM_DID_FAIL(addr) (void*)addr == PMM_FAILED
namespace PMM namespace PMM
{ {
void init(); void init();
Result<void*> request_page(); void* request_page();
Result<void*> request_pages(uint64_t count); void* request_pages(uint64_t count);
void free_page(void* address); void free_page(void* address);
void free_pages(void* address, uint64_t count); void free_pages(void* address, uint64_t count);

View File

@ -1,125 +0,0 @@
#pragma once
#include "std/ensure.h"
#include "std/string.h"
#include "utils/move.h"
#include "utils/new.h"
struct Error
{
Error(int err)
{
error = err;
}
int error;
};
template <typename T> class Result
{
public:
Result(const T& value)
{
m_storage.store_reference(value);
m_has_value = true;
m_has_error = false;
}
Result(T&& value)
{
m_storage.store_movable_reference(move(value));
m_has_value = true;
m_has_error = false;
}
Result(const Result<T>& other)
{
m_storage.store_reference(other.m_storage.fetch_reference());
m_has_value = true;
m_has_error = false;
}
Result(Result<T>&& other)
{
m_storage.store_movable_reference(move(other.m_storage.fetch_reference()));
m_has_value = true;
m_has_error = false;
}
Result(const Error& err)
{
m_error = err.error;
m_has_error = true;
m_has_value = false;
}
bool has_error()
{
return m_has_error;
}
bool has_value()
{
return m_has_value;
}
int error()
{
ensure(has_error());
return m_error;
}
Error release_error()
{
ensure(has_error());
return {m_error};
}
T value()
{
ensure(has_value());
return m_storage.fetch_reference();
}
T release_value()
{
ensure(has_value());
T item = m_storage.fetch_reference();
m_has_value = false;
return move(item);
}
private:
struct Storage
{
unsigned char buffer[sizeof(T)];
T* fetch_ptr()
{
return (T*)buffer;
}
T& fetch_reference()
{
return *fetch_ptr();
}
void store_ptr(T* ptr)
{
new (buffer) T(*ptr);
}
void store_reference(const T& ref)
{
new (buffer) T(ref);
}
void store_movable_reference(T&& ref)
{
new (buffer) T(ref);
}
};
Storage m_storage;
int m_error;
bool m_has_error;
bool m_has_value;
};

View File

@ -1,13 +0,0 @@
#pragma once
#include <stddef.h>
inline void* operator new(size_t, void* p) noexcept
{
return p;
}
inline void* operator new[](size_t, void* p) noexcept
{
return p;
}
inline void operator delete(void*, void*) noexcept {};
inline void operator delete[](void*, void*) noexcept {};

View File

@ -4,17 +4,14 @@
#include "log/Log.h" #include "log/Log.h"
#include "memory/PMM.h" #include "memory/PMM.h"
#include "memory/VMM.h" #include "memory/VMM.h"
#include "std/errno.h"
#include "std/stdlib.h" #include "std/stdlib.h"
#include "std/string.h" #include "std/string.h"
#include "utils/move.h" #include "utils/move.h"
Result<AddressSpace> AddressSpace::create() AddressSpace AddressSpace::create()
{ {
AddressSpace result; AddressSpace result;
auto page = PMM::request_page(); result.m_pml4 = (PageTable*)PMM::request_page();
if (page.has_error()) return page.release_error();
result.m_pml4 = (PageTable*)page.release_value();
memset(result.m_pml4, 0, PAGE_SIZE); memset(result.m_pml4, 0, PAGE_SIZE);
VMM::install_kernel_page_directory_into_address_space(result); VMM::install_kernel_page_directory_into_address_space(result);
return move(result); return move(result);
@ -159,9 +156,8 @@ void AddressSpace::clear()
static PageTable* try_clone_page_table(PageTable* source) static PageTable* try_clone_page_table(PageTable* source)
{ {
auto page = PMM::request_page(); PageTable* dst = (PageTable*)PMM::request_page();
if (page.has_error()) { return 0; } if (PMM_DID_FAIL(dst)) { return 0; }
PageTable* dst = (PageTable*)page.release_value();
memcpy(dst, source, sizeof(PageTable)); memcpy(dst, source, sizeof(PageTable));
return dst; return dst;
} }

View File

@ -10,8 +10,6 @@
#include "misc/utils.h" #include "misc/utils.h"
#include "std/ensure.h" #include "std/ensure.h"
// FIXME: Use Result in here.
void MemoryManager::init() void MemoryManager::init()
{ {
KernelHeap::clear(); KernelHeap::clear();
@ -125,15 +123,15 @@ void* MemoryManager::get_page(int flags)
void* MemoryManager::get_page_at(uint64_t addr, int flags) void* MemoryManager::get_page_at(uint64_t addr, int flags)
{ {
auto paddr = PMM::request_page(); void* physicalAddress = PMM::request_page();
if (paddr.has_error()) if (PMM_DID_FAIL(physicalAddress))
{ {
#ifdef MM_DEBUG #ifdef MM_DEBUG
kwarnln("OOM while allocating one page of memory. this is not good..."); kwarnln("OOM while allocating one page of memory. this is not good...");
#endif #endif
return 0; return 0;
} }
VMM::map(addr, (uint64_t)paddr.release_value(), flags); VMM::map(addr, (uint64_t)physicalAddress, flags);
return (void*)addr; return (void*)addr;
} }
@ -174,19 +172,17 @@ void* MemoryManager::get_pages_at(uint64_t addr, uint64_t count, int flags)
#endif #endif
for (uint64_t i = 0; i < count; i++) for (uint64_t i = 0; i < count; i++)
{ {
auto paddr = PMM::request_page(); void* physicalAddress = PMM::request_page();
if (paddr.has_error()) // OOM: No physical memory available! Since this might be at the end of a if (PMM_DID_FAIL(physicalAddress)) // OOM: No physical memory available! Since this might be at the end of a
// long allocation, we should be able to recover most of it and allocate a // long allocation, we should be able to recover most of it and allocate a
// smaller range, so this might not be fatal. // smaller range, so this might not be fatal.
{ {
#ifdef MM_DEBUG #ifdef MM_DEBUG
kwarnln("OOM while allocating page %ld of memory. this might be recoverable...", i); kwarnln("OOM while allocating page %ld of memory. this might be recoverable...", i);
#endif #endif
// FIXME: Weren't we supposed to free all previously allocated pages, to avoid leaks when failing large
// allocations?
return 0; return 0;
} }
VMM::map(addr + (i * PAGE_SIZE), (uint64_t)paddr.release_value(), flags); VMM::map(addr + (i * PAGE_SIZE), (uint64_t)physicalAddress, flags);
} }
return (void*)addr; return (void*)addr;
} }

View File

@ -7,7 +7,6 @@
#include "memory/MemoryManager.h" #include "memory/MemoryManager.h"
#include "misc/utils.h" #include "misc/utils.h"
#include "std/ensure.h" #include "std/ensure.h"
#include "std/errno.h"
#include "std/string.h" #include "std/string.h"
extern BOOTBOOT bootboot; extern BOOTBOOT bootboot;
@ -84,7 +83,7 @@ static void bitmap_set(uint64_t index, bool value)
if (value) { virtual_bitmap_addr[byteIndex] |= bitIndexer; } if (value) { virtual_bitmap_addr[byteIndex] |= bitIndexer; }
} }
Result<void*> PMM::request_page() void* PMM::request_page()
{ {
for (uint64_t index = start_index; index < (bitmap_size * 8); index++) for (uint64_t index = start_index; index < (bitmap_size * 8); index++)
{ {
@ -96,10 +95,10 @@ Result<void*> PMM::request_page()
return (void*)(index * PAGE_SIZE); return (void*)(index * PAGE_SIZE);
} }
return {ENOMEM}; return PMM_FAILED;
} }
Result<void*> PMM::request_pages(uint64_t count) void* PMM::request_pages(uint64_t count)
{ {
uint64_t contiguous = 0; uint64_t contiguous = 0;
uint64_t contiguous_start = 0; uint64_t contiguous_start = 0;
@ -126,7 +125,7 @@ Result<void*> PMM::request_pages(uint64_t count)
} }
} }
return {ENOMEM}; return PMM_FAILED;
} }
void PMM::free_page(void* address) void PMM::free_page(void* address)

View File

@ -196,9 +196,8 @@ PageDirectoryEntry* VMM::create_pde_if_not_exists(PageTable* root, uint64_t vadd
decompose_vaddr(vaddr, page_index, indexes[2], indexes[1], indexes[0]); decompose_vaddr(vaddr, page_index, indexes[2], indexes[1], indexes[0]);
auto pde_create_if_not_present = [&]() { auto pde_create_if_not_present = [&]() {
auto pt_or_error = PMM::request_page(); pt = (PageTable*)PMM::request_page();
ensure(pt_or_error.has_value()); ensure(!(PMM_DID_FAIL(pt)));
pt = (PageTable*)pt_or_error.release_value();
memset(pt, 0, PAGE_SIZE); memset(pt, 0, PAGE_SIZE);
pde->set_address((uint64_t)pt); pde->set_address((uint64_t)pt);
pde->present = true; pde->present = true;
@ -342,10 +341,7 @@ void VMM::install_kernel_page_directory_into_address_space(AddressSpace& space)
if (!space_last_pdp_pde.present) if (!space_last_pdp_pde.present)
{ {
auto result = PMM::request_page(); space_last_pdp = (PageTable*)PMM::request_page(); // FIXME: Add out-of-memory checks.
ensure(result.has_value()); // FIXME: Propagate this error.
space_last_pdp = (PageTable*)result.release_value();
memset(space_last_pdp, 0, PAGE_SIZE); memset(space_last_pdp, 0, PAGE_SIZE);
space_last_pdp_pde.present = true; space_last_pdp_pde.present = true;

View File

@ -171,7 +171,7 @@ long Scheduler::load_user_task(const char* filename)
Interrupts::pop(); Interrupts::pop();
return -ENOMEM; return -ENOMEM;
} }
new_task->address_space = AddressSpace::create().release_value(); // FIXME: Propagate this error. new_task->address_space = AddressSpace::create();
VMM::switch_to_user_address_space(new_task->address_space); VMM::switch_to_user_address_space(new_task->address_space);
long result; long result;
if ((result = ELFLoader::check_elf_image_from_filesystem(filename)) < 0) if ((result = ELFLoader::check_elf_image_from_filesystem(filename)) < 0)

View File

@ -1,5 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e
unset -f filter-lines unset -f filter-lines
filter-lines() filter-lines()