Compare commits
No commits in common. "662afad426bc2c96caefedb0c1455f3cd9c0661c" and "559d074ce4cb30f9fc79cecfe31254c17c10727d" have entirely different histories.
662afad426
...
559d074ce4
@ -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();
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
|
||||||
};
|
|
@ -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 {};
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user