Add a VERY BASIC and hacky way of allocating memory from userspace
All checks were successful
continuous-integration/drone/push Build is passing

Only supports one-page allocations and doesn't have libc wrappers, which means it has to be invoked using syscall().
This commit is contained in:
apio 2023-01-11 23:01:47 +01:00
parent 0e1e15e85a
commit 586ca19b62
Signed by: apio
GPG Key ID: B8A7D06E42258954
7 changed files with 101 additions and 1 deletions

View File

@ -1,6 +1,11 @@
#include <bits/mmap-flags.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
void bye()
{
@ -18,4 +23,18 @@ int main()
for (int i = 0; i < atoi("8"); i++) { console_write(".", 1); }
console_write("\n", 1);
long rc = syscall(SYS_allocate_memory, 4096, PROT_READ | PROT_WRITE);
if (rc < 0)
{
printf("allocate_memory: %s\n", strerror(-rc));
return 1;
}
char* address = (char*)rc;
printf("address: %p\n", address);
printf("memory at address: %c\n", *address);
*address = 'e';
printf("memory at address: %c\n", *address);
syscall(SYS_deallocate_memory, address);
}

View File

@ -19,6 +19,7 @@ set(SOURCES
src/sys/exit.cpp
src/sys/console_write.cpp
src/sys/clock_gettime.cpp
src/sys/allocate_memory.cpp
src/InitRD.cpp
src/ELF.cpp
)

View File

@ -0,0 +1,60 @@
#include "Log.h"
#include "arch/MMU.h"
#include "memory/MemoryManager.h"
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
#include <bits/mmap-flags.h>
#include <luna/Alignment.h>
constexpr uintptr_t USERSPACE_HEAP_BASE = 0x3000000;
Result<u64> sys_allocate_memory(Registers*, SyscallArgs args)
{
usize size = (usize)args[0];
int flags = (int)args[1];
if (size != ARCH_PAGE_SIZE) return err(EINVAL);
if (flags < 0) return err(EINVAL);
if (size == 0) return 0;
Thread* current = Scheduler::current();
if (!current->heap_bitmap.initialized())
{
void* bitmap_location = (void*)TRY(MemoryManager::alloc_for_kernel(1, MMU::ReadWrite));
current->heap_bitmap.initialize(bitmap_location, ARCH_PAGE_SIZE);
current->heap_bitmap.clear(false);
}
u64 index = TRY(Result<u64>::from_option(current->heap_bitmap.find_and_toggle(false), ENOMEM));
u64 address = USERSPACE_HEAP_BASE + (index * ARCH_PAGE_SIZE);
int mmu_flags = MMU::User | MMU::NoExecute;
if (flags & PROT_WRITE) mmu_flags |= MMU::ReadWrite;
if (flags & PROT_EXEC) mmu_flags &= ~MMU::NoExecute;
kdbgln("allocate_memory: allocating memory at %#lx", address);
return MemoryManager::alloc_at(address, 1, mmu_flags);
}
Result<u64> sys_deallocate_memory(Registers*, SyscallArgs args)
{
u64 address = (u64)args[0];
Thread* current = Scheduler::current();
if (!current->heap_bitmap.initialized()) return err(EFAULT);
u64 index = (address - USERSPACE_HEAP_BASE) / ARCH_PAGE_SIZE;
if (!current->heap_bitmap.get(index)) return err(EFAULT);
current->heap_bitmap.set(index, false);
kdbgln("deallocate_memory: deallocating memory at %#lx", address);
TRY(MemoryManager::unmap_owned(address, 1));
return { 0 };
}

View File

@ -4,6 +4,7 @@
#include "arch/CPU.h"
#include "arch/MMU.h"
#include "memory/MemoryManager.h"
#include <luna/Alignment.h>
#include <luna/ScopeGuard.h>
#include <luna/Stack.h>
@ -177,6 +178,11 @@ namespace Scheduler
if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->directory);
if (thread->heap_bitmap.initialized())
MemoryManager::unmap_owned_and_free_vm(
(u64)thread->heap_bitmap.location(),
get_blocks_from_size(thread->heap_bitmap.size_in_bytes(), ARCH_PAGE_SIZE));
delete thread;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "arch/MMU.h"
#include <luna/Bitmap.h>
#include <luna/LinkedList.h>
#include <luna/Result.h>
#include <luna/Stack.h>
@ -35,6 +36,8 @@ struct Thread : public LinkedListNode<Thread>
Stack stack;
Stack kernel_stack;
Bitmap heap_bitmap;
ThreadState state = ThreadState::Runnable;
bool is_kernel { true };

View File

@ -0,0 +1,11 @@
/* bits/mmap-flags.h: PROT_* constants for mmap(). */
#ifndef _BITS_MMAP_FLAGS_H
#define _BITS_MMAP_FLAGS_H
#define PROT_NONE 0
#define PROT_READ 1
#define PROT_WRITE 2
#define PROT_EXEC 4
#endif

View File

@ -1,6 +1,6 @@
#pragma once
#define enumerate_syscalls(_e) _e(exit) _e(console_write) _e(clock_gettime)
#define enumerate_syscalls(_e) _e(exit) _e(console_write) _e(clock_gettime) _e(allocate_memory) _e(deallocate_memory)
enum Syscalls
{