[kernel] Change VMA syscall addr param to inout

This change allows the `vma_map` and `vma_create_map` syscalls to map to
addresses other than the one specified, and therefore makes the address
parameter to those syscalls `inout` in order to return the mapped
address.

Also add the `exact` flag for specifying that mapping needs to be done
at the exact address given. If the mapping collides with another, the
new `j6_err_collision` error is returned.
This commit is contained in:
Justin C. Miller
2023-08-31 19:40:02 -07:00
parent 8cbde13139
commit fc16ed54b3
16 changed files with 93 additions and 69 deletions

View File

@@ -100,7 +100,7 @@ load_init_server(bootproto::program &program, uintptr_t modules_address)
((sect.type && section_flags::write) ? vm_flags::write : vm_flags::none);
obj::vm_area *vma = new obj::vm_area_fixed(sect.phys_addr, sect.size, flags);
space.add(sect.virt_addr, vma);
space.add(sect.virt_addr, vma, obj::vm_flags::exact);
}
uint64_t iopl = (3ull << 12);

View File

@@ -102,8 +102,8 @@ memory_initialize_pre_ctors(bootproto::args &kargs)
obj::vm_area *heap_map = new (&g_kernel_heapmap_area)
obj::vm_area_untracked(mem::heapmap_size, vm_flags::write);
vm.add(mem::heap_offset, heap);
vm.add(mem::heapmap_offset, heap_map);
vm.add(mem::heap_offset, heap, vm_flags::exact);
vm.add(mem::heapmap_offset, heap_map, vm_flags::exact);
new (&g_kernel_heap) heap_allocator {mem::heap_offset, mem::heap_size, mem::heapmap_offset};
@@ -111,7 +111,7 @@ memory_initialize_pre_ctors(bootproto::args &kargs)
size_t log_buffer_size = log::log_pages * arch::frame_size;
obj::vm_area *logs = new (&g_kernel_log_area)
obj::vm_area_ring(log_buffer_size, vm_flags::write);
vm.add(mem::logs_offset, logs);
vm.add(mem::logs_offset, logs, vm_flags::exact);
new (&g_logger) log::logger(
util::buffer::from(mem::logs_offset, log_buffer_size));
@@ -120,7 +120,7 @@ memory_initialize_pre_ctors(bootproto::args &kargs)
obj::vm_area *caps = new (&g_cap_table_area)
obj::vm_area_untracked(mem::caps_size, vm_flags::write);
vm.add(mem::caps_offset, caps);
vm.add(mem::caps_offset, caps, vm_flags::exact);
new (&g_cap_table) cap_table {mem::caps_offset};
@@ -129,7 +129,7 @@ memory_initialize_pre_ctors(bootproto::args &kargs)
mem::kernel_stack_pages,
mem::stacks_size,
vm_flags::write};
vm.add(mem::stacks_offset, &g_kernel_stacks);
vm.add(mem::stacks_offset, &g_kernel_stacks, vm_flags::exact);
// Clean out any remaning bootloader page table entries
for (unsigned i = 0; i < arch::kernel_root_index; ++i)
@@ -140,7 +140,7 @@ void
memory_initialize_post_ctors(bootproto::args &kargs)
{
vm_space &vm = vm_space::kernel_space();
vm.add(mem::buffers_offset, &g_kernel_buffers);
vm.add(mem::buffers_offset, &g_kernel_buffers, vm_flags::exact);
g_frame_allocator.free(
get_physical_page(kargs.page_tables.pointer),

View File

@@ -58,7 +58,7 @@ start(cpu_data &bsp, void *kpml4)
uintptr_t addr = 0x8000; // TODO: find a valid address, rewrite addresses
isr vector = static_cast<isr>(addr >> 12);
obj::vm_area *vma = new obj::vm_area_fixed(addr, 0x1000, vm_flags::write);
vm_space::kernel_space().add(addr, vma);
vm_space::kernel_space().add(addr, vma, obj::vm_flags::exact);
memcpy(
reinterpret_cast<void*>(addr),
reinterpret_cast<void*>(&ap_startup),

View File

@@ -23,7 +23,7 @@ vma_create(j6_handle_t *self, size_t size, uint32_t flags)
}
j6_status_t
vma_create_map(j6_handle_t *self, size_t size, uintptr_t base, uint32_t flags)
vma_create_map(j6_handle_t *self, size_t size, uintptr_t *base, uint32_t flags)
{
vm_area *a = nullptr;
vm_flags f = vm_flags::user_mask & flags;
@@ -32,16 +32,17 @@ vma_create_map(j6_handle_t *self, size_t size, uintptr_t base, uint32_t flags)
else
a = construct_handle<vm_area_open>(self, size, f);
process::current().space().add(base, a);
return j6_status_ok;
*base = process::current().space().add(*base, a, f);
return *base ? j6_status_ok : j6_err_collision;
}
j6_status_t
vma_map(vm_area *self, process *proc, uintptr_t base)
vma_map(vm_area *self, process *proc, uintptr_t *base, uint32_t flags)
{
vm_space &space = proc ? proc->space() : process::current().space();
space.add(base, self);
return j6_status_ok;
vm_flags f = vm_flags::user_mask & flags;
*base = space.add(*base, self, f);
return *base ? j6_status_ok : j6_err_collision;
}
j6_status_t

View File

@@ -57,7 +57,7 @@ vm_space::vm_space() :
sizeof(system_config),
vm_flags::none);
add(sysconf_user_address, sysc);
add(sysconf_user_address, sysc, vm_flags::exact);
}
vm_space::~vm_space()
@@ -80,14 +80,34 @@ vm_space::kernel_space()
return obj::process::kernel_process().space();
}
bool
vm_space::add(uintptr_t base, obj::vm_area *area)
uintptr_t
vm_space::add(uintptr_t base, obj::vm_area *area, obj::vm_flags flags)
{
//TODO: check for collisions
if (!base)
base = min_auto_address;
uintptr_t end = base + area->size();
//TODO: optimize find/insert
bool exact = util::bits::has(flags, j6_vm_flag_exact);
for (size_t i = 0; i < m_areas.count(); ++i) {
const vm_space::area &a = m_areas[i];
uintptr_t aend = a.base + a.area->size();
if (base >= aend)
continue;
if (end <= a.base)
break;
else if (exact)
return 0;
else
base = aend;
}
m_areas.sorted_insert({base, area});
area->add_to(this);
area->handle_retain();
return true;
return base;
}
void

View File

@@ -4,23 +4,27 @@
#include <stdint.h>
#include <j6/flags.h>
#include <util/enum_bitfields.h>
#include <util/spinlock.h>
#include <util/vector.h>
#include "objects/vm_area.h"
#include "page_table.h"
struct TCB;
namespace obj {
class process;
class vm_area;
}
/// Tracks a region of virtual memory address space
class vm_space
{
public:
/// Never map below this address unless explicitly asked.
static constexpr uintptr_t min_auto_address = 16 * 1024 * 1024; // 16 MiB
/// Constructor for the kernel address space
/// \arg pml4 The existing kernel PML4
vm_space(page_table *pml4);
@@ -33,8 +37,9 @@ public:
/// Add a virtual memorty area to this address space
/// \arg base The starting address of the area
/// \arg area The area to add
/// \returns True if the add succeeded
bool add(uintptr_t base, obj::vm_area *area);
/// \arg flags Flags for the operation (exact, clobber, etc)
/// \returns The base address the area was added at
uintptr_t add(uintptr_t base, obj::vm_area *area, obj::vm_flags flags);
/// Remove a virtual memory area from this address space
/// \arg area The area to remove