mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
[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:
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -56,7 +56,7 @@ channel::create(size_t size)
|
||||
channel_addr += size * 2; // account for ring buffer virtual space doubling
|
||||
lock.release();
|
||||
|
||||
result = j6_vma_create_map(&vma, size, addr, j6_vm_flag_write|j6_vm_flag_ring);
|
||||
result = j6_vma_create_map(&vma, size, &addr, j6_vm_flag_write|j6_vm_flag_ring);
|
||||
if (result != j6_status_ok) {
|
||||
syslog("Failed to create channel VMA. Error: %lx", result);
|
||||
return nullptr;
|
||||
@@ -77,7 +77,7 @@ channel::open(j6_handle_t vma)
|
||||
util::scoped_lock lock {addr_spinlock};
|
||||
uintptr_t addr = channel_addr;
|
||||
|
||||
result = j6_vma_map(vma, 0, addr);
|
||||
result = j6_vma_map(vma, 0, &addr, 0);
|
||||
if (result != j6_status_ok) {
|
||||
syslog("Failed to map channel VMA. Error: %lx", result);
|
||||
return nullptr;
|
||||
|
||||
@@ -24,4 +24,5 @@
|
||||
#define j6_err_insufficient j6_err(0x0005)
|
||||
#define j6_err_timed_out j6_err(0x0006)
|
||||
#define j6_err_denied j6_err(0x0007)
|
||||
#define j6_err_collision j6_err(0x0008)
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@ enum j6_vm_flags {
|
||||
enum j6_flags {
|
||||
j6_flag_block = 0x01,
|
||||
|
||||
j6_flags_COUNT // custom per-type flags should start here
|
||||
j6_flags_MAX // custom per-type flags should start here
|
||||
};
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
VM_FLAG( none, 0x00000000 )
|
||||
|
||||
VM_FLAG( write, 0x00000001 )
|
||||
VM_FLAG( exec, 0x00000002 )
|
||||
VM_FLAG( contiguous, 0x00000020 )
|
||||
VM_FLAG( large_pages, 0x00000100 )
|
||||
VM_FLAG( huge_pages, 0x00000200 )
|
||||
VM_FLAG( write_combine, 0x00001000 )
|
||||
VM_FLAG( ring, 0x00002000 )
|
||||
|
||||
VM_FLAG( mmio, 0x00010000 )
|
||||
VM_FLAG( contiguous, 0x00000010 )
|
||||
VM_FLAG( large_pages, 0x00000020 )
|
||||
VM_FLAG( huge_pages, 0x00000040 )
|
||||
|
||||
VM_FLAG( write_combine, 0x00000100 )
|
||||
|
||||
VM_FLAG( mmio, 0x00001000 )
|
||||
|
||||
VM_FLAG( exact, 0x00010000 )
|
||||
VM_FLAG( ring, 0x00020000 )
|
||||
@@ -19,22 +19,25 @@ template <typename Proc>
|
||||
class thread
|
||||
{
|
||||
public:
|
||||
static constexpr uintptr_t stack_base_start = 0x7f0'0000'0000;
|
||||
|
||||
/// Constructor. Create a thread and its stack space, but
|
||||
/// do not start executing the thread.
|
||||
/// \arg p The function where the thread will begin execution
|
||||
/// \arg stack_top The address where the top of this thread's stack should be mapped
|
||||
/// \arg stack_size Size of the stack, in bytes (default 64KiB)
|
||||
thread(Proc p, uintptr_t stack_top, size_t stack_size = 0x10000) :
|
||||
/// \arg stack_size Size of the stack, in bytes (default 16MiB)
|
||||
thread(Proc p, size_t stack_size = 0x100'0000) :
|
||||
m_stack {j6_handle_invalid},
|
||||
m_thread {j6_handle_invalid},
|
||||
m_stack_top {stack_top},
|
||||
m_proc {p}
|
||||
{
|
||||
uintptr_t stack_base = stack_top - stack_size;
|
||||
m_status = j6_vma_create_map(&m_stack, stack_size, stack_base, j6_vm_flag_write);
|
||||
uintptr_t stack_base = stack_base_start;
|
||||
m_status = j6_vma_create_map(&m_stack, stack_size, &stack_base, j6_vm_flag_write);
|
||||
if (m_status != j6_status_ok)
|
||||
return;
|
||||
|
||||
m_stack_top = stack_base + stack_size;
|
||||
|
||||
static constexpr size_t zeros_size = 0x10;
|
||||
m_stack_top -= zeros_size; // Sentinel
|
||||
memset(reinterpret_cast<void*>(m_stack_top), 0, zeros_size);
|
||||
|
||||
@@ -1,26 +1,17 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <j6/errors.h>
|
||||
#include <j6/syscalls.h>
|
||||
|
||||
namespace __j6libc {
|
||||
|
||||
using j6_status_t = uint64_t;
|
||||
using j6_handle_t = uint64_t;
|
||||
|
||||
constexpr j6_handle_t j6_handle_invalid = -1ull;
|
||||
constexpr j6_status_t j6_status_ok = 0;
|
||||
|
||||
static j6_handle_t core_handle = j6_handle_invalid;
|
||||
static intptr_t core_size = 0;
|
||||
|
||||
static const uintptr_t core_base = 0x1c0000000;
|
||||
static uintptr_t core_base = 0x1c0000000;
|
||||
|
||||
static const void *error_val = (void*)-1;
|
||||
|
||||
extern "C" {
|
||||
j6_status_t j6_vma_create_map(j6_handle_t *, size_t, uintptr_t, unsigned);
|
||||
j6_status_t j6_vma_resize(j6_handle_t, size_t *);
|
||||
}
|
||||
|
||||
void * increase_core(intptr_t i)
|
||||
{
|
||||
if (i == 0)
|
||||
@@ -30,7 +21,7 @@ void * increase_core(intptr_t i)
|
||||
if (i < 0)
|
||||
return (void*)-1;
|
||||
|
||||
j6_status_t result = j6_vma_create_map(&core_handle, i, core_base, 1);
|
||||
j6_status_t result = j6_vma_create_map(&core_handle, i, &core_base, 1);
|
||||
if (result != j6_status_ok)
|
||||
return (void*)-1;
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ main(int argc, const char **argv, const char **env)
|
||||
return s;
|
||||
}
|
||||
|
||||
s = j6_vma_map(fb_handle, 0, lfb_addr);
|
||||
s = j6_vma_map(fb_handle, 0, &lfb_addr, j6_vm_flag_exact);
|
||||
if (s != j6_status_ok) {
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
static uint64_t initfs_running = 1;
|
||||
static constexpr size_t buffer_size = 2048;
|
||||
static constexpr uintptr_t load_addr = 0xf00000000;
|
||||
|
||||
j6_status_t
|
||||
handle_load_request(j6romfs::fs &fs, const char *path, j6_handle_t &vma)
|
||||
@@ -21,7 +20,8 @@ handle_load_request(j6romfs::fs &fs, const char *path, j6_handle_t &vma)
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
j6_vma_create_map(&vma, in->size, load_addr, j6_vm_flag_write);
|
||||
uintptr_t load_addr = 0;
|
||||
j6_vma_create_map(&vma, in->size, &load_addr, j6_vm_flag_write);
|
||||
util::buffer dest = util::buffer::from(load_addr, in->size);
|
||||
fs.load_inode_data(in, dest);
|
||||
j6_vma_unmap(vma, 0);
|
||||
|
||||
@@ -16,10 +16,9 @@
|
||||
|
||||
using bootproto::module;
|
||||
|
||||
static uintptr_t load_addr = 0xf'000'0000;
|
||||
static constexpr size_t stack_size = 0x10000;
|
||||
static constexpr uintptr_t stack_top = 0x80000000000;
|
||||
static constexpr size_t MiB = 0x10'0000ull;
|
||||
static constexpr size_t stack_size = 16 * MiB;
|
||||
static constexpr uintptr_t stack_top = 0x7f0'0000'0000;
|
||||
|
||||
inline uintptr_t align_up(uintptr_t a) { return ((a-1) & ~(MiB-1)) + MiB; }
|
||||
|
||||
@@ -31,7 +30,7 @@ map_phys(j6_handle_t sys, uintptr_t phys, size_t len, j6_vm_flags flags)
|
||||
if (res != j6_status_ok)
|
||||
return j6_handle_invalid;
|
||||
|
||||
res = j6_vma_map(vma, 0, phys);
|
||||
res = j6_vma_map(vma, 0, &phys, j6_vm_flag_exact);
|
||||
if (res != j6_status_ok)
|
||||
return j6_handle_invalid;
|
||||
|
||||
@@ -72,8 +71,7 @@ load_program_into(j6_handle_t proc, elf::file &file, uintptr_t image_base, const
|
||||
if (seg.type != elf::segment_type::load)
|
||||
continue;
|
||||
|
||||
uintptr_t addr = load_addr;
|
||||
load_addr = align_up(load_addr + seg.mem_size);
|
||||
uintptr_t addr = 0;
|
||||
|
||||
// TODO: way to remap VMA as read-only if there's no write flag on
|
||||
// the segment
|
||||
@@ -86,7 +84,7 @@ load_program_into(j6_handle_t proc, elf::file &file, uintptr_t image_base, const
|
||||
size_t epilogue = seg.mem_size - seg.file_size;
|
||||
|
||||
j6_handle_t sub_vma = j6_handle_invalid;
|
||||
j6_status_t res = j6_vma_create_map(&sub_vma, seg.mem_size+prologue, addr, flags);
|
||||
j6_status_t res = j6_vma_create_map(&sub_vma, seg.mem_size+prologue, &addr, flags);
|
||||
if (res != j6_status_ok) {
|
||||
j6::syslog(" ** error loading ELF '%s': creating sub vma: %lx", path, res);
|
||||
return 0;
|
||||
@@ -102,9 +100,9 @@ load_program_into(j6_handle_t proc, elf::file &file, uintptr_t image_base, const
|
||||
if (eos > eop)
|
||||
eop = eos;
|
||||
|
||||
uintptr_t start_addr = (image_base + seg.vaddr);
|
||||
uintptr_t start_addr = (image_base + seg.vaddr) & ~0xfffull;
|
||||
j6::syslog("Mapping segment from %s at %012lx - %012lx", path, start_addr, start_addr+seg.mem_size);
|
||||
res = j6_vma_map(sub_vma, proc, start_addr & ~0xfffull);
|
||||
res = j6_vma_map(sub_vma, proc, &start_addr, j6_vm_flag_exact);
|
||||
if (res != j6_status_ok) {
|
||||
j6::syslog(" ** error loading ELF '%s': mapping sub vma to child: %lx", path, res);
|
||||
return 0;
|
||||
@@ -193,10 +191,9 @@ load_program(
|
||||
if (!eop)
|
||||
return false;
|
||||
|
||||
uintptr_t stack_addr = load_addr;
|
||||
load_addr = align_up(load_addr + stack_size);
|
||||
uintptr_t stack_addr = 0;
|
||||
j6_handle_t stack_vma = j6_handle_invalid;
|
||||
j6_status_t res = j6_vma_create_map(&stack_vma, stack_size, stack_addr, j6_vm_flag_write);
|
||||
j6_status_t res = j6_vma_create_map(&stack_vma, stack_size, &stack_addr, j6_vm_flag_write);
|
||||
if (res != j6_status_ok) {
|
||||
j6::syslog(" ** error loading program '%s': creating stack vma: %lx", path, res);
|
||||
return false;
|
||||
@@ -223,9 +220,8 @@ load_program(
|
||||
const elf::file_header *h = program_elf.header();
|
||||
loader_arg->image_base = program_image_base;
|
||||
loader_arg->phdr = h->ph_offset;
|
||||
loader_arg->phdr_size = h->ph_entsize;
|
||||
loader_arg->phdr_count = h->ph_num;
|
||||
loader_arg->entrypoint = program_elf.entrypoint();
|
||||
loader_arg->entrypoint = entrypoint;
|
||||
|
||||
j6_arg_handles *handles_arg = stack_push<j6_arg_handles>(stack, 2 * sizeof(j6_arg_handle_entry));
|
||||
handles_arg->nhandles = 1;
|
||||
@@ -258,7 +254,8 @@ load_program(
|
||||
}
|
||||
}
|
||||
|
||||
res = j6_vma_map(stack_vma, proc, stack_top-stack_size);
|
||||
uintptr_t stack_base = stack_top-stack_size;
|
||||
res = j6_vma_map(stack_vma, proc, &stack_base, j6_vm_flag_exact);
|
||||
if (res != j6_status_ok) {
|
||||
j6::syslog(" ** error loading program '%s': mapping stack vma: %lx", path, res);
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user